1 module orelang.Interpreter;
2 import orelang.Transpiler,
3        orelang.Engine,
4        orelang.Value;
5 import std..string,
6        std.stdio,
7        std.conv;
8 
9 // TODO: Need to implement exit operator
10 
11 class Interpreter {
12   private {
13     Engine     engine;
14     Transpiler transpiler;
15     long       bracketState;
16   }
17 
18   this() {
19     this.engine       = new Engine();
20     this.bracketState = 0;
21   }
22 
23   this(Engine engine) {
24     this.engine       = engine;
25     this.bracketState = 0;
26   }
27 
28   Engine peekEngine() {
29     return this.engine;
30   }
31 
32   void defineARGS(string[] args) {
33     Value[] vargs;
34 
35     foreach (arg; args) {
36       vargs ~= new Value(arg);
37     }
38 
39     this.engine.defineVariable("ARGS", new Value(vargs));
40   }
41 
42   bool checkBracket(string code) {
43     for (size_t i; i < code.length; ++i) {
44       char ch = code[i];
45 
46       if (ch == '(') { this.bracketState++; }
47       if (ch == ')') { this.bracketState--; }
48     }
49 
50     if (this.bracketState == 0) {
51       return true;
52     } else {
53       return false;
54     }
55   }
56 
57   void interpreter() {
58     string buf;
59     write("=> ");
60 
61     void e(char val) {
62       if (checkBracket(val.to!string) && (buf.length != 0)) {
63 //        writeln("buf -> ", buf);
64         auto transpiled = Transpiler.transpile(buf);
65 //        writeln("transpiled -> ", transpiled);
66         writeln(engine.eval(transpiled));
67         buf = [];
68       }
69     }
70 
71     while (true) {
72       string input = readln.chomp;
73 
74       if (input == "exit" || input == "(exit)") {
75         break;
76       }
77 
78       foreach (char val; input) {
79         if ('\n' == val) {
80           e(val);
81         } else {
82           buf ~= val;
83           e(val);
84         }
85       }
86 
87       for (size_t i; i < bracketState + 1; ++i) {
88         write("=");
89       }
90       write("> ");
91     }
92   }
93 
94   Value executer(string code, bool showMsg = true) {
95     string buf;
96     Value ret;
97 
98     try {
99       void e(char val) {
100         if (checkBracket(val.to!string) && (buf.length != 0)) {
101           auto transpiled = Transpiler.transpile(buf);
102           ret = engine.eval(transpiled);
103           buf = [];
104         }
105       }
106 
107       foreach(input; code.split("\n")) {
108         if (input == "exit" || input == "(exit)") {
109           break;
110         }
111 
112         foreach (char val; input) {
113           if ('\n' == val) {
114             e(val);
115           } else {
116             buf ~= val;
117             e(val);
118           }
119         }
120       }
121 
122       return ret;
123     } catch (Exception e) {
124       if (showMsg) {
125         writeln("[Exception] - ", e.msg);
126       }
127       return new Value(new CCException(e.msg));
128     }
129   }
130 }