1 module epsilon.emitgen; 2 3 import EAG = epsilon.eag; 4 import epsilon.settings; 5 import runtime; 6 import std.bitmanip : BitArray; 7 import std.stdio; 8 9 private const CaseLabels = 127; 10 private BitArray Type3; 11 private BitArray Type2; 12 private int StartMNont; 13 14 public void GenEmitProc(File output, Settings settings) 15 { 16 void CalcSets(int Nont) 17 in (EAG.firstMNont <= Nont) 18 in (Nont < EAG.NextMNont) 19 { 20 int A; 21 int F; 22 int M; 23 24 if (EAG.MNont[Nont].IsToken) 25 Type3[Nont] = true; 26 A = EAG.MNont[Nont].MRule; 27 while (A != EAG.nil) 28 { 29 F = EAG.MAlt[A].Right; 30 while (EAG.MembBuf[F] != EAG.nil) 31 { 32 M = EAG.MembBuf[F]; 33 if (M > 0) 34 { 35 if (Type3[Nont] && !Type3[M]) 36 { 37 Type3[M] = true; 38 CalcSets(M); 39 } 40 if (Type2[Nont] && !Type2[M]) 41 { 42 if (!EAG.MNont[M].IsToken) 43 Type2[M] = true; 44 CalcSets(M); 45 } 46 } 47 ++F; 48 } 49 A = EAG.MAlt[A].Next; 50 } 51 } 52 53 void GenEmitProcs(BitArray MNonts) 54 { 55 void GenProcName(size_t N, BitArray Type) 56 { 57 output.write("Emit", N, "Type", (Type == Type2) ? "2" : "3"); 58 } 59 60 void GenAlts(size_t N) 61 { 62 int A; 63 int F; 64 int M; 65 int arity; 66 int ANum; 67 68 void WhiteSpace() 69 { 70 if (settings.space) 71 output.write("Out.write(' '); "); 72 else 73 output.write("Out.writeln; "); 74 } 75 76 A = EAG.MNont[N].MRule; 77 ANum = 1; 78 output.writeln("switch (MOD(Heap[Ptr], arityConst))"); 79 output.writeln("{"); 80 while (A != EAG.nil) 81 { 82 if (ANum > CaseLabels) 83 { 84 stdout.write("internal error: Too many meta alts in "); 85 stdout.write(EAG.MTerm[N].Id.repr); 86 stdout.writeln; 87 assert(0); 88 } 89 F = EAG.MAlt[A].Right; 90 arity = 0; 91 output.writeln("case ", ANum, ":"); 92 while (EAG.MembBuf[F] != EAG.nil) 93 { 94 M = EAG.MembBuf[F]; 95 if (M < 0) 96 { 97 output.write("Out.write("); 98 output.write(EAG.MTerm[-M].Id.repr); 99 output.write("); "); 100 if (MNonts == Type2) 101 WhiteSpace; 102 } 103 else 104 { 105 if (MNonts == Type3 || EAG.MNont[M].IsToken) 106 GenProcName(M, Type3); 107 else 108 GenProcName(M, Type2); 109 ++arity; 110 output.write("(Heap[Ptr + "); 111 output.write(arity); 112 output.write("]); "); 113 if (EAG.MNont[M].IsToken && MNonts == Type2) 114 WhiteSpace; 115 } 116 ++F; 117 output.writeln; 118 } 119 output.writeln("break;"); 120 A = EAG.MAlt[A].Next; 121 ++ANum; 122 } 123 output.writeln("default:"); 124 output.writeln("Out.write(Heap[Ptr]);"); 125 output.writeln("}"); 126 } 127 128 foreach (N; MNonts.bitsSet) 129 { 130 output.write("void "); 131 GenProcName(N, MNonts); 132 output.writeln("(HeapType Ptr)"); 133 output.writeln("{"); 134 output.writeln("OutputSize += DIV(MOD(Heap[Ptr], refConst), arityConst) + 1;"); 135 GenAlts(N); 136 output.writeln("}"); 137 output.writeln; 138 } 139 } 140 141 StartMNont = EAG.DomBuf[EAG.HNont[EAG.StartSym].Sig]; 142 Type3 = BitArray(); 143 Type3.length = EAG.NextMNont + 1; 144 Type2 = BitArray(); 145 Type2.length = EAG.NextMNont + 1; 146 if (!EAG.MNont[StartMNont].IsToken) 147 Type2[StartMNont] = true; 148 CalcSets(StartMNont); 149 if (!Type3.bitsSet.empty) 150 GenEmitProcs(Type3); 151 if (!Type2.bitsSet.empty) 152 GenEmitProcs(Type2); 153 } 154 155 public void GenShowHeap(File output) @safe 156 { 157 output.writeln("if (info_)"); 158 output.writeln("{"); 159 output.write(`stdout.write(" tree of "); `); 160 output.writeln("stdout.write(OutputSize);"); 161 output.writeln(`stdout.write(" uses ");`); 162 output.writeln(`stdout.write(CountHeap());`); 163 output.writeln(`stdout.write(" of ");`); 164 output.writeln(`stdout.write(NextHeap);`); 165 output.writeln(`stdout.write(" allocated, with ");`); 166 output.writeln("stdout.write(predefined + 1);"); 167 output.writeln(`stdout.writeln(" predefined");`); 168 output.writeln("}"); 169 } 170 171 public void GenEmitCall(File output, Settings settings) 172 { 173 output.write("if ("); 174 if (settings.write) 175 output.write("!"); 176 output.writeln("write)"); 177 output.writeln(`Out = File("`, EAG.BaseName, `.Out", "w");`); 178 output.writeln("else"); 179 output.writeln("Out = stdout;"); 180 output.writeln("Emit", StartMNont, "Type", Type2[StartMNont] ? "2" : "3", "(V1);"); 181 output.writeln("Out.writeln;"); 182 output.writeln("Out.flush;"); 183 } 184 185 private string repr(int id) 186 { 187 import std.range : dropBackOne, dropOne, front, only; 188 import std.format : format; 189 190 const value = EAG.symbolTable.symbol(id); 191 192 if (value.front == '\'') 193 { 194 if (value == `'"'`) 195 return "`\"`"; 196 return format!`"%s"`(value.dropOne.dropBackOne); 197 } 198 return value; 199 200 }