1 module epsilon.soag.soaggen; 2 3 import EAG = epsilon.eag; 4 import EmitGen = epsilon.emitgen; 5 import SLAGGen = epsilon.slaggen; 6 import epsilon.settings; 7 import io : Input, read; 8 import log; 9 import runtime; 10 import optimizer = epsilon.soag.optimizer; 11 import partition = epsilon.soag.partition; 12 import Protocol = epsilon.soag.protocol; 13 import SOAG = epsilon.soag.soag; 14 import VisitSeq = epsilon.soag.visitseq; 15 import std.bitmanip : BitArray; 16 import std.stdio; 17 18 private const firstAffixOffset = 0; 19 private const optimizedStorage = -1; 20 private const notApplied = -2; 21 private bool UseConst; 22 private bool UseRefCnt; 23 private bool Optimize; 24 private int[] LocalVars; 25 private int[] NodeName; 26 private int[] AffixOffset; 27 private int[] AffixVarCount; 28 private int[] SubTreeOffset; 29 private int[] FirstRule; 30 private int[] AffixAppls; 31 private File output; 32 private bool Close; 33 34 /** 35 * SEM: Steuerung der Generierung 36 */ 37 public string Generate(Settings settings) 38 in (EAG.Performed(EAG.analysed | EAG.predicates)) 39 { 40 UseConst = !settings.c; 41 UseRefCnt = !settings.r; 42 Optimize = !settings.o; 43 partition.Compute; 44 VisitSeq.Generate; 45 if (Optimize) 46 optimizer.Optimize; 47 info!"SOAG writing %s"(EAG.BaseName); 48 if (Optimize) 49 info!"optimize"; 50 else 51 info!"don't optimize"; 52 Init; 53 54 const fileName = GenerateModule(settings); 55 56 EAG.History |= EAG.isSweep; 57 EAG.History |= EAG.hasEvaluator; 58 return fileName; 59 } 60 61 /** 62 * IN: Regel 63 * OUT: - 64 * SEM: Berechnet im Feld NodeNames für alle Affixbaumanalysen der Regel 65 * die Namen der temp. Variablen für die Baumknoten; 66 * die maximale Variablenummer der Regel wird in LocalVars[] abgelegt 67 */ 68 private void ComputeNodeNames(int R) @nogc nothrow 69 { 70 int Var; 71 int ProcVar; 72 int AP; 73 int Node; 74 int SO; 75 int PBI; 76 77 /** 78 * IN: Knoten in NodeBuf[], Variablenname 79 * OUT: - 80 * SEM: Berechnet für jeden Knoten des Teilbaums NodeBuf[Node] 81 * die temp. Variable für die Baumanalyse oder -synthese 82 */ 83 void Traverse(int Node, ref int Var) 84 { 85 int Node1; 86 const Arity = EAG.MAlt[EAG.NodeBuf[Node]].Arity; 87 88 ++Var; 89 NodeName[Node] = Var; 90 for (size_t n = 1; n <= Arity; ++n) 91 { 92 Node1 = EAG.NodeBuf[Node + n]; 93 if (Node1 > 0) 94 { 95 if (UseConst && EAG.MAlt[EAG.NodeBuf[Node1]].Arity == 0) 96 { 97 ++Var; 98 NodeName[Node1] = Var; 99 } 100 else 101 { 102 Traverse(Node1, Var); 103 } 104 } 105 } 106 } 107 108 LocalVars[R] = 0; 109 for (AP = SOAG.Rule[R].AffOcc.Beg; AP <= SOAG.Rule[R].AffOcc.End; ++AP) 110 { 111 PBI = SOAG.AffOcc[AP].ParamBufInd; 112 if (EAG.ParamBuf[PBI].isDef || UseRefCnt) 113 { 114 Var = 0; 115 Node = EAG.ParamBuf[PBI].Affixform; 116 if (Node > 0) 117 { 118 if (UseConst && EAG.MAlt[EAG.NodeBuf[Node]].Arity == 0) 119 { 120 ++Var; 121 NodeName[Node] = Var; 122 } 123 else 124 { 125 Traverse(Node, Var); 126 } 127 } 128 if (Var > LocalVars[R]) 129 { 130 LocalVars[R] = Var; 131 } 132 } 133 } 134 for (SO = SOAG.Rule[R].SymOcc.Beg; SO <= SOAG.Rule[R].SymOcc.End; ++SO) 135 { 136 if (SOAG.IsPredNont(SO)) 137 { 138 Var = 0; 139 ProcVar = 0; 140 for (AP = SOAG.SymOcc[SO].AffOcc.Beg; AP <= SOAG.SymOcc[SO].AffOcc.End; 141 ++AP) 142 { 143 PBI = SOAG.AffOcc[AP].ParamBufInd; 144 Node = EAG.ParamBuf[PBI].Affixform; 145 if (!EAG.ParamBuf[PBI].isDef) 146 { 147 if (Node > 0) 148 { 149 ++Var; 150 NodeName[Node] = Var; 151 } 152 } 153 } 154 if (Var > LocalVars[R]) 155 { 156 LocalVars[R] = Var; 157 } 158 } 159 } 160 } 161 162 /** 163 * IN: Affixparameter 164 * OUT: Affixposition 165 * SEM: gibt die Affixposition zurück, zu der der Affixparameter korrespondiert 166 */ 167 private int GetCorrespondedAffPos(int AP) @nogc nothrow @safe 168 { 169 const SO = SOAG.AffOcc[AP].SymOccInd; 170 const AN = AP - SOAG.SymOcc[SO].AffOcc.Beg; 171 172 return SOAG.Sym[SOAG.SymOcc[SO].SymInd].AffPos.Beg + AN; 173 } 174 175 /** 176 * IN: Regel 177 * OUT: - 178 * SEM: berechnet im Feld AffixOffset[], das parallel zu EAG.Var liegt, 179 * den Offset der Affixvariablen im Feld Var[] des generierten Compilers; 180 * alle nicht-applizierten Affixvariablen (AffixAppls[]=0) werden ausgelassen 181 * PRE: AffixAppls[] muss berechnet sein 182 */ 183 private void ComputeAffixOffset(int R) @nogc nothrow @safe 184 { 185 EAG.ScopeDesc Scope; 186 187 if (auto ordRule = cast(SOAG.OrdRule) SOAG.Rule[R]) 188 { 189 Scope = ordRule.Alt.Scope; 190 } 191 else if (auto emptyRule = cast(SOAG.EmptyRule) SOAG.Rule[R]) 192 { 193 EAG.Rule EAGRule = emptyRule.Rule; 194 195 if (auto opt = cast(EAG.Opt) EAGRule) 196 Scope = opt.Scope; 197 else if (auto rep = cast(EAG.Rep) EAGRule) 198 Scope = rep.Scope; 199 } 200 201 int Offset = firstAffixOffset; 202 203 foreach (A; Scope.Beg .. Scope.End) 204 { 205 if (AffixAppls[A] > 0) 206 { 207 if (Optimize) 208 { 209 const AP = GetCorrespondedAffPos(SOAG.DefAffOcc[A]); 210 211 if (SOAG.StorageName[AP] == 0) 212 { 213 AffixOffset[A] = Offset; 214 ++Offset; 215 } 216 else 217 { 218 AffixOffset[A] = optimizedStorage; 219 } 220 } 221 else 222 { 223 AffixOffset[A] = Offset; 224 ++Offset; 225 } 226 } 227 else 228 { 229 AffixOffset[A] = notApplied; 230 } 231 } 232 AffixVarCount[R] = Offset - firstAffixOffset; 233 } 234 235 /** 236 * SEM: liefert die echte Anzahl an Affixvariablen in der Regel; 237 * nur zur Information über die Optimierungleistung 238 */ 239 private int GetAffixCount(int R) @nogc nothrow @safe 240 { 241 EAG.ScopeDesc Scope; 242 243 if (auto ordRule = cast(SOAG.OrdRule) SOAG.Rule[R]) 244 { 245 Scope = ordRule.Alt.Scope; 246 } 247 else if (auto emptyRule = cast(SOAG.EmptyRule) SOAG.Rule[R]) 248 { 249 EAG.Rule EAGRule = emptyRule.Rule; 250 251 if (auto opt = cast(EAG.Opt) EAGRule) 252 Scope = opt.Scope; 253 else if (auto rep = cast(EAG.Rep) EAGRule) 254 Scope = rep.Scope; 255 } 256 return Scope.End - Scope.Beg; 257 } 258 259 /** 260 * IN: - 261 * OUT: Hyper-Arity-Konstante 262 * SEM: Liefert die Arity-Konstante für den Ableitungsbaum, der durch den Parser erzeugt wird; 263 * müsste eigentlich von SLAG geliefert werden (in Sweep wurde es auch intern definiert, 264 * deshalb wird es hier für spätere Module exportiert) 265 */ 266 private int HyperArity() nothrow 267 { 268 const Nonts = EAG.All - EAG.Pred; 269 int Max = 0; 270 int i; 271 272 foreach (N; Nonts.bitsSet) 273 { 274 EAG.Alt A = EAG.HNont[N].Def.Sub; 275 276 i = 0; 277 do 278 { 279 ++i; 280 A = A.Next; 281 } 282 while (A !is null); 283 if (cast(EAG.Opt) EAG.HNont[N].Def || cast(EAG.Rep) EAG.HNont[N].Def) 284 ++i; 285 if (i > Max) 286 Max = i; 287 } 288 i = 1; 289 while (i <= Max) 290 i = i * 2; 291 return i; 292 } 293 294 /** 295 * SEM: Initialisierung der Datenstrukturen des Moduls 296 */ 297 private void Init() nothrow 298 { 299 int R; 300 int SO; 301 int S; 302 int Offset; 303 304 LocalVars = new int[SOAG.NextRule]; 305 AffixVarCount = new int[SOAG.NextRule]; 306 AffixOffset = new int[EAG.NextVar]; 307 NodeName = new int[EAG.NextNode]; 308 SubTreeOffset = new int[SOAG.NextSymOcc]; 309 FirstRule = new int[SOAG.NextSym]; 310 AffixAppls = new int[EAG.NextVar]; 311 for (size_t i = SOAG.firstRule; i < SOAG.NextRule; ++i) 312 { 313 LocalVars[i] = 0; 314 AffixVarCount[i] = -1; 315 } 316 for (size_t i = EAG.firstNode; i < EAG.NextNode; ++i) 317 { 318 NodeName[i] = -1; 319 } 320 for (size_t i = EAG.firstVar; i < EAG.NextVar; ++i) 321 { 322 EAG.Var[i].Def = false; 323 AffixAppls[i] = SOAG.AffixApplCnt[i]; 324 } 325 for (R = SOAG.firstRule; R < SOAG.NextRule; ++R) 326 { 327 Offset = 0; 328 for (SO = SOAG.Rule[R].SymOcc.Beg + 1; SO <= SOAG.Rule[R].SymOcc.End; ++SO) 329 { 330 if (!SOAG.IsPredNont(SO)) 331 { 332 ++Offset; 333 SubTreeOffset[SO] = Offset; 334 } 335 } 336 } 337 for (S = SOAG.firstSym; S < SOAG.NextSym; ++S) 338 { 339 SO = SOAG.Sym[S].FirstOcc; 340 if (SO != SOAG.nil) 341 { 342 R = SOAG.SymOcc[SO].RuleInd; 343 while (SO != SOAG.Rule[R].SymOcc.Beg) 344 { 345 SO = SOAG.SymOcc[SO].Next; 346 R = SOAG.SymOcc[SO].RuleInd; 347 } 348 SO = SOAG.SymOcc[SO].Next; 349 while (R >= SOAG.firstRule && S == SOAG.SymOcc[SOAG.Rule[R].SymOcc.Beg].SymInd) 350 { 351 FirstRule[S] = R; 352 --R; 353 } 354 } 355 } 356 } 357 358 private void GenHeapInc(int n) @safe 359 { 360 if (n != 0) 361 { 362 if (n == 1) 363 output.writeln("++NextHeap;"); 364 else 365 output.writeln("NextHeap += ", n, ";"); 366 } 367 } 368 369 private void GenVar(int Var) @safe 370 { 371 output.write("V", Var); 372 } 373 374 private void GenHeap(int Var, int Offset) @safe 375 { 376 output.write("Heap["); 377 if (Var > 0) 378 GenVar(Var); 379 else 380 output.write("NextHeap"); 381 if (Offset > 0) 382 output.write(" + ", Offset); 383 else if (Offset < 0) 384 output.write(" - ", -Offset); 385 output.write("]"); 386 } 387 388 private void GenOverflowGuard(int n) @safe 389 { 390 if (n > 0) 391 output.writeln("if (NextHeap >= Heap.length - ", n, ") EvalExpand;"); 392 } 393 394 /** 395 * IN: Symbol, Nummer eines Affixparameter relativ zum Symbolvorkommen 396 * OUT: - 397 * SEM: Generierung eines Zugriffs auf die Instanz einer Affixposition 398 */ 399 private void GenAffPos(int S, int AN) @safe 400 { 401 output.write("AffPos[S", S, " + ", AN, "]"); 402 } 403 404 /** 405 * IN: Affixnummer 406 * OUT: - 407 * SEM: Generiert einen Zugriff auf den Inhalt eines Affixes 408 */ 409 private void GenAffix(int V) @safe 410 in (AffixOffset[V] != notApplied) 411 { 412 int AP; 413 414 if (AffixOffset[V] == optimizedStorage) 415 { 416 AP = GetCorrespondedAffPos(SOAG.DefAffOcc[V]); 417 if (SOAG.StorageName[AP] > 0) 418 output.write("Stacks.Top(Stack", SOAG.StorageName[AP], ") "); 419 else 420 output.write("GV", -SOAG.StorageName[AP]); 421 } 422 else 423 { 424 output.write("Var[VI + ", AffixOffset[V], "]"); 425 } 426 } 427 428 /** 429 * IN: Affix 430 * OUT: - 431 * SEM: Generierung einer Zuweisung zu einer Instanz einer Affixvariable; 432 * nur in Kombination mit der Prozedur GenClose zu verwenden 433 */ 434 private void GenAffixAssign(int V) @safe 435 in (AffixOffset[V] != notApplied) 436 { 437 int AP; 438 439 if (AffixOffset[V] == optimizedStorage) 440 { 441 AP = GetCorrespondedAffPos(SOAG.DefAffOcc[V]); 442 if (SOAG.StorageName[AP] > 0) 443 { 444 output.write("Stacks.Push(Stack", SOAG.StorageName[AP], ", "); 445 Close = true; 446 } 447 else 448 { 449 output.write("GV", -SOAG.StorageName[AP], " = "); 450 Close = false; 451 } 452 } 453 else 454 { 455 output.write("Var[VI + ", AffixOffset[V], "] = "); 456 Close = false; 457 } 458 } 459 460 private void GenClose() @safe 461 { 462 if (Close) 463 output.write(");"); 464 else 465 output.write(";"); 466 } 467 468 /** 469 * IN: Affixvariable oder (< 0) lokale Variable 470 * OUT: - 471 * SEM: Generiert eine Erhöhung des Referenzzählers des Knotens auf den das Affixes 472 * bzw. der Index verweist, im Falle eines Stacks wird globale Var. RefIncVar verwendet 473 */ 474 private void GenIncRefCnt(int Var) @safe 475 { 476 output.write("Heap["); 477 if (Var < 0) 478 GenVar(-Var); 479 else 480 GenAffix(Var); 481 output.writeln("] += refConst;"); 482 } 483 484 /** 485 * IN: Affixvariable 486 * OUT: - 487 * SEM: generiert die Freigabe des alloziierten Speichers, 488 * wenn die Affixvariable das letzte mal appliziert wurde (AffixAppls = 0) 489 */ 490 private void GenFreeAffix(int V) @safe 491 { 492 if (AffixAppls[V] == 0) 493 { 494 output.write("FreeHeap("); 495 GenAffix(V); 496 output.writeln(");"); 497 } 498 } 499 500 /** 501 * IN: Affixvariable 502 * OUT: - 503 * SEM: generiert die Kellerspeicherfreigabe, 504 * wenn die Affixvariable das letzte mal appliziert wurde (AffixAppls = 0) 505 */ 506 private void GenPopAffix(int V) @safe 507 { 508 if (AffixAppls[V] == 0) 509 { 510 if (AffixOffset[V] == optimizedStorage) 511 { 512 const AP = GetCorrespondedAffPos(SOAG.DefAffOcc[V]); 513 514 if (SOAG.StorageName[AP] > 0) 515 output.writeln("Stacks.Pop(Stack", SOAG.StorageName[AP], ");"); 516 else 517 output.writeln("GV", -SOAG.StorageName[AP], " = -1;"); 518 } 519 } 520 } 521 522 /** 523 * IN: Symbolvorkommen 524 * OUT: - 525 * SEM: Generierung der Syntheseaktionen eines Besuchs für die besuchsrelevanten Affixparameter eines Symbolvorkommens 526 */ 527 private void GenSynPred(int SymOccInd, int VisitNo) 528 { 529 int Node; 530 int S; 531 int Offset; 532 int AP; 533 int AN; 534 int V; 535 int SN; 536 int P; 537 bool IsPred; 538 539 /** 540 * IN: Knoten des Affixbaumes, Offset des nächsten freien Heap-Elementes 541 * OUT: - 542 * SEM: Traversierung eines Affixbaumes und Ausgabe der Syntheseaktionen für den zu generierenden Compiler 543 */ 544 void GenSynTraverse(int Node, ref int Offset) 545 { 546 int Offset1; 547 int Node1; 548 int n; 549 int V; 550 const Alt = EAG.NodeBuf[Node]; 551 552 GenHeap(-1, Offset); 553 output.writeln(" = ", SLAGGen.NodeIdent[Alt], ";"); 554 Offset1 = Offset; 555 Offset += 1 + EAG.MAlt[Alt].Arity; 556 for (n = 1; n <= EAG.MAlt[Alt].Arity; ++n) 557 { 558 Node1 = EAG.NodeBuf[Node + n]; 559 if (Node1 < 0) 560 { 561 V = -Node1; 562 if (!EAG.Var[V].Def) 563 { 564 SOAG.Error(SOAG.abnormalError, "eSOAGGen.GenSynTraverse: Affix nicht definiert."); 565 } 566 else 567 { 568 GenHeap(-1, Offset1 + n); 569 output.write(" = "); 570 GenAffix(V); 571 output.writeln(";"); 572 --AffixAppls[V]; 573 if (UseRefCnt) 574 GenFreeAffix(V); 575 if (Optimize) 576 GenPopAffix(V); 577 } 578 } 579 else 580 { 581 GenHeap(-1, Offset1 + n); 582 output.write(" = "); 583 if (UseConst && EAG.MAlt[EAG.NodeBuf[Node1]].Arity == 0) 584 { 585 output.writeln(SLAGGen.Leaf[EAG.NodeBuf[Node1]], ";"); 586 } 587 else 588 { 589 output.writeln("NextHeap + ", Offset, ";"); 590 GenSynTraverse(Node1, Offset); 591 } 592 } 593 } 594 } 595 596 /** 597 * IN: Knoten des Affixbaumes 598 * OUT: - 599 * SEM: Traversierung eines Affixbaumes und Ausgabe der Syntheseaktionen mit Referenzzähler-Verfahren 600 * für den zu generierenden Compiler 601 */ 602 void GenSynTraverseRefCnt(int Node) 603 { 604 int Node1; 605 int n; 606 int V; 607 const Alt = EAG.NodeBuf[Node]; 608 609 GenHeap(NodeName[Node], 0); 610 output.writeln(" = ", SLAGGen.NodeIdent[Alt], ";"); 611 for (n = 1; n <= EAG.MAlt[Alt].Arity; ++n) 612 { 613 Node1 = EAG.NodeBuf[Node + n]; 614 if (Node1 < 0) 615 { 616 V = -Node1; 617 if (!EAG.Var[V].Def) 618 { 619 SOAG.Error(SOAG.abnormalError, "eSOAGGen.GenSynTraverse: Affix nicht definiert."); 620 } 621 else 622 { 623 GenHeap(NodeName[Node], n); 624 output.write(" = "); 625 GenAffix(V); 626 output.write("; "); 627 --AffixAppls[V]; 628 if (AffixAppls[V] > 0) 629 GenIncRefCnt(V); 630 else 631 output.writeln("// komplementäre Referenzzählerbehandlung"); 632 if (Optimize) 633 GenPopAffix(V); 634 } 635 } 636 else 637 { 638 if (UseConst && EAG.MAlt[EAG.NodeBuf[Node1]].Arity == 0) 639 { 640 GenHeap(NodeName[Node], n); 641 output.write(" = ", SLAGGen.Leaf[EAG.NodeBuf[Node1]], "; "); 642 output.writeln("Heap[", SLAGGen.Leaf[EAG.NodeBuf[Node1]], "] += refConst;"); 643 } 644 else 645 { 646 output.write("GetHeap(", EAG.MAlt[EAG.NodeBuf[Node1]].Arity, ", "); 647 GenVar(NodeName[Node1]); 648 output.writeln(");"); 649 GenSynTraverseRefCnt(Node1); 650 GenHeap(NodeName[Node], n); 651 output.write(" = "); 652 GenVar(NodeName[Node1]); 653 output.writeln(";"); 654 } 655 } 656 } 657 } 658 659 S = SOAG.SymOcc[SymOccInd].SymInd; 660 IsPred = VisitNo == -1; 661 for (AP = SOAG.SymOcc[SymOccInd].AffOcc.Beg; AP <= SOAG.SymOcc[SymOccInd].AffOcc.End; 662 ++AP) 663 { 664 AN = AP - SOAG.SymOcc[SymOccInd].AffOcc.Beg; 665 P = SOAG.AffOcc[AP].ParamBufInd; 666 if (!EAG.ParamBuf[P].isDef && (VisitSeq.GetVisitNo(AP) == VisitNo || IsPred)) 667 { 668 Node = EAG.ParamBuf[P].Affixform; 669 SN = SymOccInd - SOAG.Rule[SOAG.SymOcc[SymOccInd].RuleInd].SymOcc.Beg; 670 if (Node < 0) 671 { 672 V = -Node; 673 if (!EAG.Var[V].Def) 674 { 675 SOAG.Error(SOAG.abnormalError, "eSOAGGen.GenSynTraverse: Affix nicht definiert."); 676 } 677 else if (!IsPred) 678 { 679 GenAffPos(S, AN); 680 output.write(" = "); 681 GenAffix(V); 682 output.write("; "); 683 --AffixAppls[V]; 684 if (UseRefCnt && AffixAppls[V] > 0) 685 GenIncRefCnt(V); 686 else 687 output.writeln("// komplementäre Referenzzählerbehandlung"); 688 if (Optimize) 689 GenPopAffix(V); 690 output.writeln; 691 } 692 } 693 else 694 { 695 if (UseConst && SLAGGen.AffixPlace[P] >= 0) 696 { 697 GenAffPos(S, AN); 698 output.write(" = ", SLAGGen.AffixPlace[P]); 699 if (UseRefCnt) 700 output.write("; Heap[", SLAGGen.AffixPlace[P], "] += refConst"); 701 output.writeln(";"); 702 } 703 else if (UseRefCnt) 704 { 705 output.write("GetHeap(", EAG.MAlt[EAG.NodeBuf[Node]].Arity, ", "); 706 GenVar(NodeName[Node]); 707 output.writeln(");"); 708 GenSynTraverseRefCnt(Node); 709 GenAffPos(S, AN); 710 output.write(" = "); 711 GenVar(NodeName[Node]); 712 output.writeln(";"); 713 } 714 else 715 { 716 GenOverflowGuard(SLAGGen.AffixSpace[P]); 717 GenAffPos(S, AN); 718 output.writeln(" = NextHeap;"); 719 Offset = 0; 720 GenSynTraverse(Node, Offset); 721 GenHeapInc(Offset); 722 } 723 } 724 } 725 } 726 } 727 728 /** 729 * IN: Symbolvorkommen, Visit-Nummer 730 * OUT: - 731 * SEM: Generierung der Analyseaktionen eines Besuchs für die besuchsrelevanten Affixparameter eines Symbolvorkommens 732 */ 733 private void GenAnalPred(int SymOccInd, int VisitNo) @safe 734 { 735 int S; 736 int AP; 737 int AN; 738 int Node; 739 int V; 740 int SN; 741 bool IsPred; 742 bool PosNeeded; 743 744 void GenEqualErrMsg(int Var) 745 { 746 output.write(`"'`); 747 output.write(EAG.VarRepr(Var)); 748 output.write("' failed in '"); 749 output.write(EAG.NamedHNontRepr(SOAG.SymOcc[SymOccInd].SymInd)); 750 output.write(`'"`); 751 } 752 753 void GenAnalErrMsg() 754 { 755 output.write(`"`); 756 output.write(EAG.NamedHNontRepr(SOAG.SymOcc[SymOccInd].SymInd)); 757 output.write(`"`); 758 } 759 760 /** 761 * IN: Index auf EAG.Var[] des def. Affixes, Index auf NodeName[] und Nr. des Sohnes im Heap 762 * OUT: - 763 * SEM: Generiert einen Vergleich zwischen einer Variable eines def. Affixes und einem Baumeintrag 764 */ 765 void GenEqualPred(int V, int Node, int n) 766 { 767 output.write("Eq("); 768 GenHeap(NodeName[Node], n); 769 output.write(", "); 770 GenAffix(V); 771 output.write(", "); 772 GenEqualErrMsg(V); 773 output.writeln(");"); 774 } 775 776 /** 777 * IN: zwei Indexe auf EAG.Var[] 778 * OUT: - 779 * SEM: Generiert einen Vergleich zwischen zwei Variablen der Felder Var[] (gen. Compiler) 780 */ 781 void GenUnequalPred(int V1, int V2) 782 { 783 output.write("UnEq("); 784 GenAffix(V1); 785 output.write(", "); 786 GenAffix(V2); 787 output.write(", "); 788 if (EAG.Var[V1].Num < 0) 789 GenEqualErrMsg(V1); 790 else 791 GenEqualErrMsg(V2); 792 output.writeln(");"); 793 } 794 795 /** 796 * SEM: Generierung einer Positionszuweisung, wenn notwendig 797 */ 798 void GenPos(ref bool PosNeeded) 799 { 800 if (PosNeeded) 801 { 802 output.writeln("Pos = SemTree[TreeAdr + ", SubTreeOffset[SymOccInd], "].Pos;"); 803 PosNeeded = false; 804 } 805 } 806 807 /** 808 * IN: Knoten des Affixbaumes 809 * OUT: - 810 * SEM: Traversierung eines Affixbaumes und Ausgabe der Analyseaktionen für den zu generierenden Compiler 811 */ 812 void GenAnalTraverse(int Node) 813 { 814 int Node1; 815 int n; 816 int V; 817 const Alt = EAG.NodeBuf[Node]; 818 819 output.write("if ("); 820 if (UseConst && EAG.MAlt[Alt].Arity == 0) 821 { 822 GenVar(NodeName[Node]); 823 output.write(" != ", SLAGGen.Leaf[Alt]); 824 } 825 else 826 { 827 GenHeap(NodeName[Node], 0); 828 if (UseRefCnt) 829 output.write(".MOD(refConst)"); 830 output.write(" != ", SLAGGen.NodeIdent[Alt]); 831 } 832 output.write(") AnalyseError("); 833 GenVar(NodeName[Node]); 834 output.write(", "); 835 GenAnalErrMsg; 836 output.writeln(");"); 837 for (n = 1; n <= EAG.MAlt[Alt].Arity; ++n) 838 { 839 Node1 = EAG.NodeBuf[Node + n]; 840 if (Node1 < 0) 841 { 842 V = -Node1; 843 if (EAG.Var[V].Def) 844 { 845 GenEqualPred(V, Node, n); 846 --AffixAppls[V]; 847 if (UseRefCnt) 848 GenFreeAffix(V); 849 if (Optimize) 850 GenPopAffix(V); 851 } 852 else 853 { 854 EAG.Var[V].Def = true; 855 if (AffixOffset[V] != notApplied) 856 { 857 GenAffixAssign(V); 858 GenHeap(NodeName[Node], n); 859 GenClose; 860 if (EAG.Var[EAG.Var[V].Neg].Def) 861 { 862 output.writeln; 863 GenUnequalPred(EAG.Var[V].Neg, V); 864 --AffixAppls[EAG.Var[V].Neg]; 865 --AffixAppls[V]; 866 if (UseRefCnt && AffixAppls[V] > 0) 867 GenIncRefCnt(V); 868 if (UseRefCnt) 869 GenFreeAffix(EAG.Var[V].Neg); 870 if (Optimize) 871 { 872 GenPopAffix(EAG.Var[V].Neg); 873 GenPopAffix(V); 874 } 875 } 876 else if (UseRefCnt) 877 { 878 GenIncRefCnt(V); 879 } 880 } 881 } 882 } 883 else 884 { 885 GenVar(NodeName[Node1]); 886 output.write(" = "); 887 GenHeap(NodeName[Node], n); 888 output.writeln(";"); 889 GenAnalTraverse(Node1); 890 } 891 } 892 } 893 894 S = SOAG.SymOcc[SymOccInd].SymInd; 895 IsPred = VisitNo == -1; 896 PosNeeded = !IsPred; 897 for (AP = SOAG.SymOcc[SymOccInd].AffOcc.Beg; AP <= SOAG.SymOcc[SymOccInd].AffOcc.End; 898 ++AP) 899 { 900 AN = AP - SOAG.SymOcc[SymOccInd].AffOcc.Beg; 901 if (EAG.ParamBuf[SOAG.AffOcc[AP].ParamBufInd].isDef 902 && (VisitSeq.GetVisitNo(AP) == VisitNo || IsPred)) 903 { 904 Node = EAG.ParamBuf[SOAG.AffOcc[AP].ParamBufInd].Affixform; 905 SN = SymOccInd - SOAG.Rule[SOAG.SymOcc[SymOccInd].RuleInd].SymOcc.Beg; 906 if (Node < 0) 907 { 908 V = -Node; 909 if (EAG.Var[V].Def) 910 { 911 GenPos(PosNeeded); 912 output.write("Eq("); 913 GenAffPos(S, AN); 914 output.write(", "); 915 GenAffix(V); 916 output.write(", "); 917 GenEqualErrMsg(V); 918 output.writeln(");"); 919 --AffixAppls[V]; 920 if (UseRefCnt) 921 GenFreeAffix(V); 922 if (Optimize) 923 GenPopAffix(V); 924 if (UseRefCnt) 925 { 926 output.write("FreeHeap("); 927 GenAffPos(S, AN); 928 output.writeln(");"); 929 } 930 } 931 else 932 { 933 EAG.Var[V].Def = true; 934 if (!IsPred) 935 { 936 if (AffixOffset[V] != notApplied) 937 { 938 GenAffixAssign(V); 939 GenAffPos(S, AN); 940 GenClose; 941 if (UseRefCnt) 942 output.write(" // komplementäre Referenzzählerbehandlung"); 943 output.writeln; 944 } 945 } 946 if (EAG.Var[EAG.Var[V].Neg].Def) 947 { 948 GenPos(PosNeeded); 949 output.write("UnEq("); 950 GenAffix(EAG.Var[V].Neg); 951 output.write(", "); 952 GenAffix(V); 953 output.write(", "); 954 GenEqualErrMsg(V); 955 output.writeln(");"); 956 --AffixAppls[EAG.Var[V].Neg]; 957 --AffixAppls[V]; 958 if (UseRefCnt) 959 { 960 GenFreeAffix(EAG.Var[V].Neg); 961 GenFreeAffix(V); 962 } 963 if (Optimize) 964 { 965 GenPopAffix(EAG.Var[V].Neg); 966 GenPopAffix(V); 967 } 968 } 969 } 970 } 971 else 972 { 973 GenPos(PosNeeded); 974 GenVar(NodeName[Node]); 975 output.write(" = "); 976 GenAffPos(S, AN); 977 output.writeln(";"); 978 GenAnalTraverse(Node); 979 if (UseRefCnt) 980 { 981 output.write("FreeHeap("); 982 GenAffPos(S, AN); 983 output.writeln(");"); 984 } 985 } 986 } 987 } 988 } 989 990 /** 991 * IN: Symbolvorkommen, Visit-Nummer 992 * OUT: - 993 * SEM: Generierung eines Aufrufes der Prozedur 'Visit' für den zu generierenden Compiler 994 */ 995 private void GenVisitCall(int SO, int VisitNo) @safe 996 { 997 output.writeln("Visit(TreeAdr + ", SubTreeOffset[SO], ", ", VisitNo, ");"); 998 } 999 1000 /** 1001 * SEM: generiert nur Kommentar 1002 */ 1003 private void GenLeave(int VisitNo) @safe 1004 { 1005 output.writeln("// Leave; VisitNo: ", VisitNo); 1006 } 1007 1008 /** 1009 * IN: Symbolvorkommen eines Prädikates 1010 * OUT: - 1011 * SEM: Generierung des Aufrufes einer Prädikatprozedur 1012 */ 1013 private void GenPredCall(int SO) @safe 1014 { 1015 int S; 1016 int AP; 1017 int AN; 1018 int AP1; 1019 int Node; 1020 int V; 1021 1022 if (UseRefCnt) 1023 { 1024 for (AP = SOAG.SymOcc[SO].AffOcc.Beg; AP <= SOAG.SymOcc[SO].AffOcc.End; ++AP) 1025 { 1026 if (!EAG.ParamBuf[SOAG.AffOcc[AP].ParamBufInd].isDef) 1027 { 1028 AN = AP - SOAG.SymOcc[SO].AffOcc.Beg; 1029 V = -EAG.ParamBuf[SOAG.AffOcc[AP].ParamBufInd].Affixform; 1030 if (V > 0) 1031 GenIncRefCnt(V); 1032 } 1033 } 1034 } 1035 S = SOAG.SymOcc[SO].SymInd; 1036 output.write("Check", S, `("`); 1037 output.write(EAG.NamedHNontRepr(S)); 1038 output.write(`", `); 1039 for (AP = SOAG.SymOcc[SO].AffOcc.Beg; AP <= SOAG.SymOcc[SO].AffOcc.End; ++AP) 1040 { 1041 Node = EAG.ParamBuf[SOAG.AffOcc[AP].ParamBufInd].Affixform; 1042 AN = AP - SOAG.SymOcc[SO].AffOcc.Beg; 1043 V = -Node; 1044 if (EAG.ParamBuf[SOAG.AffOcc[AP].ParamBufInd].isDef) 1045 { 1046 if (V > 0 && SOAG.DefAffOcc[V] == AP) 1047 { 1048 if (Optimize && AffixOffset[V] == optimizedStorage) 1049 { 1050 AP1 = GetCorrespondedAffPos(SOAG.DefAffOcc[V]); 1051 if (SOAG.StorageName[AP1] > 0) 1052 GenAffPos(S, AN); 1053 else 1054 output.write("GV", -SOAG.StorageName[AP1]); 1055 } 1056 else if (AffixOffset[V] == notApplied) 1057 { 1058 GenAffPos(S, AN); 1059 } 1060 else 1061 { 1062 GenAffix(V); 1063 } 1064 } 1065 else 1066 { 1067 GenAffPos(S, AN); 1068 } 1069 } 1070 else 1071 { 1072 if (Node > 0) 1073 GenAffPos(S, AN); 1074 else 1075 GenAffix(V); 1076 } 1077 if (AP != SOAG.SymOcc[SO].AffOcc.End) 1078 output.write(", "); 1079 else 1080 output.writeln(");"); 1081 } 1082 for (AP = SOAG.SymOcc[SO].AffOcc.Beg; AP <= SOAG.SymOcc[SO].AffOcc.End; ++AP) 1083 { 1084 AN = AP - SOAG.SymOcc[SO].AffOcc.Beg; 1085 V = -EAG.ParamBuf[SOAG.AffOcc[AP].ParamBufInd].Affixform; 1086 if (V > 0) 1087 { 1088 if (EAG.ParamBuf[SOAG.AffOcc[AP].ParamBufInd].isDef) 1089 { 1090 if (AffixOffset[V] == optimizedStorage) 1091 { 1092 AP1 = GetCorrespondedAffPos(SOAG.DefAffOcc[V]); 1093 if (SOAG.StorageName[AP1] > 0) 1094 { 1095 output.write("Stacks.Push(Stack", SOAG.StorageName[AP1], ", "); 1096 GenAffPos(S, AN); 1097 output.writeln(");"); 1098 } 1099 } 1100 else if (AffixOffset[V] == notApplied) 1101 { 1102 output.write("FreeHeap("); 1103 GenAffPos(S, AN); 1104 output.writeln("); // Dummy-Variable"); 1105 } 1106 } 1107 else 1108 { 1109 --AffixAppls[V]; 1110 if (UseRefCnt) 1111 GenFreeAffix(V); 1112 if (Optimize) 1113 GenPopAffix(V); 1114 } 1115 } 1116 } 1117 } 1118 1119 /** 1120 * IN: Regel 1121 * OUT: - 1122 * SEM: Generierung der Variablendeklarationen einer Regel 1123 */ 1124 private void GenVarDecls(int R) @safe 1125 { 1126 output.writeln("IndexType TreeAdr;"); 1127 output.writeln("IndexType VI;"); 1128 output.writeln("SemTreeEntry S;"); 1129 if (LocalVars[R] > 0) 1130 { 1131 for (int i = 1; i <= LocalVars[R]; ++i) 1132 { 1133 output.write("HeapType "); 1134 GenVar(i); 1135 output.writeln(";"); 1136 } 1137 } 1138 } 1139 1140 /** 1141 * IN: Regel, Nummer des Visit-Sequenz-Eintrages, Notwendigkeit der Positionszuweisung 1142 * OUT: - 1143 * SEM: Generierung der Positionszuweisung vor Prädikatprozeduraufrufen; 1144 * zugewiesen wird die Position des vorhergehenden Visits 1145 */ 1146 private void GenPredPos(int R, int i, ref bool PosNeeded) @safe 1147 { 1148 int k; 1149 1150 if (PosNeeded) 1151 { 1152 --i; 1153 while (cast(SOAG.Visit) SOAG.VS[i] is null && cast(SOAG.Leave) SOAG.VS[i] is null && i > SOAG.Rule[R].VS.Beg) 1154 --i; 1155 if (auto visit = cast(SOAG.Visit) SOAG.VS[i]) 1156 k = SubTreeOffset[visit.SymOcc]; 1157 else 1158 k = SOAG.Rule[R].SymOcc.Beg; 1159 output.writeln("Pos = SemTree[TreeAdr + ", k, "].Pos;"); 1160 PosNeeded = false; 1161 } 1162 } 1163 1164 /** 1165 * IN: Regelnummer 1166 * OUT: - 1167 * SEM: Generiert Code für die Visit-Sequenzen einer Regel 1168 */ 1169 private void GenVisitRule(int R) 1170 { 1171 int SO; 1172 int VN; 1173 int VisitNo; 1174 int i; 1175 int S; 1176 int NontCnt; 1177 bool onlyoneVisit; 1178 bool first; 1179 bool PosNeeded; 1180 1181 output.writeln("void VisitRule", R, "(long Symbol, int VisitNo)"); 1182 output.writeln("/*"); 1183 Protocol.output = output; 1184 output.write(" * "); 1185 Protocol.WriteRule(R); 1186 output.writeln(" */"); 1187 Protocol.output = stdout; 1188 output.writeln("{"); 1189 GenVarDecls(R); 1190 NontCnt = 1; 1191 for (SO = SOAG.Rule[R].SymOcc.Beg + 1; SO <= SOAG.Rule[R].SymOcc.End; ++SO) 1192 if (!SOAG.IsPredNont(SO)) 1193 ++NontCnt; 1194 SO = SOAG.Rule[R].SymOcc.Beg; 1195 output.writeln("if (VisitNo == syntacticPart)"); 1196 output.writeln("{"); 1197 output.writeln("if (NextSemTree >= SemTree.length - ", NontCnt, ") ExpandSemTree;"); 1198 output.writeln("TreeAdr = SemTree[Symbol].Adr;"); 1199 output.writeln("SemTree[Symbol].Adr = NextSemTree;"); 1200 output.writeln("SemTree[Symbol].Pos = PosTree[TreeAdr];"); 1201 output.writeln("AffixVarCount += ", GetAffixCount(R), ";"); 1202 if (AffixVarCount[R] > 0) 1203 { 1204 output.writeln("if (NextVar >= Var.length - ", AffixVarCount[R], ") ExpandVar;"); 1205 output.writeln("SemTree[Symbol].VarInd = NextVar; NextVar += ", AffixVarCount[R], ";"); 1206 } 1207 else 1208 { 1209 output.writeln("SemTree[Symbol].VarInd = nil;"); 1210 } 1211 output.writeln("SemTree[NextSemTree] = SemTree[Symbol];"); 1212 output.writeln("++NextSemTree;"); 1213 for (SO = SOAG.Rule[R].SymOcc.Beg + 1; SO <= SOAG.Rule[R].SymOcc.End; ++SO) 1214 { 1215 if (!SOAG.IsPredNont(SO)) 1216 { 1217 output.writeln("S = new SemTreeEntry;"); 1218 output.writeln("S.Adr = Tree[TreeAdr + ", SubTreeOffset[SO], "];"); 1219 output.writeln("S.Rule = ", FirstRule[SOAG.SymOcc[SO].SymInd] - 1, " + MOD(Tree[S.Adr], hyperArityConst);"); 1220 output.writeln("SemTree[NextSemTree] = S; ++NextSemTree;"); 1221 } 1222 } 1223 first = true; 1224 for (SO = SOAG.Rule[R].SymOcc.Beg + 1; SO <= SOAG.Rule[R].SymOcc.End; ++SO) 1225 { 1226 if (!SOAG.IsPredNont(SO)) 1227 { 1228 if (first) 1229 { 1230 output.writeln("TreeAdr = SemTree[Symbol].Adr;"); 1231 first = false; 1232 } 1233 output.writeln("Visit(TreeAdr + ", SubTreeOffset[SO], ", syntacticPart);"); 1234 } 1235 } 1236 output.writeln("}"); 1237 output.writeln("else"); 1238 output.writeln("{"); 1239 output.writeln("TreeAdr = SemTree[Symbol].Adr;"); 1240 if (AffixVarCount[R] > 0) 1241 output.writeln("VI = SemTree[Symbol].VarInd;"); 1242 if (VisitSeq.GetMaxVisitNo(SOAG.Rule[R].SymOcc.Beg) == 1) 1243 { 1244 onlyoneVisit = true; 1245 } 1246 else 1247 { 1248 onlyoneVisit = false; 1249 output.writeln("switch (VisitNo)"); 1250 output.writeln("{"); 1251 output.writeln("case 1:"); 1252 } 1253 VisitNo = 1; 1254 PosNeeded = true; 1255 output.writeln("// Visit-beginnende Analyse"); 1256 GenAnalPred(SOAG.Rule[R].SymOcc.Beg, VisitNo); 1257 for (i = SOAG.Rule[R].VS.Beg; i <= SOAG.Rule[R].VS.End; ++i) 1258 { 1259 if (auto visit = cast(SOAG.Visit) SOAG.VS[i]) 1260 { 1261 SO = visit.SymOcc; 1262 S = SOAG.SymOcc[SO].SymInd; 1263 VN = visit.VisitNo; 1264 output.writeln("// Synthese"); 1265 GenSynPred(SO, VN); 1266 GenVisitCall(SO, VN); 1267 output.writeln("// Analyse"); 1268 GenAnalPred(SO, VN); 1269 output.writeln; 1270 PosNeeded = true; 1271 } 1272 else if (auto call = cast(SOAG.Call) SOAG.VS[i]) 1273 { 1274 SO = call.SymOcc; 1275 output.writeln("// Synthese"); 1276 GenSynPred(SO, -1); 1277 GenPredPos(R, i, PosNeeded); 1278 GenPredCall(SO); 1279 output.writeln("// Analyse"); 1280 GenAnalPred(SO, -1); 1281 output.writeln; 1282 } 1283 else if (auto leave = cast(SOAG.Leave) SOAG.VS[i]) 1284 { 1285 SO = SOAG.Rule[R].SymOcc.Beg; 1286 VN = leave.VisitNo; 1287 1288 assert(VN == VisitNo); 1289 1290 output.writeln("// Visit-abschließende Synthese"); 1291 GenSynPred(SO, VisitNo); 1292 GenLeave(VisitNo); 1293 if (VisitNo < VisitSeq.GetMaxVisitNo(SO)) 1294 { 1295 output.writeln("break;"); 1296 ++VisitNo; 1297 PosNeeded = true; 1298 output.writeln("case ", VisitNo, ":"); 1299 output.writeln("// Visit-beginnende Analyse"); 1300 GenAnalPred(SO, VisitNo); 1301 } 1302 else 1303 { 1304 if (!onlyoneVisit) 1305 output.writeln("break;"); 1306 } 1307 } 1308 } 1309 if (!onlyoneVisit) 1310 { 1311 output.writeln("default:"); 1312 output.writeln("assert(0);"); 1313 output.writeln("}"); 1314 } 1315 output.writeln("}"); 1316 output.writeln("}"); 1317 output.writeln; 1318 } 1319 1320 /** 1321 * SEM: Generierung der Prozedur 'Visit', die die Besuche auf die entsprechenden Regeln verteilt 1322 */ 1323 private void GenVisit() 1324 { 1325 output.writeln("void Visit(long Symbol, int VisitNo)"); 1326 output.writeln("{"); 1327 output.writeln("switch (SemTree[Symbol].Rule)"); 1328 output.writeln("{"); 1329 for (int R = SOAG.firstRule; R < SOAG.NextRule; ++R) 1330 { 1331 if (SOAG.IsEvaluatorRule(R)) 1332 { 1333 output.write("case ", R, ": "); 1334 output.writeln("VisitRule", R, "(Symbol, VisitNo); break;"); 1335 } 1336 } 1337 output.writeln("default:"); 1338 output.writeln("assert(0);"); 1339 output.writeln("}"); 1340 output.writeln("}"); 1341 output.writeln; 1342 } 1343 1344 /** 1345 * SEM: Generierung der Konstanten für den Zugriff auf AffPos[] im generierten Compiler 1346 */ 1347 private void GenConstDeclarations() @safe 1348 { 1349 for (int S = SOAG.firstSym; S < SOAG.NextSym; ++S) 1350 { 1351 output.write("const S", S, " = "); 1352 output.write(SOAG.Sym[S].AffPos.Beg, "; // "); 1353 output.write(EAG.HNontRepr(S)); 1354 output.writeln; 1355 } 1356 } 1357 1358 /** 1359 * SEM: Generierung der Deklarationen der globalen Variablen und Stacks 1360 */ 1361 private void GenStackDeclarations() @safe 1362 { 1363 if (optimizer.GlobalVar > 0 || optimizer.StackVar > 0) 1364 { 1365 for (int V = optimizer.firstGlobalVar; V <= optimizer.GlobalVar; ++V) 1366 output.writeln("HeapType GV", V, ";"); 1367 for (int V = optimizer.firstStackVar; V <= optimizer.StackVar; ++V) 1368 output.writeln("Stacks.Stack Stack", V, ";"); 1369 output.writeln; 1370 } 1371 } 1372 1373 /** 1374 * SEM: Generierung der Initialisierungen der Stacks 1375 */ 1376 private void GenStackInit() @safe 1377 { 1378 if (optimizer.StackVar > 0) 1379 { 1380 for (int S = optimizer.firstStackVar; S <= optimizer.StackVar; ++S) 1381 output.writeln("Stacks.New(Stack", S, ", 8);"); 1382 } 1383 } 1384 1385 /** 1386 * SEM: Generierung des Compiler-Moduls 1387 */ 1388 private string GenerateModule(Settings settings) 1389 { 1390 int R; 1391 Input Fix; 1392 int StartRule; 1393 1394 void InclFix(char Term) 1395 { 1396 import std.conv : to; 1397 import std.exception : enforce; 1398 1399 char c = Fix.front.to!char; 1400 1401 while (c != Term) 1402 { 1403 enforce(c != 0, 1404 "error: unexpected end of eSOAG.fix.d"); 1405 1406 output.write(c); 1407 Fix.popFront; 1408 c = Fix.front.to!char; 1409 } 1410 Fix.popFront; 1411 } 1412 1413 enum fixName = "soag.fix.d"; 1414 const name = EAG.BaseName ~ "Eval"; 1415 const fileName = settings.path(name ~ ".d"); 1416 1417 Fix = Input(fixName, import(fixName)); 1418 output = File(fileName, "w"); 1419 SLAGGen.InitGen(output, SLAGGen.sweepPass, settings); 1420 InclFix('$'); 1421 output.write(name); 1422 InclFix('$'); 1423 output.write(HyperArity()); 1424 InclFix('$'); 1425 GenConstDeclarations; 1426 InclFix('$'); 1427 if (Optimize) 1428 GenStackDeclarations; 1429 SLAGGen.GenDeclarations(settings); 1430 InclFix('$'); 1431 SLAGGen.GenPredProcs; 1432 for (R = SOAG.firstRule; R < SOAG.NextRule; ++R) 1433 { 1434 if (SOAG.IsEvaluatorRule(R)) 1435 { 1436 ComputeNodeNames(R); 1437 ComputeAffixOffset(R); 1438 GenVisitRule(R); 1439 } 1440 } 1441 GenVisit; 1442 EmitGen.GenEmitProc(output, settings); 1443 InclFix('$'); 1444 output.write(SOAG.NextPartNum); 1445 InclFix('$'); 1446 if (Optimize) 1447 GenStackInit; 1448 StartRule = FirstRule[SOAG.SymOcc[SOAG.Sym[EAG.StartSym].FirstOcc].RuleInd]; 1449 InclFix('$'); 1450 if (StartRule - 1 != 0) 1451 output.write(StartRule - 1, " + "); 1452 InclFix('$'); 1453 output.write("S", EAG.StartSym); 1454 InclFix('$'); 1455 EmitGen.GenEmitCall(output, settings); 1456 InclFix('$'); 1457 EmitGen.GenShowHeap(output); 1458 InclFix('$'); 1459 if (Optimize) 1460 output.write(optimizer.StackVar); 1461 else 1462 output.write(0); 1463 InclFix('$'); 1464 if (Optimize) 1465 output.write(optimizer.GlobalVar); 1466 else 1467 output.write(0); 1468 InclFix('$'); 1469 output.write(EAG.BaseName); 1470 output.write("Eval"); 1471 InclFix('$'); 1472 output.flush; 1473 SLAGGen.FinitGen; 1474 output.close; 1475 return fileName; 1476 }