1 module epsilon.sweep;
2 
3 import EAG = epsilon.eag;
4 import EmitGen = epsilon.emitgen;
5 import EvalGen = epsilon.slaggen;
6 import epsilon.settings;
7 import io : Input, read, UndefPos;
8 import log;
9 import runtime;
10 import std.bitmanip : BitArray;
11 import std.stdio;
12 import std.typecons;
13 
14 private const nil = 0;
15 private const indexOfFirstAlt = 1;
16 private int[] FactorOffset;
17 private BitArray GenNonts;
18 private BitArray GenFactors;
19 private bool Error;
20 
21 public void Test(Settings settings)
22 in (EAG.Performed(EAG.analysed | EAG.predicates))
23 {
24     info!"single-sweep testing %s"(EAG.BaseName);
25     EAG.History &= ~EAG.isSweep;
26     Init;
27     scope (exit)
28         Finit;
29 
30     const SaveHistory = EAG.History;
31 
32     EAG.History = 0;
33     GenerateMod(No.createMod, settings);
34     EAG.History = SaveHistory;
35     if (!Error)
36     {
37         info!"%s grammar is single sweep"(EAG.BaseName);
38         EAG.History |= EAG.isSweep;
39     }
40 }
41 
42 public string Generate(Settings settings)
43 in (EAG.Performed(EAG.analysed | EAG.predicates))
44 {
45     info!"single-sweep writing %s"(EAG.BaseName);
46     EAG.History &= ~EAG.isSweep;
47     Init;
48     scope (exit)
49         Finit;
50 
51     const SaveHistory = EAG.History;
52 
53     EAG.History = 0;
54 
55     const fileName = GenerateMod(Yes.createMod, settings);
56 
57     EAG.History = SaveHistory;
58     if (!Error)
59     {
60         EAG.History |= EAG.isSweep;
61         EAG.History |= EAG.hasEvaluator;
62     }
63     return fileName;
64 }
65 
66 private void Init() nothrow
67 {
68     FactorOffset = new int[EAG.NextHFactor + EAG.NextHAlt + 1];
69     GenFactors = EAG.Prod & EAG.Reach;
70     GenNonts = GenFactors - EAG.Pred;
71     Error = false;
72 }
73 
74 private void Finit() @nogc nothrow @safe
75 {
76     FactorOffset = null;
77 }
78 
79 private string GenerateMod(Flag!"createMod" createMod, Settings settings)
80 {
81     const firstEdge = 1;
82     const firstStack = 0;
83 
84     struct EdgeRecord
85     {
86         int Dest;
87         int Next;
88     }
89 
90     struct FactorRecord
91     {
92         int Vars;
93         int CountAppl;
94         int Prio;
95         EAG.Factor F;
96     }
97 
98     struct VarRecord
99     {
100         int Factors;
101     }
102 
103     int V;
104     File output;
105     Input Fix;
106     EAG.Rule SavedNontDef;
107     int SavedNextHFactor;
108     int SavedNextHAlt;
109     FactorRecord[] Factor;
110     VarRecord[] Var;
111     EdgeRecord[] Edge;
112     int NextEdge;
113     int[] Stack;
114     int NextStack;
115     BitArray DefVars;
116 
117     void Expand()
118     {
119         if (NextEdge >= Edge.length)
120         {
121             auto Edge1 = new EdgeRecord[2 * Edge.length];
122 
123             for (size_t i = firstEdge; i < Edge.length; ++i)
124             {
125                 Edge1[i] = Edge[i];
126             }
127             Edge = Edge1;
128         }
129     }
130 
131     void InclFix(char Term)
132     {
133         import std.conv : to;
134         import std.exception : enforce;
135 
136         char c = Fix.front.to!char;
137 
138         while (c != Term)
139         {
140             enforce(c != 0,
141                     "error: unexpected end of eSSweep.fix.d");
142 
143             output.write(c);
144             Fix.popFront;
145             c = Fix.front.to!char;
146         }
147         Fix.popFront;
148     }
149 
150     int HyperArity()
151     {
152         const Nonts = EAG.All - EAG.Pred;
153         int Max = 0;
154         int i;
155 
156         foreach (N; Nonts.bitsSet)
157         {
158             EAG.Alt A = EAG.HNont[N].Def.Sub;
159 
160             i = 0;
161             do
162             {
163                 ++i;
164                 A = A.Next;
165             }
166             while (A !is null);
167             if (cast(EAG.Opt) EAG.HNont[N].Def || cast(EAG.Rep) EAG.HNont[N].Def)
168                 ++i;
169             if (i > Max)
170                 Max = i;
171         }
172         i = 1;
173         while (i <= Max)
174             i = i * 2;
175         return i;
176     }
177 
178     void SaveAndPatchNont(size_t N)
179     {
180         import std.conv : to;
181 
182         EAG.Alt A;
183         EAG.Alt A1;
184         EAG.Alt A2;
185         EAG.Factor F;
186         EAG.Nont F1;
187         EAG.Nont F2;
188 
189         SavedNontDef = EAG.HNont[N].Def;
190         SavedNextHFactor = EAG.NextHFactor;
191         SavedNextHAlt = EAG.NextHAlt;
192 
193         EAG.Grp Def = new EAG.Grp;
194 
195         A = EAG.HNont[N].Def.Sub;
196         A2 = null;
197         do
198         {
199             A1 = new EAG.Alt;
200             EAG.assign(A1, A);
201             A1.Sub = null;
202             A1.Last = null;
203             A1.Next = null;
204             if (A2 !is null)
205                 A2.Next = A1;
206             else
207                 Def.Sub = A1;
208             A2 = A1;
209             F = A.Sub;
210             F2 = null;
211             while (F !is null)
212             {
213                 if (auto nont = cast(EAG.Nont) F)
214                     if (GenFactors[nont.Sym])
215                     {
216                         F1 = new EAG.Nont;
217                         EAG.assign(F1, nont);
218                         F1.Prev = F2;
219                         F1.Next = null;
220                         A1.Last = F1;
221                         if (F2 !is null)
222                             F2.Next = F1;
223                         else
224                             A1.Sub = F1;
225                         F2 = F1;
226                     }
227                 F = F.Next;
228             }
229             if (cast(EAG.Rep) EAG.HNont[N].Def)
230             {
231                 F1 = new EAG.Nont;
232                 F1.Ind = EAG.NextHFactor;
233                 ++EAG.NextHFactor;
234                 F1.Prev = A1.Last;
235                 A1.Last = F1;
236                 if (A1.Sub is null)
237                     A1.Sub = F1;
238                 if (F1.Prev !is null)
239                     F1.Prev.Next = F1;
240                 F1.Next = null;
241                 F1.Sym = N.to!int;
242                 F1.Pos = A1.Actual.Pos;
243                 F1.Actual = A1.Actual;
244                 A1.Actual.Pos = UndefPos;
245                 A1.Actual.Params = EAG.empty;
246             }
247             A = A.Next;
248         }
249         while (A !is null);
250         if (cast(EAG.Opt) EAG.HNont[N].Def || cast(EAG.Rep) EAG.HNont[N].Def)
251         {
252             A1 = new EAG.Alt;
253             A1.Ind = EAG.NextHAlt;
254             ++EAG.NextHAlt;
255             A1.Up = N.to!int;
256             A1.Next = null;
257             A1.Sub = null;
258             A1.Last = null;
259             if (auto opt = cast(EAG.Opt) EAG.HNont[N].Def)
260             {
261                 A1.Scope = opt.Scope;
262                 A1.Formal = opt.Formal;
263                 A1.Pos = opt.EmptyAltPos;
264             }
265             else if (auto rep = cast(EAG.Rep) EAG.HNont[N].Def)
266             {
267                 A1.Scope = rep.Scope;
268                 A1.Formal = rep.Formal;
269                 A1.Pos = rep.EmptyAltPos;
270             }
271             A1.Actual.Params = EAG.empty;
272             A1.Actual.Pos = UndefPos;
273             A2.Next = A1;
274         }
275         EAG.HNont[N].Def = Def;
276     }
277 
278     void RestoreNont(size_t N)
279     {
280         EAG.HNont[N].Def = SavedNontDef;
281         EAG.NextHFactor = SavedNextHFactor;
282         EAG.NextHAlt = SavedNextHAlt;
283     }
284 
285     void ComputePermutation(size_t N)
286     {
287         const def = 0;
288         const right = 1;
289         const appl = 2;
290         EAG.Alt A;
291         EAG.Factor F;
292         EAG.Factor F1;
293         int Prio;
294         int Index;
295         int Offset;
296         int NE;
297         int VE;
298         int V;
299 
300         void TravParams(int op, int P, EAG.Factor F)
301         {
302             bool Def;
303 
304             void NewEdge(ref int From, int To)
305             {
306                 if (NextEdge >= Edge.length)
307                 {
308                     Expand;
309                 }
310                 Edge[NextEdge].Dest = To;
311                 Edge[NextEdge].Next = From;
312                 From = NextEdge;
313                 ++NextEdge;
314             }
315 
316             void Tree(int Node)
317             {
318                 int n;
319                 if (Node < 0)
320                 {
321                     switch (op)
322                     {
323                     case def:
324                         if (Def)
325                             DefVars[-Node] = true;
326                         break;
327                     case right:
328                         if (!DefVars[-Node])
329                         {
330                             if (Def)
331                             {
332                                 NewEdge(Factor[F.Ind].Vars, -Node);
333                             }
334                             else
335                             {
336                                 NewEdge(Var[-Node].Factors, F.Ind);
337                                 ++Factor[F.Ind].CountAppl;
338                             }
339                         }
340                         break;
341                     case appl:
342                         if (!Def && !DefVars[-Node])
343                         {
344                             error!"variable %s is not defined\n%s"(EAG.VarRepr(-Node), EAG.ParamBuf[P].Pos);
345                             Error = true;
346                         }
347                         break;
348                     default:
349                         assert(0);
350                     }
351                 }
352                 else
353                 {
354                     for (n = 1; n <= EAG.MAlt[EAG.NodeBuf[Node]].Arity; ++n)
355                         Tree(EAG.NodeBuf[Node + n]);
356                 }
357             }
358 
359             while (EAG.ParamBuf[P].Affixform != EAG.nil)
360             {
361                 Def = EAG.ParamBuf[P].isDef;
362                 Tree(EAG.ParamBuf[P].Affixform);
363                 ++P;
364             }
365         }
366 
367         void Pop(ref EAG.Factor F)
368         {
369             int i;
370             int MinPrio;
371             int MinIndex;
372 
373             MinPrio = int.max;
374             for (i = firstStack; i < NextStack; ++i)
375             {
376                 if (Factor[Stack[i]].Prio < MinPrio)
377                 {
378                     MinPrio = Factor[Stack[i]].Prio;
379                     MinIndex = i;
380                 }
381             }
382             F = Factor[Stack[MinIndex]].F;
383             Stack[MinIndex] = Stack[NextStack - 1];
384             --NextStack;
385         }
386 
387         A = EAG.HNont[N].Def.Sub;
388         do
389         {
390             DefVars[] = false;
391             NextEdge = firstEdge;
392             NextStack = firstStack;
393             TravParams(def, A.Formal.Params, null);
394             F = A.Sub;
395             Prio = 0;
396             Offset = 1;
397             while (F !is null)
398             {
399                 Factor[F.Ind].Vars = nil;
400                 Factor[F.Ind].CountAppl = 0;
401                 Factor[F.Ind].Prio = Prio;
402                 ++Prio;
403                 Factor[F.Ind].F = F;
404                 if (!EAG.Pred[(cast(EAG.Nont) F).Sym])
405                 {
406                     FactorOffset[F.Ind] = Offset;
407                     ++Offset;
408                 }
409                 TravParams(right, (cast(EAG.Nont) F).Actual.Params, F);
410                 if (Factor[F.Ind].CountAppl == 0)
411                 {
412                     Stack[NextStack] = F.Ind;
413                     ++NextStack;
414                 }
415                 F = F.Next;
416             }
417             A.Sub = null;
418             A.Last = null;
419             F1 = null;
420             Index = 0;
421             while (NextStack > firstStack)
422             {
423                 Pop(F);
424                 F.Prev = F1;
425                 F.Next = null;
426                 A.Last = F;
427                 if (F1 !is null)
428                     F1.Next = F;
429                 else
430                     A.Sub = F;
431                 F1 = F;
432                 ++Index;
433                 VE = Factor[F.Ind].Vars;
434                 while (VE != nil)
435                 {
436                     V = Edge[VE].Dest;
437                     if (!DefVars[V])
438                     {
439                         NE = Var[V].Factors;
440                         while (NE != nil)
441                         {
442                             --Factor[Edge[NE].Dest].CountAppl;
443                             if (Factor[Edge[NE].Dest].CountAppl == 0)
444                             {
445                                 Stack[NextStack] = Edge[NE].Dest;
446                                 ++NextStack;
447                             }
448                             NE = Edge[NE].Next;
449                         }
450                         DefVars[V] = true;
451                     }
452                     VE = Edge[VE].Next;
453                 }
454             }
455             if (Index == Prio)
456             {
457                 TravParams(appl, A.Formal.Params, null);
458             }
459             else
460             {
461                 error!"alternative is not single sweep\n%s"(A.Pos);
462                 Error = true;
463             }
464             A = A.Next;
465         }
466         while (A !is null);
467     }
468 
469     void GenerateNont(size_t N)
470     {
471         EAG.Alt A;
472         EAG.Factor F;
473         EAG.Factor F1;
474         int AltIndex;
475         EvalGen.ComputeVarNames(N, No.embed);
476         output.write("void P", N, "(TreeType Adr");
477         EvalGen.GenFormalParams(N, No.parNeeded);
478         output.write(") // ", EAG.HNontRepr(N));
479         if (EAG.HNont[N].anonymous)
480             output.write(" in ", EAG.NamedHNontRepr(N));
481         output.writeln;
482         output.writeln("{");
483         EvalGen.GenVarDecl(N);
484         output.writeln("switch (MOD(Tree[Adr], hyperArityConst))");
485         output.writeln("{");
486         A = EAG.HNont[N].Def.Sub;
487         AltIndex = indexOfFirstAlt;
488         do
489         {
490             output.writeln("case ", AltIndex, ":");
491             EvalGen.InitScope(A.Scope);
492             if (EvalGen.PosNeeded(A.Formal.Params))
493                 output.writeln("Pos = PosTree[Adr];");
494             EvalGen.GenAnalPred(N, A.Formal.Params);
495             F = A.Sub;
496             while (F !is null)
497             {
498                 if (auto nont = cast(EAG.Nont) F)
499                 {
500                     if (!EAG.Pred[nont.Sym])
501                     {
502                         EvalGen.GenSynPred(N, nont.Actual.Params);
503                         output.write("P", nont.Sym, "(Tree[Adr + ", FactorOffset[F.Ind], "]");
504                         EvalGen.GenActualParams(nont.Actual.Params, false);
505                         output.write("); // ", EAG.HNontRepr(nont.Sym));
506                         if (EAG.HNont[nont.Sym].anonymous)
507                             output.write(" in ", EAG.NamedHNontRepr(nont.Sym));
508                         output.writeln;
509                         if (EvalGen.PosNeeded(nont.Actual.Params))
510                             output.writeln("Pos = PosTree[Adr + ", FactorOffset[F.Ind], "];");
511                         EvalGen.GenAnalPred(N, nont.Actual.Params);
512                     }
513                     else
514                     {
515                         EvalGen.GenSynPred(N, nont.Actual.Params);
516                         output.write("Pos = PosTree[Adr");
517                         F1 = F.Prev;
518                         while (F1 !is null && EAG.Pred[(cast(EAG.Nont) F1).Sym])
519                             F1 = F1.Prev;
520                         if (F1 !is null)
521                             output.write(" + ", FactorOffset[F1.Ind]);
522                         output.writeln("];");
523                         EvalGen.GenPredCall(nont.Sym, nont.Actual.Params);
524                         EvalGen.GenAnalPred(N, nont.Actual.Params);
525                     }
526                 }
527                 F = F.Next;
528             }
529             EvalGen.GenSynPred(N, A.Formal.Params);
530             output.writeln("break;");
531             A = A.Next;
532             ++AltIndex;
533         }
534         while (A !is null);
535         output.writeln("default:");
536         output.writeln("assert(0);");
537         output.writeln("}");
538         output.writeln("}");
539         output.writeln;
540     }
541 
542     enum fixName = "sweep.fix.d";
543     const name = EAG.BaseName ~ "Eval";
544     const fileName = settings.path(name ~ ".d");
545 
546     EvalGen.InitTest;
547     Error = Error || !EvalGen.PredsOK();
548     if (createMod)
549     {
550         Fix = Input(fixName, import(fixName));
551         output = File(fileName, "w");
552         if (!Error)
553         {
554             EvalGen.InitGen(output, EvalGen.sweepPass, settings);
555             InclFix('$');
556             output.write(name);
557             InclFix('$');
558             output.write(HyperArity());
559             InclFix('$');
560             EvalGen.GenDeclarations(settings);
561             EvalGen.GenPredProcs;
562             output.writeln;
563         }
564     }
565     Factor = new FactorRecord[EAG.NextHFactor + EAG.NextHAlt + 1];
566     Var = new VarRecord[EAG.NextVar + 1];
567     Edge = new EdgeRecord[127];
568     Stack = new int[EAG.NextHFactor + 1];
569     DefVars = BitArray();
570     DefVars.length = EAG.NextVar + 1;
571     for (V = EAG.firstVar; V < EAG.NextVar; ++V)
572         Var[V].Factors = nil;
573     foreach (N; GenNonts.bitsSet)
574     {
575         SaveAndPatchNont(N);
576         ComputePermutation(N);
577         if (!Error)
578         {
579             Error = !EvalGen.IsLAG(N);
580             if (!Error && createMod)
581                 GenerateNont(N);
582         }
583         RestoreNont(N);
584     }
585     if (createMod)
586     {
587         if (!Error)
588         {
589             EmitGen.GenEmitProc(output, settings);
590             InclFix('$');
591             output.write("P", EAG.StartSym);
592             InclFix('$');
593             EmitGen.GenEmitCall(output, settings);
594             InclFix('$');
595             EmitGen.GenShowHeap(output);
596             InclFix('$');
597             output.write(EAG.BaseName, "Eval");
598             InclFix('$');
599             output.close;
600         }
601         EvalGen.FinitGen;
602     }
603     EvalGen.FinitTest;
604     return fileName;
605 }