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 }