1 module epsilon.slaggen; 2 3 import core.time : MonoTime; 4 import EAG = epsilon.eag; 5 import epsilon.settings; 6 import io : Input, Position, read; 7 import log; 8 import runtime; 9 import std.algorithm; 10 import std.bitmanip : BitArray; 11 import std.stdio; 12 import std.typecons; 13 14 public const parsePass = 0; 15 public const onePass = 1; 16 public const sweepPass = 2; 17 public int[] NodeIdent; 18 public int[] Leaf; 19 public int[] AffixPlace; 20 public int[] AffixSpace; 21 22 private File output; 23 private bool SavePos; 24 private bool UseConst; 25 private bool UseRefCnt; 26 private bool TraversePass; 27 private int[] VarCnt; 28 private int[] VarAppls; 29 private bool Testing; 30 private bool Generating; 31 private BitArray PreparedHNonts; 32 private int[] VarDeps; 33 private int FirstHeap; 34 private int MaxMAlt; 35 private long RefConst; 36 private int[] AffixName; 37 private BitArray HNontDef; 38 private int[] HNontVars; 39 private int[] HNontFVars; 40 private bool[] RepAppls; 41 private int[] FormalName; 42 private int[] VarRefCnt; 43 private int[] VarDepPos; 44 private int[] VarName; 45 private int[] NodeName; 46 private int IfLevel; 47 private int[] ActualName; 48 private BitArray RepVar; 49 private BitArray EmptySet; 50 51 public void Test() 52 in (EAG.Performed(EAG.analysed | EAG.predicates)) 53 { 54 auto type = Type.slag; 55 56 info!"SLAG testing %s"(EAG.BaseName); 57 EAG.History &= ~EAG.isSLAG; 58 59 InitTest; 60 scope (exit) 61 FinitTest; 62 63 foreach (N; EAG.Prod.bitsSet) 64 if (EAG.HNont[N].Id >= 0) 65 type = min(type, TestHNont(N, Yes.checkSLAG)); 66 67 final switch (type) with (Type) 68 { 69 case neither: 70 info!"%s grammar is no LAG"(EAG.BaseName); 71 break; 72 case lag: 73 info!"%s grammar is no SLAG but LAG"(EAG.BaseName); 74 break; 75 case slag: 76 info!"%s grammar is SLAG"(EAG.BaseName); 77 EAG.History |= EAG.isSLAG; 78 break; 79 } 80 } 81 82 public void InitTest() nothrow 83 { 84 if (!Generating && !Testing) 85 PrepareInit; 86 Testing = true; 87 } 88 89 public void FinitTest() nothrow 90 { 91 if (!Generating) 92 PrepareFinit; 93 Testing = false; 94 } 95 96 public bool PredsOK() 97 { 98 return EAG.Pred.bitsSet 99 .map!(N => IsLAG(N)) 100 .all; 101 } 102 103 public bool IsLAG(size_t N) 104 { 105 return TestHNont(N) != Type.neither; 106 } 107 108 private Type TestHNont(size_t N, Flag!"checkSLAG" checkSLAG = No.checkSLAG) 109 in (EAG.Prod[N]) 110 { 111 auto type = Type.slag; 112 113 void CheckDefPos(EAG.ParamRecord param) 114 { 115 void DefPos(int Node) 116 { 117 if (Node < 0) 118 { 119 EAG.Var[-Node].Def = true; 120 } 121 else 122 { 123 foreach (n; 0 .. EAG.MAlt[EAG.NodeBuf[Node]].Arity) 124 DefPos(EAG.NodeBuf[Node + n + 1]); 125 } 126 } 127 128 if (param.isDef) 129 DefPos(param.Affixform); 130 } 131 132 void CheckApplPos(EAG.ParamRecord param) 133 { 134 void ApplPos(int Node) 135 { 136 if (Node < 0) 137 { 138 const V = -Node; 139 140 if (!EAG.Var[V].Def) 141 { 142 error!"not left-defining\n%s"(EAG.Var[V].Pos); 143 type = Type.neither; 144 } 145 } 146 else 147 { 148 foreach (n; 0 .. EAG.MAlt[EAG.NodeBuf[Node]].Arity) 149 ApplPos(EAG.NodeBuf[Node + n + 1]); 150 } 151 } 152 153 if (!param.isDef) 154 ApplPos(param.Affixform); 155 } 156 157 void CheckSLAGCond(EAG.ParamRecord param) 158 { 159 const Node = param.Affixform; 160 161 if (param.isDef) 162 { 163 if (Node >= 0) 164 { 165 error!"cannot analyze bottom up\n%s"(param.Pos); 166 type = min(type, Type.lag); 167 } 168 else if (EAG.Var[-Node].Def) 169 { 170 error!"cannot check for equality bottom up\n%s"(param.Pos); 171 type = min(type, Type.lag); 172 } 173 else if (EAG.Var[EAG.Var[-Node].Neg].Def) 174 { 175 error!"cannot check for inequality bottom up\n%s"(param.Pos); 176 type = min(type, Type.lag); 177 } 178 else if (VarAppls[-Node] > 1) 179 { 180 error!"cannot synthesize %s times bottom up\n%s"(VarAppls[-Node], param.Pos); 181 type = min(type, Type.lag); 182 } 183 } 184 } 185 186 Prepare(N); 187 188 EAG.Rule Node = EAG.HNont[N].Def; 189 190 if (auto rep = cast(EAG.Rep) Node) 191 { 192 InitScope(rep.Scope); 193 rep.Formal.params.each!(param => CheckDefPos(param)); 194 rep.Formal.params.each!(param => CheckApplPos(param)); 195 } 196 else if (auto opt = cast(EAG.Opt) Node) 197 { 198 InitScope(opt.Scope); 199 opt.Formal.params.each!(param => CheckDefPos(param)); 200 opt.Formal.params.each!(param => CheckApplPos(param)); 201 } 202 203 EAG.Alt A = Node.Sub; 204 205 do 206 { 207 InitScope(A.Scope); 208 A.Formal.params.each!(param => CheckDefPos(param)); 209 210 EAG.Factor F = A.Sub; 211 212 while (F !is null) 213 { 214 if (auto nont = cast(EAG.Nont) F) 215 { 216 nont.Actual.params.each!(param => CheckApplPos(param)); 217 if (checkSLAG && EAG.HNont[nont.Sym].anonymous) 218 type = min(type, TestHNont(nont.Sym, checkSLAG)); 219 nont.Actual.params.each!(param => CheckDefPos(param)); 220 } 221 F = F.Next; 222 } 223 if (cast(EAG.Rep) Node !is null) 224 { 225 A.Actual.params.each!(param => CheckApplPos(param)); 226 foreach (param; A.Actual.params) 227 { 228 if (checkSLAG) 229 CheckSLAGCond(param); 230 CheckDefPos(param); 231 } 232 } 233 A.Formal.params.each!(param => CheckApplPos(param)); 234 A = A.Next; 235 } 236 while (A !is null); 237 return type; 238 } 239 240 private enum Type 241 { 242 neither, 243 lag, 244 slag, 245 } 246 247 private void Prepare(size_t N) nothrow 248 { 249 void Traverse(EAG.ParamRecord[] params) 250 { 251 void DefPos(int Node) 252 { 253 if (Node < 0) 254 { 255 ++VarCnt[-Node]; 256 } 257 else 258 { 259 foreach (n; 0 .. EAG.MAlt[EAG.NodeBuf[Node]].Arity) 260 DefPos(EAG.NodeBuf[Node + n + 1]); 261 } 262 } 263 264 void ApplPos(int Node) 265 { 266 if (Node < 0) 267 { 268 ++VarCnt[-Node]; 269 ++VarAppls[-Node]; 270 } 271 else 272 { 273 foreach (n; 0 .. EAG.MAlt[EAG.NodeBuf[Node]].Arity) 274 ApplPos(EAG.NodeBuf[Node + n + 1]); 275 } 276 } 277 278 foreach (param; params) 279 if (param.isDef) 280 DefPos(param.Affixform); 281 else 282 ApplPos(param.Affixform); 283 } 284 285 void InitArray(EAG.ScopeDesc Scope) 286 { 287 foreach (i; Scope.Beg .. Scope.End) 288 { 289 VarCnt[i] = 0; 290 VarAppls[i] = 0; 291 } 292 } 293 294 if (!PreparedHNonts[N]) 295 { 296 EAG.Rule Node = EAG.HNont[N].Def; 297 298 if (auto rep = cast(EAG.Rep) Node) 299 { 300 InitArray(rep.Scope); 301 Traverse(rep.Formal.params); 302 } 303 else if (auto opt = cast(EAG.Opt) Node) 304 { 305 InitArray(opt.Scope); 306 Traverse(opt.Formal.params); 307 } 308 309 EAG.Alt A = Node.Sub; 310 311 do 312 { 313 InitArray(A.Scope); 314 Traverse(A.Formal.params); 315 316 EAG.Factor F = A.Sub; 317 318 while (F !is null) 319 { 320 if (auto nont = cast(EAG.Nont) F) 321 Traverse(nont.Actual.params); 322 F = F.Next; 323 } 324 if (cast(EAG.Rep) Node !is null) 325 { 326 Traverse(A.Actual.params); 327 foreach (param; A.Actual.params) 328 if (param.isDef && param.Affixform < 0) 329 RepVar[-param.Affixform] = true; 330 } 331 A = A.Next; 332 } 333 while (A !is null); 334 PreparedHNonts[N] = true; 335 } 336 } 337 338 public void InitGen(File MOut, int Treatment, Settings settings) 339 { 340 void SetFlags(int Treatment) 341 { 342 switch (Treatment) 343 { 344 case parsePass: 345 SavePos = true; 346 UseConst = false; 347 UseRefCnt = false; 348 break; 349 case onePass: 350 break; 351 case sweepPass: 352 TraversePass = true; 353 break; 354 default: 355 assert(0); 356 } 357 } 358 359 if (Generating) 360 trace!"resetting SLAG"; 361 output = MOut; 362 SavePos = false; 363 TraversePass = false; 364 UseConst = !settings.c; 365 UseRefCnt = !settings.r; 366 SetFlags(Treatment); 367 info!"%s %s"(UseRefCnt ? "+rc" : "-rc", UseConst ? "+ct" : "-ct"); 368 if (!Testing) 369 PrepareInit; 370 ComputeNodeIdent; 371 ComputeConstDat; 372 AffixName = new int[EAG.NextParam]; 373 foreach (i; EAG.firstParam .. EAG.NextParam) 374 AffixName[i] = -1; 375 NodeName = new int[EAG.NextNode]; 376 VarName = new int[EAG.NextVar]; 377 VarDeps = new int[EAG.NextVar]; 378 VarRefCnt = new int[EAG.NextVar]; 379 VarDepPos = new int[EAG.NextVar]; 380 foreach (i; EAG.firstVar .. EAG.NextVar) 381 { 382 VarRefCnt[i] = 0; 383 VarDepPos[i] = -1; 384 VarName[i] = -1; 385 } 386 ActualName = new int[EAG.NextDom]; 387 FormalName = new int[EAG.NextDom]; 388 foreach (i; EAG.firstDom .. EAG.NextDom) 389 { 390 ActualName[i] = -1; 391 FormalName[i] = -1; 392 } 393 HNontVars = new int[EAG.NextHNont]; 394 HNontFVars = new int[EAG.NextHNont]; 395 HNontDef = BitArray(); 396 HNontDef.length = EAG.NextHNont + 1; 397 RepAppls = new bool[EAG.NextHNont]; 398 foreach (i; EAG.firstHNont .. EAG.NextHNont) 399 RepAppls[i] = true; 400 EmptySet = BitArray(); 401 EmptySet.length = EAG.NextVar + 1; 402 Generating = true; 403 } 404 405 private void PrepareInit() nothrow 406 { 407 VarCnt = new int[EAG.NextVar]; 408 VarAppls = new int[EAG.NextVar]; 409 RepVar = BitArray(); 410 RepVar.length = EAG.NextVar + 1; 411 PreparedHNonts = BitArray(); 412 PreparedHNonts.length = EAG.NextHNont + 1; 413 } 414 415 private void ComputeNodeIdent() nothrow @safe 416 { 417 int i; 418 419 NodeIdent = new int[EAG.NextMAlt]; 420 foreach (A; EAG.firstMAlt .. EAG.NextMAlt) 421 NodeIdent[A] = -1; 422 MaxMAlt = 0; 423 foreach (N; EAG.firstMNont .. EAG.NextMNont) 424 { 425 int A = EAG.MNont[N].MRule; 426 427 i = 0; 428 while (A != EAG.nil) 429 { 430 ++i; 431 NodeIdent[A] = i; 432 A = EAG.MAlt[A].Next; 433 } 434 if (i > MaxMAlt) 435 MaxMAlt = i; 436 } 437 i = 1; 438 while (i <= MaxMAlt) 439 i = i * 2; 440 MaxMAlt = i; 441 RefConst = 0; 442 foreach (A; EAG.firstMAlt .. EAG.NextMAlt) 443 { 444 assert(NodeIdent[A] >= 0); 445 446 NodeIdent[A] = NodeIdent[A] + EAG.MAlt[A].Arity * MaxMAlt; 447 if (RefConst < NodeIdent[A]) 448 RefConst = NodeIdent[A]; 449 } 450 i = 1; 451 while (i <= RefConst) 452 i = i * 2; 453 RefConst = i; 454 } 455 456 private void ComputeConstDat() nothrow 457 { 458 void Traverse(size_t N, ref int ConstPtr) 459 { 460 void CheckParams(int P, ref int ConstPtr) 461 { 462 bool isConst; 463 464 void TraverseTree(int Node, ref int Next) 465 { 466 if (Node < 0) 467 { 468 isConst = false; 469 } 470 else 471 { 472 const Arity = EAG.MAlt[EAG.NodeBuf[Node]].Arity; 473 474 if (!UseConst || Arity != 0) 475 Next += 1 + Arity; 476 foreach (n; 0 .. Arity) 477 TraverseTree(EAG.NodeBuf[Node + n + 1], Next); 478 } 479 } 480 481 while (EAG.ParamBuf[P].Affixform != EAG.nil) 482 { 483 const Tree = EAG.ParamBuf[P].Affixform; 484 485 isConst = true; 486 TraverseTree(Tree, AffixSpace[P]); 487 if (Tree > 0 && EAG.MAlt[EAG.NodeBuf[Tree]].Arity == 0) 488 { 489 if (isConst) 490 AffixPlace[P] = Leaf[EAG.NodeBuf[Tree]]; 491 } 492 else 493 { 494 if (isConst) 495 { 496 AffixPlace[P] = ConstPtr; 497 ConstPtr += AffixSpace[P]; 498 } 499 } 500 ++P; 501 } 502 } 503 504 EAG.Rule Node = EAG.HNont[N].Def; 505 506 if (auto rep = cast(EAG.Rep) Node) 507 CheckParams(rep.Formal.Params, ConstPtr); 508 else if (auto opt = cast(EAG.Opt) Node) 509 CheckParams(opt.Formal.Params, ConstPtr); 510 511 EAG.Alt A = Node.Sub; 512 513 do 514 { 515 CheckParams(A.Formal.Params, ConstPtr); 516 517 EAG.Factor F = A.Sub; 518 519 while (F !is null) 520 { 521 if (auto nont = cast(EAG.Nont) F) 522 CheckParams(nont.Actual.Params, ConstPtr); 523 F = F.Next; 524 } 525 if (cast(EAG.Rep) Node) 526 CheckParams(A.Actual.Params, ConstPtr); 527 A = A.Next; 528 } 529 while (A !is null); 530 } 531 532 AffixSpace = new int[EAG.NextParam]; 533 AffixPlace = new int[EAG.NextParam]; 534 foreach (i; EAG.firstParam .. EAG.NextParam) 535 { 536 AffixSpace[i] = 0; 537 AffixPlace[i] = -1; 538 } 539 Leaf = new int[EAG.NextMAlt]; 540 541 int ConstPtr = EAG.MaxMArity + 1; 542 543 FirstHeap = ConstPtr; 544 foreach (A; EAG.firstMAlt .. EAG.NextMAlt) 545 { 546 if (EAG.MAlt[A].Arity == 0) 547 { 548 Leaf[A] = ConstPtr; 549 ++ConstPtr; 550 } 551 else 552 { 553 Leaf[A] = -1; 554 } 555 } 556 foreach (i; EAG.Prod.bitsSet) 557 Traverse(i, ConstPtr); 558 if (UseConst) 559 FirstHeap = ConstPtr; 560 } 561 562 public void FinitGen() 563 { 564 if (!Testing) 565 PrepareFinit; 566 EmptySet.length = 0; 567 NodeIdent = null; 568 AffixSpace = null; 569 AffixPlace = null; 570 Leaf = null; 571 AffixName = null; 572 NodeName = null; 573 VarName = null; 574 VarDeps = null; 575 VarRefCnt = null; 576 VarDepPos = null; 577 ActualName = null; 578 FormalName = null; 579 HNontVars = null; 580 HNontFVars = null; 581 RepAppls = null; 582 Generating = false; 583 } 584 585 private void PrepareFinit() nothrow 586 { 587 VarCnt = null; 588 VarAppls = null; 589 RepVar.length = 0; 590 PreparedHNonts.length = 0; 591 } 592 593 public void GenRepStart(int Sym) @safe 594 { 595 if (!UseRefCnt) 596 { 597 import std.conv : to; 598 599 const Next = (cast(EAG.Rep) EAG.HNont[Sym].Def).Sub.Formal.params 600 .count!(param => !param.isDef) 601 .to!int; 602 603 GenOverflowGuard(Next); 604 } 605 606 int Dom = EAG.HNont[Sym].Sig; 607 int P = (cast(EAG.Rep) EAG.HNont[Sym].Def).Sub.Formal.Params; 608 609 while (EAG.DomBuf[Dom] != EAG.nil) 610 { 611 if (!EAG.ParamBuf[P].isDef) 612 { 613 if (UseRefCnt) 614 { 615 output.write("GetHeap(0, "); 616 GenVar(FormalName[Dom]); 617 output.write("); "); 618 } 619 else 620 { 621 GenVar(FormalName[Dom]); 622 output.write(" = NextHeap; ++NextHeap; "); 623 } 624 GenVar(AffixName[P]); 625 output.write(" = "); 626 GenVar(FormalName[Dom]); 627 output.writeln(";"); 628 } 629 ++P; 630 ++Dom; 631 } 632 } 633 634 public void GenDeclarations(Settings settings) 635 { 636 Input Fix; 637 638 void InclFix(char Term) 639 { 640 import std.conv : to; 641 import std.exception : enforce; 642 643 char c = Fix.front.to!char; 644 645 while (c != Term) 646 { 647 enforce(c != 0, 648 "error: unexpected end of eSLAGGen.fix.d"); 649 650 output.write(c); 651 Fix.popFront; 652 c = Fix.front.to!char; 653 } 654 Fix.popFront; 655 } 656 657 void SkipFix(char Term) 658 { 659 import std.conv : to; 660 import std.exception : enforce; 661 662 char c = Fix.front.to!char; 663 664 while (c != Term) 665 { 666 enforce(c != 0, 667 "error: unexpected end of eSLAGGen.fix.d"); 668 669 Fix.popFront; 670 c = Fix.front.to!char; 671 } 672 Fix.popFront; 673 } 674 675 void GenTabFile(string name, long TabTimeStamp) 676 { 677 const errVal = 0; 678 const magic = 1_818_326_597; 679 int[] Heap; 680 681 void SynTree(int Node, ref int Next) 682 { 683 const Next1 = Next; 684 685 Heap[Next] = NodeIdent[EAG.NodeBuf[Node]]; 686 Next += 1 + EAG.MAlt[EAG.NodeBuf[Node]].Arity; 687 foreach (n; 0 .. EAG.MAlt[EAG.NodeBuf[Node]].Arity) 688 { 689 const Node1 = EAG.NodeBuf[Node + n + 1]; 690 691 if (EAG.MAlt[EAG.NodeBuf[Node1]].Arity == 0) 692 { 693 Heap[Next1 + n + 1] = Leaf[EAG.NodeBuf[Node1]]; 694 } 695 else 696 { 697 Heap[Next1 + n + 1] = Next; 698 SynTree(Node1, Next); 699 } 700 } 701 } 702 703 File Tab = File(settings.path(name), "w"); 704 705 Tab.writefln!"long %s"(magic); 706 Tab.writefln!"long %s"(TabTimeStamp); 707 Tab.writefln!"long %s"(FirstHeap - 1); 708 Heap = new int[FirstHeap]; 709 Heap[errVal] = 0; 710 foreach (i; 0 .. EAG.MaxMArity) 711 Heap[i + 1] = errVal; 712 if (UseConst) 713 { 714 foreach (i; EAG.firstMAlt .. EAG.NextMAlt) 715 { 716 if (Leaf[i] >= errVal) 717 Heap[Leaf[i]] = NodeIdent[i]; 718 } 719 foreach (P; EAG.firstParam .. EAG.NextParam) 720 { 721 if (EAG.ParamBuf[P].Affixform != EAG.nil && AffixPlace[P] >= 0) 722 { 723 int Next = AffixPlace[P]; 724 725 SynTree(EAG.ParamBuf[P].Affixform, Next); 726 } 727 } 728 } 729 foreach (i; 0 .. FirstHeap) 730 Tab.writefln!"long %s"(Heap[i]); 731 Tab.writefln!"long %s"(TabTimeStamp); 732 } 733 734 enum fixName = "slaggen.fix.d"; 735 const name = EAG.BaseName ~ (TraversePass ? "Eval.EvalTab" : ".EvalTab"); 736 const TabTimeStamp = MonoTime.currTime.ticks; 737 738 Fix = Input(fixName, import(fixName)); 739 InclFix('$'); 740 output.write(FirstHeap - 1); 741 InclFix('$'); 742 output.write(MaxMAlt); 743 InclFix('$'); 744 if (SavePos) 745 output.write("Eval.TreeType"); 746 else 747 output.write("long"); 748 InclFix('$'); 749 if (SavePos) 750 output.write("Eval.TreeType[]"); 751 else 752 output.write("HeapType[]"); 753 InclFix('$'); 754 if (SavePos) 755 InclFix('$'); 756 else 757 SkipFix('$'); 758 InclFix('$'); 759 output.write(EAG.MaxMArity + 1); 760 InclFix('$'); 761 output.write(RefConst); 762 InclFix('$'); 763 if (SavePos) 764 { 765 SkipFix('$'); 766 InclFix('$'); 767 } 768 else 769 { 770 InclFix('$'); 771 SkipFix('$'); 772 } 773 if (UseRefCnt) 774 { 775 InclFix('$'); 776 SkipFix('$'); 777 } 778 else 779 { 780 SkipFix('$'); 781 InclFix('$'); 782 } 783 InclFix('$'); 784 if (!TraversePass) 785 output.write("S."); 786 InclFix('$'); 787 if (UseRefCnt) 788 InclFix('$'); 789 else 790 SkipFix('$'); 791 InclFix('$'); 792 output.write(name); 793 InclFix('$'); 794 output.write(TabTimeStamp); 795 InclFix('$'); 796 if (SavePos) 797 InclFix('$'); 798 else 799 SkipFix('$'); 800 InclFix('$'); 801 GenTabFile(name, TabTimeStamp); 802 } 803 804 public bool PosNeeded(int P) @nogc nothrow @safe 805 { 806 while (EAG.ParamBuf[P].Affixform != EAG.nil) 807 { 808 if (EAG.ParamBuf[P].isDef) 809 { 810 const V = -EAG.ParamBuf[P].Affixform; 811 812 if (V < 0) 813 return true; 814 else if (EAG.Var[V].Def) 815 return true; 816 else if (EAG.Var[EAG.Var[V].Neg].Def) 817 return true; 818 } 819 ++P; 820 } 821 return false; 822 } 823 824 public void GenRepAlt(int Sym, EAG.Alt A) 825 { 826 int P; 827 int P1; 828 int Dom; 829 const Guard = !RepAppls[Sym]; 830 831 GenSynPred(Sym, A.Actual.Params); 832 if (SavePos) 833 output.writeln("PushPos;"); 834 P = A.Actual.Params; 835 Dom = EAG.HNont[Sym].Sig; 836 while (EAG.ParamBuf[P].Affixform != EAG.nil) 837 { 838 if (!EAG.ParamBuf[P].isDef && AffixName[P] != FormalName[Dom]) 839 { 840 GenVar(FormalName[Dom]); 841 output.write(" = "); 842 GenVar(AffixName[P]); 843 output.writeln(";"); 844 } 845 ++P; 846 ++Dom; 847 } 848 P1 = A.Actual.Params; 849 Dom = EAG.HNont[Sym].Sig; 850 P = A.Formal.Params; 851 if (!UseRefCnt) 852 GetAffixSpace(P); 853 GenHangIn(P, Guard); 854 855 int Next = 0; 856 857 while (EAG.ParamBuf[P].Affixform != EAG.nil) 858 { 859 if (!EAG.ParamBuf[P].isDef) 860 { 861 const Tree = EAG.ParamBuf[P].Affixform; 862 863 if (SavePos) 864 output.writeln("PopPos(", EAG.MAlt[EAG.NodeBuf[Tree]].Arity, ");"); 865 if (Tree > 0 && !(UseConst && AffixPlace[P] >= 0)) 866 { 867 if (Guard) 868 { 869 output.write("if ("); 870 GenVar(NodeName[Tree]); 871 output.writeln(" != undef)"); 872 output.writeln("{"); 873 } 874 if (UseRefCnt) 875 Gen1SynTree(Tree, RepVar, EAG.Pred[Sym]); 876 else 877 GenSynTree(Tree, RepVar, Next); 878 output.writeln; 879 if (Guard) 880 output.writeln("}"); 881 } 882 if (Guard && VarAppls[-EAG.ParamBuf[P1].Affixform] == 0) 883 { 884 GenVar(AffixName[P1]); 885 output.writeln(" = undef;"); 886 } 887 } 888 ++P; 889 ++P1; 890 ++Dom; 891 } 892 if (!UseRefCnt) 893 GenHeapInc(Next); 894 } 895 896 public void GenRepEnd(int Sym) 897 { 898 const Guard = false; // TODO: eliminate dead code? 899 900 InitScope((cast(EAG.Rep) EAG.HNont[Sym].Def).Scope); 901 902 int P = (cast(EAG.Rep) EAG.HNont[Sym].Def).Formal.Params; 903 int P1 = EAG.HNont[Sym].Def.Sub.Actual.Params; 904 int Dom = EAG.HNont[Sym].Sig; 905 int Next = 0; 906 907 GenAnalPred(Sym, P); 908 if (!UseRefCnt) 909 GetAffixSpace(P); 910 GenHangIn(P, Guard); 911 while (EAG.ParamBuf[P].Affixform != EAG.nil) 912 { 913 if (!EAG.ParamBuf[P].isDef) 914 { 915 const Tree = EAG.ParamBuf[P].Affixform; 916 917 if (SavePos) 918 output.writeln("PopPos(", EAG.MAlt[EAG.NodeBuf[Tree]].Arity, ");"); 919 if (Tree > 0 && !(UseConst && AffixPlace[P] >= 0)) 920 { 921 if (Guard) 922 { 923 output.write("if ("); 924 GenVar(NodeName[Tree]); 925 output.writeln(" != undef)"); 926 output.writeln("{"); 927 } 928 if (UseRefCnt) 929 Gen1SynTree(Tree, EmptySet, EAG.Pred[Sym]); 930 else 931 GenSynTree(Tree, EmptySet, Next); 932 output.writeln(""); 933 if (Guard) 934 output.writeln("}"); 935 } 936 if (UseRefCnt) 937 { 938 GenVar(AffixName[P]); 939 output.write(" = "); 940 GenVar(FormalName[Dom]); 941 output.write("; "); 942 } 943 GenVar(FormalName[Dom]); 944 output.write(" = "); 945 GenHeap(FormalName[Dom], 0); 946 output.writeln(";"); 947 if (UseRefCnt) 948 { 949 GenHeap(AffixName[P], 0); 950 output.writeln(" = 0;"); 951 output.write("FreeHeap("); 952 GenVar(AffixName[P]); 953 output.writeln(");"); 954 } 955 } 956 ++P; 957 ++P1; 958 ++Dom; 959 } 960 if (!UseRefCnt) 961 GenHeapInc(Next); 962 } 963 964 private void GenHangIn(int P, bool Guard) 965 { 966 void FreeVariables(int Node) 967 { 968 if (Node < 0) 969 { 970 if (!RepVar[-Node]) 971 { 972 output.write("FreeHeap("); 973 GenVar(VarName[-Node]); 974 output.write("); "); 975 } 976 } 977 else 978 { 979 foreach (n; 0 .. EAG.MAlt[EAG.NodeBuf[Node]].Arity) 980 FreeVariables(EAG.NodeBuf[Node + n + 1]); 981 } 982 } 983 984 int Next = 0; 985 986 while (EAG.ParamBuf[P].Affixform != EAG.nil) 987 { 988 if (!EAG.ParamBuf[P].isDef) 989 { 990 const Tree = EAG.ParamBuf[P].Affixform; 991 if (Guard) 992 { 993 output.write("if ("); 994 GenVar(AffixName[P]); 995 output.writeln(" != undef)"); 996 output.writeln("{"); 997 } 998 if (UseConst && AffixPlace[P] >= 0) 999 { 1000 GenHeap(AffixName[P], 0); 1001 output.writeln(" = ", AffixPlace[P], ";"); 1002 if (UseRefCnt) 1003 GenIncRefCnt(-AffixPlace[P], 1); 1004 } 1005 else if (Tree < 0) 1006 { 1007 if (AffixName[P] != VarName[-Tree]) 1008 { 1009 GenHeap(AffixName[P], 0); 1010 output.write(" = "); 1011 GenVar(VarName[-Tree]); 1012 output.writeln(";"); 1013 if (Guard) 1014 { 1015 output.writeln("}"); 1016 output.writeln("else"); 1017 output.writeln("{"); 1018 output.write("FreeHeap("); 1019 GenVar(VarName[-Tree]); 1020 output.writeln(");"); 1021 } 1022 } 1023 } 1024 else 1025 { 1026 if (UseRefCnt) 1027 { 1028 output.write("GetHeap(", EAG.MAlt[EAG.NodeBuf[Tree]].Arity, ", "); 1029 GenVar(NodeName[Tree]); 1030 output.write("); "); 1031 GenHeap(AffixName[P], 0); 1032 output.write(" = "); 1033 GenVar(NodeName[Tree]); 1034 output.writeln(";"); 1035 if (Guard) 1036 { 1037 output.writeln("}"); 1038 output.writeln("else"); 1039 output.writeln("{"); 1040 FreeVariables(Tree); 1041 } 1042 } 1043 else 1044 { 1045 GenHeap(AffixName[P], 0); 1046 output.write(" = NextHeap"); 1047 if (Next != 0) 1048 output.write(" + ", Next); 1049 output.writeln(";"); 1050 Next += AffixSpace[P]; 1051 if (Guard) 1052 { 1053 output.writeln("}"); 1054 output.writeln("else"); 1055 output.writeln("{"); 1056 } 1057 } 1058 if (Guard) 1059 { 1060 GenVar(NodeName[Tree]); 1061 output.writeln(" = undef;"); 1062 } 1063 } 1064 if (Guard) 1065 output.writeln("}"); 1066 } 1067 ++P; 1068 } 1069 } 1070 1071 public void GenPredProcs() 1072 { 1073 void GenPredCover(size_t N) 1074 in (EAG.Pred[N]) 1075 { 1076 output.write("void Check", N, "(string ErrMsg"); 1077 GenFormalParams(N, No.parNeeded); 1078 output.writeln(")"); 1079 output.writeln("{"); 1080 output.write("if (!Pred", N, "("); 1081 1082 int Dom = EAG.HNont[N].Sig; 1083 int i = 1; 1084 1085 if (EAG.DomBuf[Dom] != EAG.nil) 1086 { 1087 while (true) 1088 { 1089 GenVar(i); 1090 ++Dom; 1091 ++i; 1092 if (EAG.DomBuf[Dom] == EAG.nil) 1093 break; 1094 output.write(", "); 1095 } 1096 } 1097 output.writeln("))"); 1098 output.writeln("{"); 1099 Dom = EAG.HNont[N].Sig; 1100 i = 1; 1101 while (EAG.DomBuf[Dom] > 0) 1102 ++Dom; 1103 if (EAG.DomBuf[Dom] != EAG.nil) 1104 { 1105 output.write("if ("); 1106 while (true) 1107 { 1108 GenVar(i); 1109 output.write(" != errVal"); 1110 do 1111 { 1112 ++Dom; 1113 ++i; 1114 } 1115 while (!(EAG.DomBuf[Dom] <= 0)); 1116 if (EAG.DomBuf[Dom] == EAG.nil) 1117 break; 1118 output.write(" && "); 1119 } 1120 output.writeln(")"); 1121 output.writeln("PredError(ErrMsg);"); 1122 } 1123 else 1124 { 1125 output.write("Error(ErrMsg);"); 1126 } 1127 output.writeln("}"); 1128 output.writeln("}"); 1129 output.writeln; 1130 } 1131 1132 void GenPredicateCode(size_t N) 1133 { 1134 EAG.Rule Node = EAG.HNont[N].Def; 1135 EAG.Alt A; 1136 1137 void CleanLevel(int Level) 1138 { 1139 if (Level >= 1) 1140 { 1141 foreach (i; 0 .. Level) 1142 output.write("} "); 1143 output.writeln; 1144 } 1145 } 1146 1147 void FreeParamTrees(int P) 1148 { 1149 while (EAG.ParamBuf[P].Affixform != EAG.nil) 1150 { 1151 if (EAG.ParamBuf[P].isDef) 1152 GenFreeHeap(AffixName[P]); 1153 ++P; 1154 } 1155 } 1156 1157 void TraverseFactor(EAG.Factor F, int FormalParams) 1158 { 1159 if (F !is null) 1160 { 1161 auto nont = cast(EAG.Nont) F; 1162 1163 assert(nont !is null); 1164 assert(EAG.Pred[nont.Sym]); 1165 1166 GenSynPred(N, nont.Actual.Params); 1167 output.write("if (Pred", nont.Sym); 1168 GenActualParams(nont.Actual.Params, true); 1169 output.writeln(") // ", EAG.HNontRepr(nont.Sym)); 1170 output.writeln("{"); 1171 GenAnalPred(N, nont.Actual.Params); 1172 1173 const Level = IfLevel; 1174 1175 TraverseFactor(F.Next, FormalParams); 1176 CleanLevel(Level); 1177 output.writeln("}"); 1178 if (UseRefCnt) 1179 FreeParamTrees(nont.Actual.Params); 1180 } 1181 else 1182 { 1183 if (cast(EAG.Rep) Node) 1184 { 1185 GenSynPred(N, A.Actual.Params); 1186 output.write("if (Pred", N); 1187 GenActualParams(A.Actual.Params, true); 1188 output.writeln(") // ", EAG.HNontRepr(N)); 1189 output.writeln("{"); 1190 GenAnalPred(N, A.Actual.Params); 1191 1192 const Level = IfLevel; 1193 1194 GenSynPred(N, FormalParams); 1195 output.writeln("Failed = false;"); 1196 CleanLevel(Level); 1197 output.writeln("}"); 1198 if (UseRefCnt) 1199 FreeParamTrees(A.Actual.Params); 1200 } 1201 else 1202 { 1203 GenSynPred(N, FormalParams); 1204 output.writeln("Failed = false;"); 1205 } 1206 } 1207 } 1208 1209 int AltLevel = 0; 1210 int P; 1211 1212 output.writeln("Failed = true;"); 1213 if (cast(EAG.Rep) Node || cast(EAG.Opt) Node) 1214 { 1215 EAG.ScopeDesc Scope; 1216 1217 if (auto opt = cast(EAG.Opt) Node) 1218 { 1219 P = opt.Formal.Params; 1220 Scope = opt.Scope; 1221 } 1222 else if (auto rep = cast(EAG.Rep) Node) 1223 { 1224 P = rep.Formal.Params; 1225 Scope = rep.Scope; 1226 } 1227 InitScope(Scope); 1228 GenAnalPred(N, P); 1229 1230 const Level = IfLevel; 1231 1232 GenSynPred(N, P); 1233 output.writeln("Failed = false;"); 1234 CleanLevel(Level); 1235 ++AltLevel; 1236 } 1237 A = Node.Sub; 1238 while (true) 1239 { 1240 if (AltLevel > 0) 1241 { 1242 output.writeln("if (Failed) // alternative #", AltLevel + 1); 1243 output.writeln("{"); 1244 } 1245 InitScope(A.Scope); 1246 GenAnalPred(N, A.Formal.Params); 1247 1248 const Level = IfLevel; 1249 1250 TraverseFactor(A.Sub, A.Formal.Params); 1251 CleanLevel(Level); 1252 ++AltLevel; 1253 A = A.Next; 1254 if (A is null) 1255 { 1256 break; 1257 } 1258 } 1259 foreach (i; 1 .. AltLevel) 1260 output.write("} "); 1261 output.writeln; 1262 P = Node.Sub.Formal.Params; 1263 if (UseRefCnt) 1264 FreeParamTrees(P); 1265 output.writeln("if (Failed)"); 1266 output.writeln("{"); 1267 while (EAG.ParamBuf[P].Affixform != EAG.nil) 1268 { 1269 if (!EAG.ParamBuf[P].isDef) 1270 { 1271 GenVar(AffixName[P]); 1272 output.writeln(" = errVal;"); 1273 if (UseRefCnt) 1274 output.writeln("Heap[errVal] += refConst;"); 1275 } 1276 ++P; 1277 } 1278 output.writeln("}"); 1279 } 1280 1281 foreach (N; EAG.Pred.bitsSet) 1282 GenPredCover(N); 1283 foreach (N; EAG.Pred.bitsSet) 1284 { 1285 ComputeVarNames(N, No.embed); 1286 output.write("bool Pred", N); 1287 GenFormalParams(N, Yes.parNeeded); 1288 output.writeln(" // ", EAG.HNontRepr(N)); 1289 output.writeln("{"); 1290 GenVarDecl(N); 1291 GenPredicateCode(N); 1292 output.writeln("return !Failed;"); 1293 output.writeln("}"); 1294 output.writeln; 1295 } 1296 } 1297 1298 public void ComputeVarNames(size_t N, Flag!"embed" embed) 1299 in (EAG.Prod[N]) 1300 in (!HNontDef[N]) 1301 { 1302 int[] FreeVar; 1303 int[] RefCnt; 1304 int Top; 1305 int NextFreeVar; 1306 1307 void VarExpand() 1308 { 1309 if (NextFreeVar >= RefCnt.length) 1310 { 1311 auto Int = new int[2 * RefCnt.length]; 1312 1313 foreach (i; 0 .. NextFreeVar) 1314 Int[i] = RefCnt[i]; 1315 foreach (i; NextFreeVar .. Int.length) 1316 Int[i] = 0; 1317 RefCnt = Int; 1318 } 1319 if (Top >= FreeVar.length) 1320 { 1321 auto Int = new int[2 * FreeVar.length]; 1322 1323 foreach (i; 0 .. Top) 1324 Int[i] = FreeVar[i]; 1325 FreeVar = Int; 1326 } 1327 } 1328 1329 int GetFreeVar() 1330 { 1331 int Var; 1332 1333 if (Top > 0) 1334 { 1335 --Top; 1336 Var = FreeVar[Top]; 1337 } 1338 else 1339 { 1340 ++NextFreeVar; 1341 if (NextFreeVar >= RefCnt.length) 1342 VarExpand; 1343 RefCnt[NextFreeVar] = 0; 1344 Var = NextFreeVar; 1345 } 1346 trace!"RC: -%s"(Var); 1347 return Var; 1348 } 1349 1350 void Dispose(int Var) 1351 { 1352 --RefCnt[Var]; 1353 if (RefCnt[Var] == 0) 1354 { 1355 trace!"RC: +%s"(Var); 1356 FreeVar[Top] = Var; 1357 ++Top; 1358 if (Top >= FreeVar.length) 1359 VarExpand; 1360 } 1361 } 1362 1363 void Traverse(size_t N) 1364 { 1365 EAG.Rule Node; 1366 EAG.Alt A; 1367 EAG.Factor F; 1368 int P; 1369 int Tree; 1370 bool isPred; 1371 1372 void CheckDefPos(int P) 1373 { 1374 void DefPos(int Node, int Var) 1375 { 1376 if (Node < 0) 1377 { 1378 const V = -Node; 1379 1380 if (!EAG.Var[V].Def) 1381 { 1382 EAG.Var[V].Def = true; 1383 if (VarName[V] < 0) 1384 { 1385 VarName[V] = GetFreeVar; 1386 ++RefCnt[VarName[V]]; 1387 } 1388 if (EAG.Var[EAG.Var[V].Neg].Def) 1389 { 1390 const Vn = EAG.Var[V].Neg; 1391 1392 --VarDeps[V]; 1393 --VarDeps[Vn]; 1394 if (VarDeps[Vn] == 0) 1395 { 1396 VarDepPos[Vn] = P; 1397 Dispose(VarName[Vn]); 1398 } 1399 } 1400 } 1401 else 1402 { 1403 if (VarDeps[V] == 1) 1404 VarDepPos[V] = P; 1405 } 1406 --VarDeps[V]; 1407 if (VarDeps[V] == 0) 1408 Dispose(VarName[V]); 1409 } 1410 else 1411 { 1412 const Arity = EAG.MAlt[EAG.NodeBuf[Node]].Arity; 1413 1414 if (Arity != 0) 1415 NodeName[Node] = Var; 1416 foreach (n; 0 .. Arity) 1417 { 1418 const Node1 = EAG.NodeBuf[Node + n + 1]; 1419 const NeedVar = ((isPred || UseRefCnt) && Var == AffixName[P] || n + 1 != Arity) 1420 && Node1 >= 0 1421 && EAG.MAlt[EAG.NodeBuf[Node1]].Arity > 0; 1422 int Var1; 1423 1424 if (NeedVar) 1425 { 1426 Var1 = GetFreeVar; 1427 ++RefCnt[Var1]; 1428 } 1429 else 1430 { 1431 Var1 = Var; 1432 } 1433 DefPos(Node1, Var1); 1434 if (NeedVar) 1435 Dispose(Var1); 1436 } 1437 } 1438 } 1439 1440 while (EAG.ParamBuf[P].Affixform != EAG.nil) 1441 { 1442 const Tree = EAG.ParamBuf[P].Affixform; 1443 1444 if (EAG.ParamBuf[P].isDef) 1445 { 1446 if (Tree < 0 && VarName[-Tree] < 0) 1447 { 1448 const V = -Tree; 1449 1450 VarName[V] = AffixName[P]; 1451 ++RefCnt[VarName[V]]; 1452 } 1453 DefPos(Tree, AffixName[P]); 1454 } 1455 ++P; 1456 } 1457 } 1458 1459 void CheckApplPos(int P, bool Repetition) 1460 { 1461 int Tree; 1462 int V; 1463 int P1; 1464 1465 void ApplPos(int Node, int Var) 1466 { 1467 if (Node < 0) 1468 { 1469 const V = -Node; 1470 1471 --VarDeps[V]; 1472 if (VarDeps[V] == 0) 1473 Dispose(VarName[V]); 1474 if (VarDepPos[V] >= 0) 1475 VarDepPos[V] = -1; 1476 } 1477 else 1478 { 1479 const Arity = EAG.MAlt[EAG.NodeBuf[Node]].Arity; 1480 1481 NodeName[Node] = Var; 1482 foreach (n; 0 .. Arity) 1483 { 1484 const Node1 = EAG.NodeBuf[Node + n + 1]; 1485 const NeedVar = !(UseConst && AffixPlace[P] > 0) 1486 && UseRefCnt 1487 && (Var == AffixName[P] || n + 1 != Arity) 1488 && Node1 >= 0 1489 && EAG.MAlt[EAG.NodeBuf[Node1]].Arity > 0; 1490 int Var1; 1491 1492 if (NeedVar) 1493 { 1494 Var1 = GetFreeVar; 1495 ++RefCnt[Var1]; 1496 } 1497 else 1498 { 1499 Var1 = Var; 1500 } 1501 ApplPos(Node1, Var1); 1502 if (NeedVar) 1503 Dispose(Var1); 1504 } 1505 } 1506 } 1507 1508 P1 = P; 1509 while (EAG.ParamBuf[P].Affixform != EAG.nil) 1510 { 1511 if (!EAG.ParamBuf[P].isDef) 1512 { 1513 Tree = EAG.ParamBuf[P].Affixform; 1514 if (Tree < 0 && VarName[-Tree] < 0) 1515 { 1516 V = -Tree; 1517 VarName[V] = AffixName[P]; 1518 ++RefCnt[VarName[V]]; 1519 } 1520 if (!(UseConst && AffixPlace[P] > 0) && Repetition && Tree >= 0) 1521 { 1522 NodeName[Tree] = GetFreeVar; 1523 ++RefCnt[NodeName[Tree]]; 1524 ApplPos(Tree, NodeName[Tree]); 1525 } 1526 else 1527 { 1528 ApplPos(Tree, AffixName[P]); 1529 } 1530 } 1531 ++P; 1532 } 1533 if (Repetition) 1534 { 1535 while (EAG.ParamBuf[P1].Affixform != EAG.nil) 1536 { 1537 if (!EAG.ParamBuf[P1].isDef && !(UseConst && AffixPlace[P1] > 0)) 1538 { 1539 Tree = EAG.ParamBuf[P1].Affixform; 1540 if (Tree >= 0) 1541 Dispose(NodeName[Tree]); 1542 } 1543 ++P1; 1544 } 1545 } 1546 } 1547 1548 void GetFormalParamNames(size_t N, int P) 1549 { 1550 const Repetition = !EAG.Pred[N] && cast(EAG.Rep) EAG.HNont[N].Def; 1551 int Dom = EAG.HNont[N].Sig; 1552 int Tree; 1553 int V; 1554 1555 while (EAG.ParamBuf[P].Affixform != EAG.nil) 1556 { 1557 if (Repetition) 1558 { 1559 AffixName[P] = ActualName[Dom]; 1560 } 1561 else 1562 { 1563 AffixName[P] = FormalName[Dom]; 1564 Tree = EAG.ParamBuf[P].Affixform; 1565 if (!EAG.ParamBuf[P].isDef && Tree < 0) 1566 { 1567 V = -Tree; 1568 VarName[V] = AffixName[P]; 1569 ++RefCnt[VarName[V]]; 1570 } 1571 } 1572 ++P; 1573 ++Dom; 1574 } 1575 } 1576 1577 void GetActualParamNames(size_t N, int P) 1578 { 1579 int FindVarName(int P, int VarName) 1580 { 1581 while (AffixName[P] != VarName) 1582 ++P; 1583 return P; 1584 } 1585 1586 const Repetition = !EAG.Pred[N] && cast(EAG.Rep) EAG.HNont[N].Def; 1587 int P1 = P; 1588 int Tree; 1589 int V; 1590 1591 while (EAG.ParamBuf[P].Affixform != EAG.nil) 1592 { 1593 Tree = EAG.ParamBuf[P].Affixform; 1594 if (AffixName[P] < 0) 1595 { 1596 if (Tree < 0 && VarName[-Tree] >= 0) 1597 { 1598 V = -Tree; 1599 if (!EAG.ParamBuf[P].isDef) 1600 { 1601 if (Repetition && VarDeps[V] > 1) 1602 { 1603 AffixName[P] = GetFreeVar; 1604 } 1605 else if (!EAG.Pred[N] && EAG.HNont[N].anonymous) 1606 { 1607 AffixName[P] = VarName[V]; 1608 if (FindVarName(P1, VarName[V]) != P) 1609 AffixName[P] = GetFreeVar; 1610 } 1611 else 1612 { 1613 AffixName[P] = VarName[V]; 1614 } 1615 } 1616 else 1617 { 1618 AffixName[P] = VarName[V]; 1619 if (EAG.Var[V].Def || FindVarName(P1, VarName[V]) != P) 1620 AffixName[P] = GetFreeVar; 1621 } 1622 } 1623 else 1624 { 1625 AffixName[P] = GetFreeVar; 1626 } 1627 } 1628 ++RefCnt[AffixName[P]]; 1629 if (isPred && EAG.ParamBuf[P].isDef) 1630 ++RefCnt[AffixName[P]]; 1631 ++P; 1632 } 1633 } 1634 1635 void FreeActualParamNames(int P) 1636 { 1637 while (EAG.ParamBuf[P].Affixform != EAG.nil) 1638 { 1639 Dispose(AffixName[P]); 1640 ++P; 1641 } 1642 } 1643 1644 void FreeAllDefPosVarNames(EAG.Alt A) 1645 { 1646 EAG.Factor F; 1647 1648 void FreeVarNames(int P) 1649 { 1650 while (EAG.ParamBuf[P].Affixform != EAG.nil) 1651 { 1652 if (EAG.ParamBuf[P].isDef) 1653 Dispose(AffixName[P]); 1654 ++P; 1655 } 1656 } 1657 1658 F = A.Sub; 1659 while (F !is null) 1660 { 1661 if (auto nont = cast(EAG.Nont) F) 1662 FreeVarNames(nont.Actual.Params); 1663 F = F.Next; 1664 } 1665 if (cast(EAG.Rep) Node) 1666 FreeVarNames(A.Actual.Params); 1667 } 1668 1669 void InitComputation(EAG.ScopeDesc Scope) 1670 { 1671 trace!"RC: enter"; 1672 InitScope(Scope); 1673 foreach (i; Scope.Beg .. Scope.End) 1674 { 1675 VarDeps[i] = VarCnt[i]; 1676 if (EAG.Var[i].Neg != EAG.nil) 1677 ++VarDeps[i]; 1678 } 1679 } 1680 1681 void FinitComputation(EAG.ScopeDesc Scope) 1682 { 1683 trace!"RC: exit"; 1684 foreach (i; Scope.Beg .. Scope.End) 1685 { 1686 VarRefCnt[i] = VarAppls[i]; 1687 if (VarDepPos[i] >= 0) 1688 ++VarRefCnt[i]; 1689 trace!`RC: "%s" %s V%s (%s)`(EAG.VarRepr(i), VarDeps[i], VarName[i], RefCnt[VarName[i]]); 1690 } 1691 } 1692 1693 Prepare(N); 1694 trace!`RC: begin "%s": RefCnt=%s`(EAG.HNontRepr(N), RefCnt[0 .. NextFreeVar + 1]); 1695 scope (exit) 1696 trace!`RC: end "%s": RefCnt=%s`(EAG.HNontRepr(N), RefCnt[0 .. NextFreeVar + 1]); 1697 Node = EAG.HNont[N].Def; 1698 isPred = EAG.Pred[N]; 1699 1700 const Repetition = !isPred && cast(EAG.Rep) Node; 1701 int Dom = EAG.HNont[N].Sig; 1702 1703 while (EAG.DomBuf[Dom] != EAG.nil) 1704 { 1705 if (FormalName[Dom] < 0) 1706 FormalName[Dom] = GetFreeVar; 1707 ++RefCnt[FormalName[Dom]]; 1708 ++Dom; 1709 } 1710 if (Repetition) 1711 { 1712 Dom = EAG.HNont[N].Sig; 1713 P = (cast(EAG.Rep) Node).Formal.Params; 1714 while (EAG.DomBuf[Dom] != EAG.nil) 1715 { 1716 ActualName[Dom] = FormalName[Dom]; 1717 if (!EAG.ParamBuf[P].isDef) 1718 { 1719 ActualName[Dom] = GetFreeVar; 1720 ++RefCnt[ActualName[Dom]]; 1721 } 1722 ++Dom; 1723 ++P; 1724 } 1725 } 1726 A = Node.Sub; 1727 do 1728 { 1729 InitComputation(A.Scope); 1730 trace!"RC: RefCnt=%s"(RefCnt[0 .. NextFreeVar + 1]); 1731 GetFormalParamNames(N, A.Formal.Params); 1732 if (Repetition) 1733 { 1734 Dom = EAG.HNont[N].Sig; 1735 P = A.Actual.Params; 1736 while (EAG.ParamBuf[P].Affixform != EAG.nil) 1737 { 1738 if (EAG.ParamBuf[P].isDef) 1739 { 1740 AffixName[P] = ActualName[Dom]; 1741 if (EAG.ParamBuf[P].Affixform < 0) 1742 { 1743 VarName[-EAG.ParamBuf[P].Affixform] = AffixName[P]; 1744 ++RefCnt[AffixName[P]]; 1745 } 1746 } 1747 ++P; 1748 ++Dom; 1749 } 1750 } 1751 CheckDefPos(A.Formal.Params); 1752 F = A.Sub; 1753 while (F !is null) 1754 { 1755 if (auto nont = cast(EAG.Nont) F) 1756 { 1757 GetActualParamNames(nont.Sym, nont.Actual.Params); 1758 CheckApplPos(nont.Actual.Params, false); 1759 if (embed && EAG.Prod[nont.Sym] && !EAG.Pred[nont.Sym] && EAG.HNont[nont.Sym].anonymous) 1760 { 1761 Dom = EAG.HNont[nont.Sym].Sig; 1762 P = nont.Actual.Params; 1763 while (EAG.DomBuf[Dom] != EAG.nil) 1764 { 1765 FormalName[Dom] = AffixName[P]; 1766 ++Dom; 1767 ++P; 1768 } 1769 Traverse(nont.Sym); 1770 } 1771 CheckDefPos(nont.Actual.Params); 1772 FreeActualParamNames(nont.Actual.Params); 1773 } 1774 F = F.Next; 1775 } 1776 if (cast(EAG.Rep) Node) 1777 { 1778 GetActualParamNames(N, A.Actual.Params); 1779 CheckApplPos(A.Actual.Params, false); 1780 CheckDefPos(A.Actual.Params); 1781 FreeActualParamNames(A.Actual.Params); 1782 } 1783 CheckApplPos(A.Formal.Params, Repetition); 1784 if (isPred) 1785 FreeAllDefPosVarNames(A); 1786 FinitComputation(A.Scope); 1787 trace!"RC: RefCnt=%s"(RefCnt[0 .. NextFreeVar + 1]); 1788 A = A.Next; 1789 } 1790 while (A !is null); 1791 if (auto rep = cast(EAG.Rep) Node) 1792 { 1793 InitComputation(rep.Scope); 1794 GetFormalParamNames(N, rep.Formal.Params); 1795 CheckDefPos(rep.Formal.Params); 1796 CheckApplPos(rep.Formal.Params, true); 1797 FinitComputation(rep.Scope); 1798 } 1799 else if (auto opt = cast(EAG.Opt) Node) 1800 { 1801 InitComputation(opt.Scope); 1802 GetFormalParamNames(N, opt.Formal.Params); 1803 CheckDefPos(opt.Formal.Params); 1804 CheckApplPos(opt.Formal.Params, false); 1805 FinitComputation(opt.Scope); 1806 } 1807 if (Repetition) 1808 { 1809 P = (cast(EAG.Rep) Node).Formal.Params; 1810 while (EAG.ParamBuf[P].Affixform != EAG.nil) 1811 { 1812 if (!EAG.ParamBuf[P].isDef) 1813 Dispose(AffixName[P]); 1814 ++P; 1815 } 1816 } 1817 Dom = EAG.HNont[N].Sig; 1818 while (EAG.DomBuf[Dom] != EAG.nil) 1819 { 1820 Dispose(FormalName[Dom]); 1821 ++Dom; 1822 } 1823 } 1824 1825 void ComputeRepAppls(size_t N) 1826 { 1827 if (cast(EAG.Rep) EAG.HNont[N].Def) 1828 { 1829 EAG.Alt A = EAG.HNont[N].Def.Sub; 1830 1831 do 1832 { 1833 foreach (param; A.Actual.params) 1834 if (param.isDef) 1835 RepAppls[N] = RepAppls[N] && VarAppls[-param.Affixform] == 1; 1836 A = A.Next; 1837 } 1838 while (A !is null); 1839 } 1840 } 1841 1842 FreeVar = new int[63]; 1843 RefCnt = new int[63]; 1844 ComputeRepAppls(N); 1845 NextFreeVar = 0; 1846 Top = 0; 1847 Traverse(N); 1848 HNontVars[N] = NextFreeVar; 1849 HNontDef[N] = true; 1850 } 1851 1852 public void GenFormalParams(size_t N, Flag!"parNeeded" parNeeded) 1853 { 1854 int Dom = EAG.HNont[N].Sig; 1855 int i = 1; 1856 1857 if (parNeeded) 1858 output.write("("); 1859 if (EAG.DomBuf[Dom] != EAG.nil) 1860 { 1861 if (!parNeeded) 1862 output.write(", "); 1863 while (true) 1864 { 1865 if (EAG.DomBuf[Dom] > 0) 1866 output.write("ref "); 1867 output.write("HeapType "); 1868 GenVar(i); 1869 ++i; 1870 ++Dom; 1871 if (EAG.DomBuf[Dom] == EAG.nil) 1872 break; 1873 output.write(", "); 1874 } 1875 } 1876 if (parNeeded) 1877 output.write(")"); 1878 HNontFVars[N] = i; 1879 } 1880 1881 public void GenVarDecl(size_t N) 1882 { 1883 if (HNontVars[N] - HNontFVars[N] >= 0) 1884 { 1885 foreach (i; HNontFVars[N] .. HNontVars[N] + 1) 1886 { 1887 output.write("HeapType "); 1888 GenVar(i); 1889 output.writeln(";"); 1890 } 1891 } 1892 if (EAG.Pred[N]) 1893 output.writeln("bool Failed;"); 1894 } 1895 1896 public void InitScope(EAG.ScopeDesc Scope) @nogc nothrow @safe 1897 { 1898 foreach (i; Scope.Beg .. Scope.End) 1899 EAG.Var[i].Def = false; 1900 } 1901 1902 public void GenPredCall(int N, int ActualParams) 1903 in (EAG.Pred[N]) 1904 { 1905 output.write("Check", N, `("`); 1906 if (EAG.HNont[N].anonymous) 1907 output.write("in "); 1908 output.write("'", EAG.NamedHNontRepr(N), `'"`); 1909 GenActualParams(ActualParams, false); 1910 output.writeln(");"); 1911 } 1912 1913 public void GenActualParams(int P, bool ParNeeded) @safe 1914 { 1915 if (ParNeeded) 1916 output.write("("); 1917 if (EAG.ParamBuf[P].Affixform != EAG.nil) 1918 { 1919 if (!ParNeeded) 1920 output.write(", "); 1921 while (true) 1922 { 1923 assert(AffixName[P] >= 0); 1924 1925 GenVar(AffixName[P]); 1926 ++P; 1927 if (EAG.ParamBuf[P].Affixform == EAG.nil) 1928 break; 1929 output.write(", "); 1930 } 1931 } 1932 if (ParNeeded) 1933 output.write(")"); 1934 } 1935 1936 public void GenSynPred(size_t Sym, int P) 1937 { 1938 int Next; 1939 bool IsPred = EAG.Pred[Sym]; 1940 1941 if (!UseRefCnt) 1942 GetAffixSpace(P); 1943 while (EAG.ParamBuf[P].Affixform != EAG.nil) 1944 { 1945 if (!EAG.ParamBuf[P].isDef) 1946 { 1947 const Tree = EAG.ParamBuf[P].Affixform; 1948 1949 if (SavePos) 1950 output.writeln("PopPos(", EAG.MAlt[EAG.NodeBuf[Tree]].Arity, ");"); 1951 if (UseConst && AffixPlace[P] >= 0) 1952 { 1953 GenVar(AffixName[P]); 1954 output.writeln(" = ", AffixPlace[P], ";"); 1955 if (UseRefCnt) 1956 GenIncRefCnt(-AffixPlace[P], 1); 1957 } 1958 else if (Tree < 0) 1959 { 1960 const V = -Tree; 1961 1962 if (UseRefCnt && IsPred) 1963 GenIncRefCnt(VarName[V], 1); 1964 if (AffixName[P] != VarName[V]) 1965 { 1966 GenVar(AffixName[P]); 1967 output.write(" = "); 1968 GenVar(VarName[V]); 1969 output.writeln(";"); 1970 } 1971 } 1972 else 1973 { 1974 if (UseRefCnt) 1975 { 1976 output.write("GetHeap(", EAG.MAlt[EAG.NodeBuf[Tree]].Arity, ", "); 1977 GenVar(NodeName[Tree]); 1978 output.write("); "); 1979 Gen1SynTree(Tree, EmptySet, IsPred); 1980 output.writeln; 1981 } 1982 else 1983 { 1984 GenVar(AffixName[P]); 1985 output.write(" = NextHeap; "); 1986 Next = 0; 1987 GenSynTree(Tree, EmptySet, Next); 1988 GenHeapInc(Next); 1989 } 1990 } 1991 } 1992 ++P; 1993 } 1994 } 1995 1996 private void GetAffixSpace(int P) @safe 1997 { 1998 int Heap = 0; 1999 2000 while (EAG.ParamBuf[P].Affixform != EAG.nil) 2001 { 2002 if (!EAG.ParamBuf[P].isDef && (!UseConst || UseConst && AffixPlace[P] < 0)) 2003 Heap += AffixSpace[P]; 2004 ++P; 2005 } 2006 GenOverflowGuard(Heap); 2007 } 2008 2009 // RepVar is to be understood only in the context of generating repetition code 2010 private void GenSynTree(int Node, BitArray RepVar, ref int Next) 2011 { 2012 const Alt = EAG.NodeBuf[Node]; 2013 const Next1 = Next; 2014 2015 GenHeap(0, Next); 2016 output.write(" = ", NodeIdent[Alt], "; "); 2017 Next += 1 + EAG.MAlt[Alt].Arity; 2018 foreach (n; 0 .. EAG.MAlt[Alt].Arity) 2019 { 2020 const Node1 = EAG.NodeBuf[Node + n + 1]; 2021 2022 if (Node1 < 0) 2023 { 2024 const V = -Node1; 2025 2026 if (RepVar[V]) 2027 { 2028 GenVar(VarName[V]); 2029 output.write(" = NextHeap + ", Next1 + n + 1); 2030 } 2031 else 2032 { 2033 GenHeap(0, Next1 + n + 1); 2034 output.write(" = "); 2035 GenVar(VarName[V]); 2036 } 2037 output.write("; "); 2038 } 2039 else 2040 { 2041 GenHeap(0, Next1 + n + 1); 2042 output.write(" = "); 2043 if (UseConst && EAG.MAlt[EAG.NodeBuf[Node1]].Arity == 0) 2044 { 2045 output.write(Leaf[EAG.NodeBuf[Node1]], "; "); 2046 } 2047 else 2048 { 2049 output.write("NextHeap + ", Next, "; "); 2050 GenSynTree(Node1, RepVar, Next); 2051 } 2052 } 2053 } 2054 } 2055 2056 // RepVar is to be understood only in the context of generating repetition code 2057 private void Gen1SynTree(int Node, BitArray RepVar, bool IsPred) 2058 { 2059 GenHeap(NodeName[Node], 0); 2060 output.write(" = ", NodeIdent[EAG.NodeBuf[Node]], "; "); 2061 foreach (n; 0 .. EAG.MAlt[EAG.NodeBuf[Node]].Arity) 2062 { 2063 const Node1 = EAG.NodeBuf[Node + n + 1]; 2064 2065 if (Node1 < 0) 2066 { 2067 const V = -Node1; 2068 2069 if (RepVar[V]) 2070 { 2071 GenVar(VarName[V]); 2072 output.write(" = "); 2073 GenVar(NodeName[Node]); 2074 output.write(" + ", n + 1, "; "); 2075 } 2076 else 2077 { 2078 GenHeap(NodeName[Node], n + 1); 2079 output.write(" = "); 2080 GenVar(VarName[V]); 2081 output.write("; "); 2082 if (IsPred) 2083 GenIncRefCnt(VarName[V], 1); 2084 } 2085 } 2086 else if (EAG.MAlt[EAG.NodeBuf[Node1]].Arity == 0) 2087 { 2088 if (UseConst) 2089 { 2090 GenHeap(NodeName[Node], n + 1); 2091 output.write(" = ", Leaf[EAG.NodeBuf[Node1]], "; "); 2092 GenIncRefCnt(-Leaf[EAG.NodeBuf[Node1]], 1); 2093 } 2094 else 2095 { 2096 output.write("GetHeap(0, "); 2097 GenHeap(NodeName[Node], n + 1); 2098 output.write("); Heap["); 2099 GenHeap(NodeName[Node], n + 1); 2100 output.write("] = ", NodeIdent[EAG.NodeBuf[Node1]], ";"); 2101 } 2102 } 2103 else 2104 { 2105 output.write("GetHeap(", EAG.MAlt[EAG.NodeBuf[Node1]].Arity, ", "); 2106 if (NodeName[Node] == NodeName[Node1]) 2107 { 2108 GenHeap(NodeName[Node], n + 1); 2109 output.write("); "); 2110 GenVar(NodeName[Node1]); 2111 output.write(" = "); 2112 GenHeap(NodeName[Node], n + 1); 2113 } 2114 else 2115 { 2116 GenVar(NodeName[Node1]); 2117 output.write("); "); 2118 GenHeap(NodeName[Node], n + 1); 2119 output.write(" = "); 2120 GenVar(NodeName[Node1]); 2121 } 2122 output.writeln(";"); 2123 Gen1SynTree(Node1, RepVar, IsPred); 2124 } 2125 } 2126 } 2127 2128 public void GenAnalPred(size_t Sym, int P) 2129 { 2130 bool MakeRefCnt; 2131 bool IsPred; 2132 2133 void Comp() 2134 { 2135 if (UseRefCnt) 2136 output.write(".MOD(refConst)"); 2137 output.write(IsPred ? " == " : " != "); 2138 } 2139 2140 void GenEqualErrMsg(size_t Sym, int Var) 2141 { 2142 output.write(`"'`, EAG.VarRepr(Var), "' failed in '", EAG.NamedHNontRepr(Sym), `'"`); 2143 } 2144 2145 void GenAnalErrMsg(size_t Sym) 2146 { 2147 output.write(`"`, EAG.NamedHNontRepr(Sym), `"`); 2148 } 2149 2150 void GenEqualPred(int VarName1, int Var2, bool Eq) 2151 { 2152 if (IsPred) 2153 { 2154 output.write("if ("); 2155 if (!Eq) 2156 output.write("!"); 2157 output.write("Equal("); 2158 GenVar(VarName1); 2159 output.write(", "); 2160 GenVar(VarName[Var2]); 2161 output.writeln("))"); 2162 output.writeln("{"); 2163 ++IfLevel; 2164 } 2165 else 2166 { 2167 if (!Eq) 2168 output.write("Un"); 2169 output.write("Eq("); 2170 GenVar(VarName1); 2171 output.write(", "); 2172 GenVar(VarName[Var2]); 2173 output.write(", "); 2174 GenEqualErrMsg(Sym, Var2); 2175 output.write("); "); 2176 } 2177 } 2178 2179 void GenAnalTree(int Node) 2180 { 2181 output.write("if ("); 2182 GenHeap(NodeName[Node], 0); 2183 Comp; 2184 output.write(NodeIdent[EAG.NodeBuf[Node]]); 2185 output.write(")"); 2186 if (IsPred) 2187 { 2188 output.writeln; 2189 output.writeln("{"); 2190 ++IfLevel; 2191 } 2192 else 2193 { 2194 output.write(" AnalyseError("); 2195 GenVar(NodeName[Node]); 2196 output.write(", "); 2197 GenAnalErrMsg(Sym); 2198 output.writeln(");"); 2199 } 2200 foreach (n; 0 .. EAG.MAlt[EAG.NodeBuf[Node]].Arity) 2201 { 2202 const Node1 = EAG.NodeBuf[Node + n + 1]; 2203 2204 if (Node1 < 0) 2205 { 2206 const V = -Node1; 2207 2208 if (EAG.Var[V].Def) 2209 { 2210 if (IsPred) 2211 { 2212 output.write("if (Equal("); 2213 GenHeap(NodeName[Node], n + 1); 2214 output.write(", "); 2215 GenVar(VarName[V]); 2216 output.writeln("))"); 2217 output.writeln("{"); 2218 ++IfLevel; 2219 } 2220 else 2221 { 2222 output.write("Eq("); 2223 GenHeap(NodeName[Node], n + 1); 2224 output.write(", "); 2225 GenVar(VarName[V]); 2226 output.write(", "); 2227 GenEqualErrMsg(Sym, V); 2228 output.write("); "); 2229 } 2230 } 2231 else 2232 { 2233 EAG.Var[V].Def = true; 2234 GenVar(VarName[V]); 2235 output.write(" = "); 2236 GenHeap(NodeName[Node], n + 1); 2237 output.write("; "); 2238 if (EAG.Var[EAG.Var[V].Neg].Def) 2239 { 2240 const Vn = EAG.Var[V].Neg; 2241 2242 GenEqualPred(VarName[Vn], V, false); 2243 if (MakeRefCnt) 2244 { 2245 if (VarDepPos[Vn] == P) 2246 { 2247 GenFreeHeap(VarName[Vn]); 2248 VarDepPos[Vn] = -2; 2249 } 2250 } 2251 } 2252 if (MakeRefCnt && VarRefCnt[V] > 0) 2253 GenIncRefCnt(VarName[V], VarRefCnt[V]); 2254 } 2255 if (MakeRefCnt) 2256 { 2257 if (VarDepPos[V] == P) 2258 { 2259 GenFreeHeap(VarName[V]); 2260 VarDepPos[V] = -2; 2261 } 2262 } 2263 } 2264 else 2265 { 2266 if (EAG.MAlt[EAG.NodeBuf[Node1]].Arity == 0) 2267 { 2268 if (UseConst) 2269 { 2270 output.write("if ("); 2271 GenHeap(NodeName[Node], n + 1); 2272 Comp; 2273 output.write(Leaf[EAG.NodeBuf[Node1]]); 2274 } 2275 else 2276 { 2277 output.write("if (Heap["); 2278 GenHeap(NodeName[Node], n + 1); 2279 output.write("]"); 2280 Comp; 2281 output.write(NodeIdent[EAG.NodeBuf[Node1]]); 2282 } 2283 output.write(")"); 2284 if (IsPred) 2285 { 2286 output.writeln; 2287 output.writeln("{"); 2288 ++IfLevel; 2289 } 2290 else 2291 { 2292 output.write(" AnalyseError("); 2293 GenHeap(NodeName[Node], n + 1); 2294 output.write(", "); 2295 GenAnalErrMsg(Sym); 2296 output.write(");"); 2297 } 2298 output.writeln; 2299 } 2300 else 2301 { 2302 GenVar(NodeName[Node1]); 2303 output.write(" = "); 2304 GenHeap(NodeName[Node], n + 1); 2305 output.write("; "); 2306 GenAnalTree(Node1); 2307 } 2308 } 2309 } 2310 } 2311 2312 IsPred = EAG.Pred[Sym]; 2313 IfLevel = 0; 2314 MakeRefCnt = UseRefCnt && !IsPred; 2315 while (EAG.ParamBuf[P].Affixform != EAG.nil) 2316 { 2317 if (EAG.ParamBuf[P].isDef) 2318 { 2319 const Tree = EAG.ParamBuf[P].Affixform; 2320 2321 if (Tree < 0) 2322 { 2323 const V = -Tree; 2324 2325 if (EAG.Var[V].Def) 2326 { 2327 assert(AffixName[P] != VarName[V]); 2328 2329 GenEqualPred(AffixName[P], V, true); 2330 if (MakeRefCnt) 2331 GenFreeHeap(AffixName[P]); 2332 } 2333 else 2334 { 2335 EAG.Var[V].Def = true; 2336 if (AffixName[P] != VarName[V]) 2337 { 2338 GenVar(VarName[V]); 2339 output.write(" = "); 2340 GenVar(AffixName[P]); 2341 output.writeln(";"); 2342 } 2343 if (EAG.Var[EAG.Var[V].Neg].Def) 2344 { 2345 const Vn = EAG.Var[V].Neg; 2346 2347 GenEqualPred(VarName[Vn], V, false); 2348 if (MakeRefCnt) 2349 { 2350 if (VarDepPos[Vn] == P) 2351 { 2352 GenFreeHeap(VarName[Vn]); 2353 VarDepPos[Vn] = -2; 2354 } 2355 } 2356 } 2357 if (MakeRefCnt) 2358 { 2359 if (VarRefCnt[V] > 1) 2360 GenIncRefCnt(VarName[V], VarRefCnt[V] - 1); 2361 else if (VarRefCnt[V] == 0) 2362 GenFreeHeap(AffixName[P]); 2363 } 2364 } 2365 if (MakeRefCnt) 2366 { 2367 if (VarDepPos[V] == P) 2368 { 2369 GenFreeHeap(VarName[V]); 2370 VarDepPos[V] = -2; 2371 } 2372 } 2373 } 2374 else 2375 { 2376 if (EAG.MAlt[EAG.NodeBuf[Tree]].Arity == 0) 2377 { 2378 output.write("if ("); 2379 GenHeap(AffixName[P], 0); 2380 Comp; 2381 output.write(NodeIdent[EAG.NodeBuf[Tree]], ")"); 2382 if (IsPred) 2383 { 2384 output.writeln; 2385 output.writeln("{"); 2386 ++IfLevel; 2387 } 2388 else 2389 { 2390 output.write(" AnalyseError("); 2391 GenVar(AffixName[P]); 2392 output.write(", "); 2393 GenAnalErrMsg(Sym); 2394 output.write(");"); 2395 } 2396 output.writeln; 2397 } 2398 else 2399 { 2400 GenAnalTree(Tree); 2401 } 2402 if (MakeRefCnt) 2403 GenFreeHeap(AffixName[P]); 2404 } 2405 } 2406 ++P; 2407 } 2408 if (SavePos) 2409 output.writeln("PushPos;"); 2410 } 2411 2412 private void GenHeap(int Var, int Offset) @safe 2413 { 2414 output.write("Heap["); 2415 if (Var <= 0) 2416 output.write("NextHeap"); 2417 else 2418 GenVar(Var); 2419 if (Offset > 0) 2420 { 2421 output.write(" + ", Offset); 2422 } 2423 else if (Offset < 0) 2424 { 2425 output.write(" - ", -Offset); 2426 } 2427 output.write("]"); 2428 } 2429 2430 private void GenIncRefCnt(int Var, int n) @safe 2431 { 2432 output.write("Heap["); 2433 if (Var < 0) 2434 output.write(-Var); 2435 else 2436 GenVar(Var); 2437 output.write("] += "); 2438 if (n != 1) 2439 output.write(n, " * "); 2440 output.writeln("refConst;"); 2441 } 2442 2443 private void GenOverflowGuard(int n) @safe 2444 { 2445 if (n > 0) 2446 { 2447 output.writeln("if (NextHeap >= Heap.length - ", n, ")"); 2448 output.writeln("EvalExpand;"); 2449 } 2450 } 2451 2452 private void GenFreeHeap(int Var) @safe 2453 { 2454 output.write("FreeHeap("); 2455 GenVar(Var); 2456 output.writeln(");"); 2457 } 2458 2459 private void GenHeapInc(int n) @safe 2460 { 2461 if (n != 0) 2462 { 2463 if (n == 1) 2464 output.writeln("++NextHeap;"); 2465 else 2466 output.writeln("NextHeap += ", n, ";"); 2467 } 2468 } 2469 2470 private void GenVar(int Var) @safe 2471 { 2472 output.write("V", Var); 2473 } 2474 2475 static this() @nogc nothrow @safe 2476 { 2477 Testing = false; 2478 Generating = false; 2479 }