root/trunk/enki/CodeGenerator.d

Revision 289, 5.3 kB (checked in by h3r3tic, 4 years ago)

ported Enki to Tango; bootstraps, no other tests done yet

Line 
1 /+
2     Copyright (c) 2006 Eric Anderton
3
4     Permission is hereby granted, free of charge, to any person
5     obtaining a copy of this software and associated documentation
6     files (the "Software"), to deal in the Software without
7     restriction, including without limitation the rights to use,
8     copy, modify, merge, publish, distribute, sublicense, and/or
9     sell copies of the Software, and to permit persons to whom the
10     Software is furnished to do so, subject to the following
11     conditions:
12
13     The above copyright notice and this permission notice shall be
14     included in all copies or substantial portions of the Software.
15
16     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23     OTHER DEALINGS IN THE SOFTWARE.
24 +/
25 module enki.CodeGenerator;
26
27 private import enki.types;
28
29 private import tango.io.Stdout;
30
31 interface IRenderable{
32     public void render(CodeGenerator generator,Statement passterm,Statement failterm);
33 }
34
35 abstract class Statement : IRenderable{
36     static EmptyStatement empty;
37     static this(){
38         empty = new EmptyStatement();
39     }
40    
41     public bool opCast(){
42         return this != empty;
43     }
44    
45     public bool isEmpty(){
46         return false;
47     }
48 }
49
50 class EmptyStatement : Statement{
51     public this(){
52     }
53    
54     public void render(CodeGenerator generator,Statement passterm,Statement failterm){
55         generator.emit("{/*do nothing*/}"); // statisfy presence of statment for labels
56     }
57    
58     public bool isEmpty(){
59         return true;
60     }   
61 }
62
63 class Label: Statement{
64     static uint counter = 0;
65     String name;
66    
67     public this(String name){
68         counter++;
69         this.name = name ~ .toString(counter);
70     }
71    
72     public void render(CodeGenerator generator,Statement passterm,Statement failterm){
73         generator.emit(name ~ ":");
74     }
75 }
76
77 class Literal: Statement{
78     String text;
79     public this(String text){
80         this.text = text;
81     }
82        
83     public void render(CodeGenerator generator,Statement passterm,Statement failterm){
84         generator.emit(text);
85     }
86 }
87
88 class Goto: Statement{
89     Label label;
90    
91     public this(Label label){
92         this.label = label;
93     }
94    
95     public void render(CodeGenerator generator,Statement passterm,Statement failterm){
96         generator.emit("goto " ~ label.name ~ ";");
97     }
98 }
99
100 class Call: Statement{
101     String name;
102     String[] args;
103    
104     public this(String name,String[] args...){
105         this.name = name;
106         this.args = args;
107     }
108    
109     public void render(CodeGenerator generator,Statement passterm,Statement failterm){
110         String signature = name ~ "(";
111        
112         foreach(uint i,String arg; args){
113             if(i == 0){
114                 signature ~= arg;
115             }
116             else{
117                 signature ~= "," ~ arg;
118             }
119         }
120         generator.emit(signature ~= ");");
121     }
122 }
123
124 class CompositeStatement : Statement{
125     Statement[] statements;
126        
127     public this(Statement[] statements...){
128         foreach(stmt; statements){
129             if(stmt.isEmpty) continue;
130             this.statements ~= stmt;
131         }
132     }
133    
134     public void render(CodeGenerator generator,Statement passterm,Statement failterm){
135         foreach(statement; statements){
136             generator.render(statement,passterm,failterm);
137         }
138     }
139    
140     public bool isEmpty(){
141         return statements.length == 0;
142     }       
143 }
144
145
146 class CodeGenerator{
147     uint counter;
148     String tabs;
149     String code;
150     String parsetype;
151    
152     public this(String parsetype){
153         counter = 0;
154         tabs = "";
155         this.parsetype = parsetype;
156     }
157    
158     public String getParseType(){
159         return this.parsetype;
160     }
161    
162     public void indent(){
163         tabs = tabs ~ "\t";
164     }
165    
166     public void unindent(){
167         tabs = tabs[0..$-1];
168     }
169    
170     public String getUniqueLabel(String label){
171         counter++;
172         return label ~ .toString(counter);
173     }
174    
175     public void emit(String text){
176         code ~= tabs ~ text ~ "\n";
177     }
178    
179     public void render(IRenderable renderable){
180         if(cast(Label)renderable){
181             unindent();
182             renderable.render(this,Statement.empty,Statement.empty);
183             indent();
184         }
185         else{
186             renderable.render(this,Statement.empty,Statement.empty);
187         }
188     }   
189    
190     public void render(IRenderable renderable,Statement passterm,Statement failterm){
191         renderable.render(this,passterm,failterm);
192     }
193    
194     public void renderFail(IRenderable renderable,Statement failterm){
195         renderable.render(this,Statement.empty,failterm);
196     }   
197    
198     public void renderPass(IRenderable renderable,Statement passterm){
199         renderable.render(this,passterm,Statement.empty);
200     }
201    
202     public void renderIfTest(String test,Statement pass,Statement fail){
203         if(pass.isEmpty && fail.isEmpty){
204             emit(test ~ ";");
205         }
206         else if(pass.isEmpty){
207             emit("if(!(" ~ test ~ ")){");
208                 indent();
209                 render(fail);
210                 unindent();                     
211             emit("}");         
212         }
213         else if(fail.isEmpty){
214             emit("if(" ~ test ~ "){");
215                 indent();
216                 render(pass);
217                 unindent();                     
218             emit("}");
219         }
220         else{
221             emit("if(" ~ test ~ "){");
222                 indent();
223                 render(pass);
224                 unindent();
225             emit("}else{");
226                 indent();
227                 render(fail);
228                 unindent();
229             emit("}");
230         }       
231     }
232    
233     public String toString(){
234         return code;
235     }
236 }
Note: See TracBrowser for help on using the browser.