1 module bf_compiler;
2 
3 import bf_parser;
4 
5 enum TargetEnum
6 {
7     AnonymousFunction,
8 }
9 
10 string indentBy(const string line, const uint iLvl) pure
11 {
12     char[] indent;
13     indent.length = iLvl;
14 
15     foreach (i; 0 .. iLvl)
16     {
17         indent[i] = '\t';
18     }
19 
20     return cast(string)(indent ~ line);
21 }
22 
23 import bf_fastMath;
24 
25 string itos(const uint val) pure
26 {
27     immutable length = fastLog10(val) + 1;
28     char[] result;
29     result.length = 10;
30 
31     foreach (i; 0 .. length)
32     {
33         immutable _val = val / fastPow10tbl[i];
34         result[length - i - 1] = cast(char)((_val % 10) + '0');
35     }
36 
37     return cast(string) result[0 .. length];
38 }
39 
40 static assert(mixin(uint.max.itos) == uint.max);
41 
42 string genCode(const RepeatedToken[] programm, const TargetEnum target, const uint cellSize = 4096) pure
43 {
44     //	import std.conv : to;
45     string result = `((const ubyte[] input){
46 	uint iPos, oPos;
47 	ubyte[] output; 
48 	ubyte[` ~ cellSize.itos ~ `] cells; 
49 	uint cellPtr = 0;
50 	output.length = 1024;` ~ "\n\n";
51 
52     uint iLvl = 1;
53 
54     if (target == TargetEnum.AnonymousFunction)
55     {
56         foreach (rt; programm)
57         {
58             final switch (rt.token) with (BFTokenEnum)
59             {
60             case LoopBegin:
61                 {
62                     foreach (_; 0 .. rt.count)
63                         result ~= "while(cells[cellPtr]) {\n".indentBy(iLvl++);
64                 }
65                 break;
66             case LoopEnd:
67                 {
68                     foreach (_; 0 .. rt.count)
69                         result ~= "}\n".indentBy(--iLvl);
70                 }
71                 break;
72 
73             case IncVal:
74                 {
75                     result ~= "cells[cellPtr] += ".indentBy(iLvl) ~ rt.count.itos ~ " ;\n";
76                 }
77                 break;
78             case DecVal:
79                 {
80                     result ~= "cells[cellPtr] -= ".indentBy(iLvl) ~ rt.count.itos ~ " ;\n";
81                 }
82                 break;
83 
84             case IncPtr:
85                 {
86                     result ~= "cellPtr += ".indentBy(iLvl) ~ rt.count.itos ~ " ;\n";
87                 }
88                 break;
89             case DecPtr:
90                 {
91                     result ~= "cellPtr -= ".indentBy(iLvl) ~ rt.count.itos ~ " ;\n";
92                 }
93                 break;
94 
95             case InputVal:
96                 {
97                     foreach (_; 0 .. rt.count)
98                         result ~= "cells[cellPtr] = input[iPos++];\n".indentBy(iLvl);
99                 }
100                 break;
101             case OutputVal:
102                 {
103                     foreach (_; 0 .. rt.count)
104                         result ~= "output[oPos++] = cells[cellPtr];\n".indentBy(iLvl);
105                 }
106                 break;
107 
108             case ProgrammBegin:
109             case ProgrammEnd:
110                 break;
111             }
112 
113         }
114 
115         return result ~ "\nreturn output[0 .. oPos];})";
116     }
117 
118     assert(0, "Target Not supported: " ~ itos(target));
119 }