45
|
1 |
using System;
|
|
2 |
using System.Collections.Generic;
|
|
3 |
using System.Text;
|
|
4 |
// Added
|
|
5 |
using System.Reflection;
|
|
6 |
using System.Reflection.Emit;
|
|
7 |
using System.IO;
|
|
8 |
|
|
9 |
public sealed class CodeGenerator
|
|
10 |
{
|
|
11 |
|
|
12 |
Dictionary<string, System.Reflection.Emit.LocalBuilder> tblIdentifier;
|
|
13 |
Dictionary<string, System.Reflection.Emit.LocalBuilder> tblArguments;
|
|
14 |
TypeBuilder _typeBuilder = null;
|
|
15 |
System.Reflection.Emit.ILGenerator _ILGenerator = null;
|
|
16 |
MemberInfo WriteLine = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) });
|
|
17 |
|
|
18 |
#region Statement
|
|
19 |
public CodeGenerator(Statement statement, string fileName)
|
|
20 |
{
|
|
21 |
string strFileName = Path.GetFileNameWithoutExtension(fileName);
|
|
22 |
|
|
23 |
#region Define Assembly
|
|
24 |
//AssemblyName _AssemblyName = new AssemblyName(Path.GetFileNameWithoutExtension(fileName));
|
|
25 |
AssemblyName _AssemblyName = new AssemblyName(strFileName);
|
|
26 |
AppDomain currentDomain = AppDomain.CurrentDomain;
|
|
27 |
AssemblyBuilder _AssemblyBuilder = currentDomain.DefineDynamicAssembly(_AssemblyName, AssemblyBuilderAccess.Save);
|
|
28 |
#endregion
|
|
29 |
|
|
30 |
#region Define Module
|
|
31 |
ModuleBuilder _ModuleBuilder = _AssemblyBuilder.DefineDynamicModule(fileName);
|
|
32 |
#endregion
|
|
33 |
|
|
34 |
_typeBuilder = _ModuleBuilder.DefineType("CodeGenerator");
|
|
35 |
MethodBuilder _MethodBuilder = _typeBuilder.DefineMethod
|
|
36 |
("Main",
|
|
37 |
MethodAttributes.Static,
|
|
38 |
typeof(void),
|
|
39 |
System.Type.EmptyTypes);
|
|
40 |
|
|
41 |
_ILGenerator = _MethodBuilder.GetILGenerator();
|
|
42 |
tblIdentifier = new Dictionary<string, System.Reflection.Emit.LocalBuilder>();
|
|
43 |
tblArguments = new Dictionary<string, System.Reflection.Emit.LocalBuilder>();
|
|
44 |
|
|
45 |
// CIL generation
|
|
46 |
GenerateStatement(statement);
|
|
47 |
|
|
48 |
_ILGenerator.Emit(OpCodes.Ret);
|
|
49 |
_typeBuilder.CreateType();
|
|
50 |
_ModuleBuilder.CreateGlobalFunctions();
|
|
51 |
_AssemblyBuilder.SetEntryPoint(_MethodBuilder);
|
|
52 |
_AssemblyBuilder.Save(fileName);
|
|
53 |
tblIdentifier = null;
|
|
54 |
_ILGenerator = null;
|
|
55 |
}
|
|
56 |
|
|
57 |
public void GenerateStatement(Statement _statement)
|
|
58 |
{
|
|
59 |
if (_statement is StatementSequence)
|
|
60 |
{
|
|
61 |
StatementSequence _StatementSequence = (StatementSequence)_statement;
|
|
62 |
GenerateStatement(_StatementSequence.Left);
|
|
63 |
GenerateStatement(_StatementSequence.Right);
|
|
64 |
}
|
|
65 |
|
|
66 |
else if (_statement is DeclareVariable)
|
|
67 |
{
|
|
68 |
// declare a variable in symbol table
|
|
69 |
DeclareVariable declare = (DeclareVariable)_statement;
|
|
70 |
tblIdentifier[declare.Identifier] =
|
|
71 |
_ILGenerator.DeclareLocal(GetExpressionType(declare.Expression));
|
|
72 |
|
|
73 |
// set the initial value
|
|
74 |
Assignment assign = new Assignment();
|
|
75 |
assign.Identifier = declare.Identifier;
|
|
76 |
assign.Expression = declare.Expression;
|
|
77 |
GenerateStatement(assign);
|
|
78 |
}
|
|
79 |
|
|
80 |
else if (_statement is Assignment)
|
|
81 |
{
|
|
82 |
Assignment assign = (Assignment)_statement;
|
|
83 |
GenerateExpression(assign.Expression,
|
|
84 |
GetExpressionType(assign.Expression));
|
|
85 |
if (GetExpressionType(assign.Expression) == typeof(ArithmaticExpression))
|
|
86 |
{
|
|
87 |
SaveIdentifier(assign.Identifier, typeof(Int32));
|
|
88 |
}
|
|
89 |
else
|
|
90 |
{
|
|
91 |
SaveIdentifier(assign.Identifier,
|
|
92 |
GetExpressionType(assign.Expression));
|
|
93 |
}
|
|
94 |
|
|
95 |
}
|
|
96 |
|
|
97 |
else if (_statement is DeclareFunction)
|
|
98 |
{
|
|
99 |
GenerateStatementMethod(_statement);
|
|
100 |
}
|
|
101 |
|
|
102 |
else if (_statement is Write)
|
|
103 |
{
|
|
104 |
// for print keyword, call .net method for printscreen
|
|
105 |
GenerateExpression(((Write)_statement).Expression,
|
|
106 |
typeof(string));
|
|
107 |
_ILGenerator.Emit(OpCodes.Call,
|
|
108 |
typeof(System.Console).GetMethod("WriteLine",
|
|
109 |
new System.Type[] { typeof(string) }));
|
|
110 |
}
|
|
111 |
|
|
112 |
else if (_statement is ReadInput)
|
|
113 |
{
|
|
114 |
// call the readline method and parse input method
|
|
115 |
_ILGenerator.Emit(OpCodes.Call,
|
|
116 |
typeof(System.Console).GetMethod("ReadLine",
|
|
117 |
BindingFlags.Public | BindingFlags.Static,
|
|
118 |
null, new System.Type[] { }, null));
|
|
119 |
_ILGenerator.Emit(OpCodes.Call,
|
|
120 |
typeof(int).GetMethod("Parse",
|
|
121 |
BindingFlags.Public | BindingFlags.Static,
|
|
122 |
null, new System.Type[] { typeof(string) }, null));
|
|
123 |
// store the input value in local builder
|
|
124 |
SaveIdentifier(((ReadInput)_statement).Identifier, typeof(int));
|
|
125 |
}
|
|
126 |
else if (_statement is IfThenElse)
|
|
127 |
{
|
|
128 |
|
|
129 |
//IfThenElse ifThenElse = (IfThenElse)stmt;
|
|
130 |
//RelationalExpression relExpr = (RelationalExpression)ifThenElse.If;
|
|
131 |
//// if, left side only
|
|
132 |
//il.Emit(OpCodes.Stloc, symbolTable[relExpr.Left.ToString()]);
|
|
133 |
//Label lblIf = il.DefineLabel();
|
|
134 |
//il.Emit(OpCodes.Br, lblIf);
|
|
135 |
//// then
|
|
136 |
//Label lblThen = il.DefineLabel();
|
|
137 |
//il.MarkLabel(lblThen);
|
|
138 |
|
|
139 |
}
|
|
140 |
|
|
141 |
else if (_statement is While)
|
|
142 |
{
|
|
143 |
While _while = (While)_statement;
|
|
144 |
Label lblTest = _ILGenerator.DefineLabel();
|
|
145 |
Label lblEnd = _ILGenerator.DefineLabel();
|
|
146 |
|
|
147 |
if (_while.Operand == RelationalOperands.GreaterThan)
|
|
148 |
{
|
|
149 |
_ILGenerator.MarkLabel(lblTest);
|
|
150 |
GenerateExpression(_while.LeftExpression, typeof(int));
|
|
151 |
GenerateExpression(_while.RightExpression, typeof(int));
|
|
152 |
_ILGenerator.Emit(OpCodes.Cgt);
|
|
153 |
_ILGenerator.Emit(OpCodes.Brfalse, lblEnd);
|
|
154 |
GenerateStatement(_while.Body);
|
|
155 |
_ILGenerator.Emit(OpCodes.Br, lblTest);
|
|
156 |
|
|
157 |
_ILGenerator.MarkLabel(lblEnd);
|
|
158 |
}
|
|
159 |
else if (_while.Operand == RelationalOperands.EqualTo)
|
|
160 |
{
|
|
161 |
_ILGenerator.MarkLabel(lblTest);
|
|
162 |
GenerateExpression(_while.LeftExpression, typeof(int));
|
|
163 |
GenerateExpression(_while.RightExpression, typeof(int));
|
|
164 |
_ILGenerator.Emit(OpCodes.Ceq);
|
|
165 |
_ILGenerator.Emit(OpCodes.Brfalse, lblEnd);
|
|
166 |
GenerateStatement(_while.Body);
|
|
167 |
_ILGenerator.Emit(OpCodes.Br, lblTest);
|
|
168 |
|
|
169 |
_ILGenerator.MarkLabel(lblEnd);
|
|
170 |
}
|
|
171 |
else if (_while.Operand == RelationalOperands.LessThan)
|
|
172 |
{
|
|
173 |
_ILGenerator.MarkLabel(lblTest);
|
|
174 |
GenerateExpression(_while.LeftExpression, typeof(int));
|
|
175 |
GenerateExpression(_while.RightExpression, typeof(int));
|
|
176 |
_ILGenerator.Emit(OpCodes.Clt);
|
|
177 |
_ILGenerator.Emit(OpCodes.Brfalse, lblEnd);
|
|
178 |
GenerateStatement(_while.Body);
|
|
179 |
_ILGenerator.Emit(OpCodes.Br, lblTest);
|
|
180 |
|
|
181 |
_ILGenerator.MarkLabel(lblEnd);
|
|
182 |
}
|
|
183 |
}
|
|
184 |
else if (_statement is IfThen)
|
|
185 |
{
|
|
186 |
#region
|
|
187 |
//////Label body = il.DefineLabel();
|
|
188 |
|
|
189 |
//////il.Emit(OpCodes.Ldc_I4, 1000);
|
|
190 |
|
|
191 |
|
|
192 |
|
|
193 |
/*
|
|
194 |
// var x = 0;
|
|
195 |
// if x < 5 then
|
|
196 |
// print "less than 5";
|
|
197 |
// endif;
|
|
198 |
|
|
199 |
IfThen ifThen = (IfThen)stmt;
|
|
200 |
// jump to test
|
|
201 |
|
|
202 |
|
|
203 |
// **test** if x LessThan 5? (do the test)
|
|
204 |
il.MarkLabel(test);
|
|
205 |
GenExpr(ifThen.LeftExpression, typeof(int));
|
|
206 |
|
|
207 |
*/
|
|
208 |
|
|
209 |
//Label greaterThan = il.DefineLabel();
|
|
210 |
|
|
211 |
//IfThen ifThen = (IfThen)stmt;
|
|
212 |
//GenExpr(ifThen.LeftExpression, typeof(int));
|
|
213 |
//GenExpr(ifThen.RightExpression, typeof(int));
|
|
214 |
//if (ifThen.Operand == RelationalOperands.GreaterThan)
|
|
215 |
//{
|
|
216 |
//
|
|
217 |
//}
|
|
218 |
#endregion
|
|
219 |
|
|
220 |
IfThen ifThen = (IfThen)_statement;
|
|
221 |
Label lblElse = _ILGenerator.DefineLabel();
|
|
222 |
Label lblEnd = _ILGenerator.DefineLabel();
|
|
223 |
|
|
224 |
#region GreaterThan
|
|
225 |
if (ifThen.Operand == RelationalOperands.GreaterThan)
|
|
226 |
{
|
|
227 |
GenerateExpression(ifThen.LeftExpression, typeof(int));
|
|
228 |
GenerateExpression(ifThen.RightExpression, typeof(int));
|
|
229 |
_ILGenerator.Emit(OpCodes.Cgt);
|
|
230 |
_ILGenerator.Emit(OpCodes.Brfalse, lblElse);
|
|
231 |
GenerateStatement(ifThen.ThenBody);
|
|
232 |
_ILGenerator.Emit(OpCodes.Br, lblEnd);
|
|
233 |
|
|
234 |
_ILGenerator.MarkLabel(lblElse);
|
|
235 |
GenerateStatement(ifThen.ElseBody);
|
|
236 |
|
|
237 |
_ILGenerator.MarkLabel(lblEnd);
|
|
238 |
}
|
|
239 |
#endregion
|
|
240 |
#region EqualTo
|
|
241 |
else if (ifThen.Operand == RelationalOperands.EqualTo)
|
|
242 |
{
|
|
243 |
GenerateExpression(ifThen.LeftExpression, typeof(int));
|
|
244 |
GenerateExpression(ifThen.RightExpression, typeof(int));
|
|
245 |
_ILGenerator.Emit(OpCodes.Ceq);
|
|
246 |
_ILGenerator.Emit(OpCodes.Brfalse, lblElse);
|
|
247 |
GenerateStatement(ifThen.ThenBody);
|
|
248 |
_ILGenerator.Emit(OpCodes.Br, lblEnd);
|
|
249 |
|
|
250 |
_ILGenerator.MarkLabel(lblElse);
|
|
251 |
GenerateStatement(ifThen.ElseBody);
|
|
252 |
|
|
253 |
_ILGenerator.MarkLabel(lblEnd);
|
|
254 |
}
|
|
255 |
#endregion
|
|
256 |
#region LessThan
|
|
257 |
else if (ifThen.Operand == RelationalOperands.LessThan)
|
|
258 |
{
|
|
259 |
GenerateExpression(ifThen.LeftExpression, typeof(int));
|
|
260 |
GenerateExpression(ifThen.RightExpression, typeof(int));
|
|
261 |
_ILGenerator.Emit(OpCodes.Clt);
|
|
262 |
_ILGenerator.Emit(OpCodes.Brfalse, lblElse);
|
|
263 |
GenerateStatement(ifThen.ThenBody);
|
|
264 |
_ILGenerator.Emit(OpCodes.Br, lblEnd);
|
|
265 |
|
|
266 |
_ILGenerator.MarkLabel(lblElse);
|
|
267 |
GenerateStatement(ifThen.ElseBody);
|
|
268 |
|
|
269 |
_ILGenerator.MarkLabel(lblEnd);
|
|
270 |
}
|
|
271 |
#endregion
|
|
272 |
|
|
273 |
#region
|
|
274 |
/*
|
|
275 |
Label gtTrue = il.DefineLabel();
|
|
276 |
Label gtFalse = il.DefineLabel();
|
|
277 |
|
|
278 |
|
|
279 |
*/
|
|
280 |
#endregion
|
|
281 |
|
|
282 |
}
|
|
283 |
else if (_statement is For)
|
|
284 |
{
|
|
285 |
// example:
|
|
286 |
// for x = 0 to 100 do
|
|
287 |
// print "hello";
|
|
288 |
// end;
|
|
289 |
|
|
290 |
// x = 0
|
|
291 |
For forLoop = (For)_statement;
|
|
292 |
Assignment assign = new Assignment();
|
|
293 |
assign.Identifier = forLoop.Identifier;
|
|
294 |
assign.Expression = forLoop.From;
|
|
295 |
GenerateStatement(assign);
|
|
296 |
// jump to the test
|
|
297 |
Label test = _ILGenerator.DefineLabel();
|
|
298 |
_ILGenerator.Emit(OpCodes.Br, test);
|
|
299 |
|
|
300 |
// body statement
|
|
301 |
Label body = _ILGenerator.DefineLabel();
|
|
302 |
_ILGenerator.MarkLabel(body);
|
|
303 |
GenerateStatement(forLoop.Body);
|
|
304 |
|
|
305 |
// increase x
|
|
306 |
_ILGenerator.Emit(OpCodes.Ldloc, tblIdentifier[forLoop.Identifier]);
|
|
307 |
_ILGenerator.Emit(OpCodes.Ldc_I4, 1);
|
|
308 |
_ILGenerator.Emit(OpCodes.Add);
|
|
309 |
SaveIdentifier(forLoop.Identifier, typeof(int));
|
|
310 |
|
|
311 |
// check if x is equal to 100
|
|
312 |
_ILGenerator.MarkLabel(test);
|
|
313 |
_ILGenerator.Emit(OpCodes.Ldloc, tblIdentifier[forLoop.Identifier]);
|
|
314 |
GenerateExpression(forLoop.To, typeof(int));
|
|
315 |
_ILGenerator.Emit(OpCodes.Blt, body);
|
|
316 |
}
|
|
317 |
|
|
318 |
else
|
|
319 |
{
|
|
320 |
ExceptionHandler("unable to generate " + _statement.GetType().Name);
|
|
321 |
}
|
|
322 |
}
|
|
323 |
|
|
324 |
public void ExceptionHandler(string strException)
|
|
325 |
{
|
|
326 |
throw new Exception(strException);
|
|
327 |
}
|
|
328 |
|
|
329 |
public void SaveIdentifier(string IdentifierName, System.Type IdentifierType)
|
|
330 |
{
|
|
331 |
if (tblIdentifier.ContainsKey(IdentifierName))
|
|
332 |
{
|
|
333 |
LocalBuilder locb = tblIdentifier[IdentifierName];
|
|
334 |
|
|
335 |
if (locb.LocalType == IdentifierType)
|
|
336 |
{
|
|
337 |
_ILGenerator.Emit(OpCodes.Stloc, tblIdentifier[IdentifierName]);
|
|
338 |
}
|
|
339 |
else
|
|
340 |
{
|
|
341 |
ExceptionHandler("'" + IdentifierName + "' is of type " + locb.LocalType.Name + " but saving in different type " + IdentifierType.Name);
|
|
342 |
}
|
|
343 |
}
|
|
344 |
else
|
|
345 |
{
|
|
346 |
ExceptionHandler("variable not declared '" + IdentifierName + "'");
|
|
347 |
}
|
|
348 |
}
|
|
349 |
|
|
350 |
public void GenerateExpression(Expression _expression, System.Type expressionType)
|
|
351 |
{
|
|
352 |
System.Type typeOfExpression;
|
|
353 |
|
|
354 |
if (_expression is AlphaNumericValue)
|
|
355 |
{
|
|
356 |
typeOfExpression = typeof(string);
|
|
357 |
_ILGenerator.Emit(OpCodes.Ldstr, ((AlphaNumericValue)_expression).Value);
|
|
358 |
}
|
|
359 |
else if (_expression is NumericValue)
|
|
360 |
{
|
|
361 |
typeOfExpression = typeof(int);
|
|
362 |
_ILGenerator.Emit(OpCodes.Ldc_I4, ((NumericValue)_expression).Value);
|
|
363 |
}
|
|
364 |
|
|
365 |
else if (_expression is ArithmaticExpression)
|
|
366 |
{
|
|
367 |
typeOfExpression = GetExpressionType(_expression);
|
|
368 |
|
|
369 |
ArithmaticExpression arithmaticExpression = (ArithmaticExpression)_expression;
|
|
370 |
GenerateExpression(arithmaticExpression.Left, GetExpressionType(arithmaticExpression.Left));
|
|
371 |
GenerateExpression(arithmaticExpression.Right, GetExpressionType(arithmaticExpression.Right));
|
|
372 |
if (arithmaticExpression.Operand == ArithmaticOperands.Add)
|
|
373 |
{
|
|
374 |
_ILGenerator.Emit(OpCodes.Add);
|
|
375 |
}
|
|
376 |
else if (arithmaticExpression.Operand == ArithmaticOperands.Subtract)
|
|
377 |
{
|
|
378 |
_ILGenerator.Emit(OpCodes.Sub);
|
|
379 |
}
|
|
380 |
else if (arithmaticExpression.Operand == ArithmaticOperands.Multiply)
|
|
381 |
{
|
|
382 |
_ILGenerator.Emit(OpCodes.Mul);
|
|
383 |
}
|
|
384 |
else if (arithmaticExpression.Operand == ArithmaticOperands.Division)
|
|
385 |
{
|
|
386 |
_ILGenerator.Emit(OpCodes.Div);
|
|
387 |
}
|
|
388 |
}
|
|
389 |
|
|
390 |
|
|
391 |
else if (_expression is Identifier)
|
|
392 |
{
|
|
393 |
string identifier = ((Identifier)_expression).IdentifierName;
|
|
394 |
typeOfExpression = GetExpressionType(_expression);
|
|
395 |
|
|
396 |
if (!tblIdentifier.ContainsKey(identifier))
|
|
397 |
{
|
|
398 |
ExceptionHandler("undeclared variable '" + identifier + "'");
|
|
399 |
}
|
|
400 |
|
|
401 |
_ILGenerator.Emit(OpCodes.Ldloc, tblIdentifier[identifier]);
|
|
402 |
}
|
|
403 |
|
|
404 |
else
|
|
405 |
{
|
|
406 |
ExceptionHandler("can't generate " + _expression.GetType().Name);
|
|
407 |
typeOfExpression = null;
|
|
408 |
}
|
|
409 |
|
|
410 |
if (typeOfExpression != expressionType)
|
|
411 |
{
|
|
412 |
if (typeOfExpression == typeof(int) &&
|
|
413 |
expressionType == typeof(string))
|
|
414 |
{
|
|
415 |
_ILGenerator.Emit(OpCodes.Box, typeof(int));
|
|
416 |
_ILGenerator.Emit(OpCodes.Callvirt, typeof(object).GetMethod("ToString"));
|
|
417 |
}
|
|
418 |
else
|
|
419 |
{
|
|
420 |
ExceptionHandler("can't convert " + typeOfExpression.Name + " to " + expressionType.Name);
|
|
421 |
}
|
|
422 |
}
|
|
423 |
|
|
424 |
}
|
|
425 |
|
|
426 |
public System.Type GetExpressionType(Expression _expression)
|
|
427 |
{
|
|
428 |
if (_expression is AlphaNumericValue)
|
|
429 |
{
|
|
430 |
return typeof(string);
|
|
431 |
}
|
|
432 |
else if (_expression is NumericValue)
|
|
433 |
{
|
|
434 |
return typeof(int);
|
|
435 |
}
|
|
436 |
else if (_expression is Identifier)
|
|
437 |
{
|
|
438 |
Identifier var = (Identifier)_expression;
|
|
439 |
if (tblIdentifier.ContainsKey(var.IdentifierName))
|
|
440 |
{
|
|
441 |
LocalBuilder locb = tblIdentifier[var.IdentifierName];
|
|
442 |
return locb.LocalType;
|
|
443 |
}
|
|
444 |
else
|
|
445 |
{
|
|
446 |
ExceptionHandler("variable not declared '" + var.IdentifierName + "'");
|
|
447 |
return null;
|
|
448 |
}
|
|
449 |
}
|
|
450 |
else if (_expression is ArithmaticExpression)
|
|
451 |
{
|
|
452 |
return typeof(ArithmaticExpression);
|
|
453 |
}
|
|
454 |
else
|
|
455 |
{
|
|
456 |
ExceptionHandler("type cannot be generated for " + _expression.GetType().Name);
|
|
457 |
return null;
|
|
458 |
}
|
|
459 |
}
|
|
460 |
|
|
461 |
#endregion
|
|
462 |
|
|
463 |
#region Method
|
|
464 |
|
|
465 |
System.Reflection.Emit.ILGenerator _ILMethod = null;
|
|
466 |
public void GenerateStatementMethod(Statement _statement)
|
|
467 |
{
|
|
468 |
#region Statement
|
|
469 |
if (_statement is StatementSequence)
|
|
470 |
{
|
|
471 |
StatementSequence _StatementSequence = (StatementSequence)_statement;
|
|
472 |
GenerateStatementMethod(_StatementSequence.Left);
|
|
473 |
GenerateStatementMethod(_StatementSequence.Right);
|
|
474 |
}
|
|
475 |
#endregion
|
|
476 |
|
|
477 |
#region Declare Variable
|
|
478 |
else if (_statement is DeclareVariable)
|
|
479 |
{
|
|
480 |
// declare a variable in symbol table
|
|
481 |
DeclareVariable declare = (DeclareVariable)_statement;
|
|
482 |
tblIdentifier[declare.Identifier] =
|
|
483 |
_ILMethod.DeclareLocal(GetExpressionTypeMethod(declare.Expression));
|
|
484 |
|
|
485 |
// set the initial value
|
|
486 |
Assignment assign = new Assignment();
|
|
487 |
assign.Identifier = declare.Identifier;
|
|
488 |
assign.Expression = declare.Expression;
|
|
489 |
GenerateStatementMethod(assign);
|
|
490 |
}
|
|
491 |
#endregion
|
|
492 |
|
|
493 |
#region Assignment
|
|
494 |
else if (_statement is Assignment)
|
|
495 |
{
|
|
496 |
Assignment assign = (Assignment)_statement;
|
|
497 |
GenerateExpressionMethod(assign.Expression, GetExpressionTypeMethod(assign.Expression));
|
|
498 |
if (GetExpressionTypeMethod(assign.Expression) == typeof(ArithmaticExpression))
|
|
499 |
{
|
|
500 |
SaveIdentifierMethod(assign.Identifier, typeof(Int32));
|
|
501 |
}
|
|
502 |
else
|
|
503 |
{
|
|
504 |
SaveIdentifierMethod(assign.Identifier,
|
|
505 |
GetExpressionTypeMethod(assign.Expression));
|
|
506 |
}
|
|
507 |
|
|
508 |
}
|
|
509 |
#endregion
|
|
510 |
|
|
511 |
else if (_statement is DeclareFunction)
|
|
512 |
{
|
|
513 |
DeclareFunction _DeclareFunction = (DeclareFunction)_statement;
|
|
514 |
|
|
515 |
string strFunctionName = _DeclareFunction.FunctionName;
|
|
516 |
|
|
517 |
Type ParameterType1 = GetExpressionTypeMethod(_DeclareFunction.Parameter1.Expression);
|
|
518 |
Type ParameterType2 = GetExpressionTypeMethod(_DeclareFunction.Parameter2.Expression);
|
|
519 |
Type ParameterType3 = GetExpressionTypeMethod(_DeclareFunction.Parameter3.Expression);
|
|
520 |
Type[] InputParameters = { ParameterType1, ParameterType2, ParameterType3 };
|
|
521 |
|
|
522 |
Type ReturnType = typeof(void);
|
|
523 |
if(_DeclareFunction.ReturnType == "void")
|
|
524 |
ReturnType = typeof(void);
|
|
525 |
else if (_DeclareFunction.ReturnType == "string")
|
|
526 |
ReturnType = typeof(string);
|
|
527 |
else if (_DeclareFunction.ReturnType == "numeric")
|
|
528 |
ReturnType = typeof(int);
|
|
529 |
|
|
530 |
|
|
531 |
|
|
532 |
//FieldBuilder Parameter1 = _typeBuilder.DefineField(_DeclareFunction.Parameter1.Identifier, ParameterType1, FieldAttributes.Private);
|
|
533 |
//FieldBuilder Parameter2 = _typeBuilder.DefineField(_DeclareFunction.Parameter2.Identifier, ParameterType2, FieldAttributes.Private);
|
|
534 |
//FieldBuilder Parameter3 = _typeBuilder.DefineField(_DeclareFunction.Parameter3.Identifier, ParameterType3, FieldAttributes.Private);
|
|
535 |
|
|
536 |
MethodBuilder NewMethod =
|
|
537 |
_typeBuilder.DefineMethod
|
|
538 |
(strFunctionName,
|
|
539 |
MethodAttributes.Static,
|
|
540 |
ReturnType,
|
|
541 |
InputParameters);
|
|
542 |
|
|
543 |
//ParameterBuilder poolRefBuilder = NewMethod.DefineParameter(1, ParameterAttributes.In, _DeclareFunction.Parameter1.Identifier);
|
|
544 |
|
|
545 |
_ILMethod = NewMethod.GetILGenerator();
|
|
546 |
|
|
547 |
|
|
548 |
//tblArguments[_DeclareFunction.Parameter0.Identifier] = _ILMethod.
|
|
549 |
|
|
550 |
tblArguments[_DeclareFunction.Parameter1.Identifier] = _ILMethod.DeclareLocal(ParameterType1);
|
|
551 |
GenerateExpressionMethod(_DeclareFunction.Parameter1.Expression, ParameterType1);
|
|
552 |
//_ILMethod.Emit(OpCodes.Starg, 0);
|
|
553 |
|
|
554 |
tblArguments[_DeclareFunction.Parameter1.Identifier] = _ILMethod.DeclareLocal(ParameterType2);
|
|
555 |
GenerateExpressionMethod(_DeclareFunction.Parameter1.Expression, ParameterType2);
|
|
556 |
//_ILMethod.Emit(OpCodes.Starg, 1);
|
|
557 |
|
|
558 |
tblArguments[_DeclareFunction.Parameter2.Identifier] = _ILMethod.DeclareLocal(ParameterType3);
|
|
559 |
GenerateExpressionMethod(_DeclareFunction.Parameter2.Expression, ParameterType3);
|
|
560 |
//_ILMethod.Emit(OpCodes.Starg, 2);
|
|
561 |
|
|
562 |
//GenerateStatementMethod(_DeclareFunction.Body);
|
|
563 |
//_ILMethod.Emit(OpCodes.Ret);
|
|
564 |
}
|
|
565 |
|
|
566 |
#region write-read
|
|
567 |
else if (_statement is Write)
|
|
568 |
{
|
|
569 |
// for print keyword, call .net method for printscreen
|
|
570 |
GenerateExpressionMethod(((Write)_statement).Expression,
|
|
571 |
typeof(string));
|
|
572 |
_ILMethod.Emit(OpCodes.Call,
|
|
573 |
typeof(System.Console).GetMethod("WriteLine",
|
|
574 |
new System.Type[] { typeof(string) }));
|
|
575 |
}
|
|
576 |
|
|
577 |
else if (_statement is ReadInput)
|
|
578 |
{
|
|
579 |
// call the readline method and parse input method
|
|
580 |
_ILMethod.Emit(OpCodes.Call,
|
|
581 |
typeof(System.Console).GetMethod("ReadLine",
|
|
582 |
BindingFlags.Public | BindingFlags.Static,
|
|
583 |
null, new System.Type[] { }, null));
|
|
584 |
_ILMethod.Emit(OpCodes.Call,
|
|
585 |
typeof(int).GetMethod("Parse",
|
|
586 |
BindingFlags.Public | BindingFlags.Static,
|
|
587 |
null, new System.Type[] { typeof(string) }, null));
|
|
588 |
// store the input value in local builder
|
|
589 |
SaveIdentifierMethod(((ReadInput)_statement).Identifier, typeof(int));
|
|
590 |
}
|
|
591 |
#endregion
|
|
592 |
|
|
593 |
#region While
|
|
594 |
else if (_statement is While)
|
|
595 |
{
|
|
596 |
While _while = (While)_statement;
|
|
597 |
Label lblTest = _ILMethod.DefineLabel();
|
|
598 |
Label lblEnd = _ILMethod.DefineLabel();
|
|
599 |
|
|
600 |
if (_while.Operand == RelationalOperands.GreaterThan)
|
|
601 |
{
|
|
602 |
_ILMethod.MarkLabel(lblTest);
|
|
603 |
GenerateExpressionMethod(_while.LeftExpression, typeof(int));
|
|
604 |
GenerateExpressionMethod(_while.RightExpression, typeof(int));
|
|
605 |
_ILMethod.Emit(OpCodes.Cgt);
|
|
606 |
_ILMethod.Emit(OpCodes.Brfalse, lblEnd);
|
|
607 |
GenerateStatementMethod(_while.Body);
|
|
608 |
_ILMethod.Emit(OpCodes.Br, lblTest);
|
|
609 |
|
|
610 |
_ILMethod.MarkLabel(lblEnd);
|
|
611 |
}
|
|
612 |
else if (_while.Operand == RelationalOperands.EqualTo)
|
|
613 |
{
|
|
614 |
_ILMethod.MarkLabel(lblTest);
|
|
615 |
GenerateExpressionMethod(_while.LeftExpression, typeof(int));
|
|
616 |
GenerateExpressionMethod(_while.RightExpression, typeof(int));
|
|
617 |
_ILMethod.Emit(OpCodes.Ceq);
|
|
618 |
_ILMethod.Emit(OpCodes.Brfalse, lblEnd);
|
|
619 |
GenerateStatementMethod(_while.Body);
|
|
620 |
_ILMethod.Emit(OpCodes.Br, lblTest);
|
|
621 |
|
|
622 |
_ILMethod.MarkLabel(lblEnd);
|
|
623 |
}
|
|
624 |
else if (_while.Operand == RelationalOperands.LessThan)
|
|
625 |
{
|
|
626 |
_ILMethod.MarkLabel(lblTest);
|
|
627 |
GenerateExpressionMethod(_while.LeftExpression, typeof(int));
|
|
628 |
GenerateExpressionMethod(_while.RightExpression, typeof(int));
|
|
629 |
_ILMethod.Emit(OpCodes.Clt);
|
|
630 |
_ILMethod.Emit(OpCodes.Brfalse, lblEnd);
|
|
631 |
GenerateStatementMethod(_while.Body);
|
|
632 |
_ILMethod.Emit(OpCodes.Br, lblTest);
|
|
633 |
|
|
634 |
_ILMethod.MarkLabel(lblEnd);
|
|
635 |
}
|
|
636 |
}
|
|
637 |
#endregion
|
|
638 |
|
|
639 |
#region If-Then
|
|
640 |
else if (_statement is IfThen)
|
|
641 |
{
|
|
642 |
IfThen ifThen = (IfThen)_statement;
|
|
643 |
Label lblElse = _ILMethod.DefineLabel();
|
|
644 |
Label lblEnd = _ILMethod.DefineLabel();
|
|
645 |
|
|
646 |
#region GreaterThan
|
|
647 |
if (ifThen.Operand == RelationalOperands.GreaterThan)
|
|
648 |
{
|
|
649 |
GenerateExpressionMethod(ifThen.LeftExpression, typeof(int));
|
|
650 |
GenerateExpressionMethod(ifThen.RightExpression, typeof(int));
|
|
651 |
_ILMethod.Emit(OpCodes.Cgt);
|
|
652 |
_ILMethod.Emit(OpCodes.Brfalse, lblElse);
|
|
653 |
GenerateStatementMethod(ifThen.ThenBody);
|
|
654 |
_ILMethod.Emit(OpCodes.Br, lblEnd);
|
|
655 |
|
|
656 |
_ILMethod.MarkLabel(lblElse);
|
|
657 |
GenerateStatementMethod(ifThen.ElseBody);
|
|
658 |
|
|
659 |
_ILMethod.MarkLabel(lblEnd);
|
|
660 |
}
|
|
661 |
#endregion
|
|
662 |
#region EqualTo
|
|
663 |
else if (ifThen.Operand == RelationalOperands.EqualTo)
|
|
664 |
{
|
|
665 |
GenerateExpressionMethod(ifThen.LeftExpression, typeof(int));
|
|
666 |
GenerateExpressionMethod(ifThen.RightExpression, typeof(int));
|
|
667 |
_ILMethod.Emit(OpCodes.Ceq);
|
|
668 |
_ILMethod.Emit(OpCodes.Brfalse, lblElse);
|
|
669 |
GenerateStatementMethod(ifThen.ThenBody);
|
|
670 |
_ILMethod.Emit(OpCodes.Br, lblEnd);
|
|
671 |
|
|
672 |
_ILMethod.MarkLabel(lblElse);
|
|
673 |
GenerateStatementMethod(ifThen.ElseBody);
|
|
674 |
|
|
675 |
_ILMethod.MarkLabel(lblEnd);
|
|
676 |
}
|
|
677 |
#endregion
|
|
678 |
#region LessThan
|
|
679 |
else if (ifThen.Operand == RelationalOperands.LessThan)
|
|
680 |
{
|
|
681 |
GenerateExpressionMethod(ifThen.LeftExpression, typeof(int));
|
|
682 |
GenerateExpressionMethod(ifThen.RightExpression, typeof(int));
|
|
683 |
_ILMethod.Emit(OpCodes.Clt);
|
|
684 |
_ILMethod.Emit(OpCodes.Brfalse, lblElse);
|
|
685 |
GenerateStatementMethod(ifThen.ThenBody);
|
|
686 |
_ILMethod.Emit(OpCodes.Br, lblEnd);
|
|
687 |
|
|
688 |
_ILMethod.MarkLabel(lblElse);
|
|
689 |
GenerateStatementMethod(ifThen.ElseBody);
|
|
690 |
|
|
691 |
_ILMethod.MarkLabel(lblEnd);
|
|
692 |
}
|
|
693 |
#endregion
|
|
694 |
}
|
|
695 |
#endregion
|
|
696 |
|
|
697 |
#region for
|
|
698 |
else if (_statement is For)
|
|
699 |
{
|
|
700 |
For forLoop = (For)_statement;
|
|
701 |
Assignment assign = new Assignment();
|
|
702 |
assign.Identifier = forLoop.Identifier;
|
|
703 |
assign.Expression = forLoop.From;
|
|
704 |
GenerateStatementMethod(assign);
|
|
705 |
|
|
706 |
Label test = _ILMethod.DefineLabel();
|
|
707 |
_ILMethod.Emit(OpCodes.Br, test);
|
|
708 |
|
|
709 |
Label body = _ILMethod.DefineLabel();
|
|
710 |
_ILMethod.MarkLabel(body);
|
|
711 |
GenerateStatementMethod(forLoop.Body);
|
|
712 |
|
|
713 |
_ILMethod.Emit(OpCodes.Ldloc, tblIdentifier[forLoop.Identifier]);
|
|
714 |
_ILMethod.Emit(OpCodes.Ldc_I4, 1);
|
|
715 |
_ILMethod.Emit(OpCodes.Add);
|
|
716 |
SaveIdentifierMethod(forLoop.Identifier, typeof(int));
|
|
717 |
|
|
718 |
_ILMethod.MarkLabel(test);
|
|
719 |
_ILMethod.Emit(OpCodes.Ldloc, tblIdentifier[forLoop.Identifier]);
|
|
720 |
GenerateExpressionMethod(forLoop.To, typeof(int));
|
|
721 |
_ILMethod.Emit(OpCodes.Blt, body);
|
|
722 |
}
|
|
723 |
#endregion
|
|
724 |
|
|
725 |
else
|
|
726 |
{
|
|
727 |
ExceptionHandler("unable to generate " + _statement.GetType().Name);
|
|
728 |
}
|
|
729 |
}
|
|
730 |
|
|
731 |
public void SaveIdentifierMethod(string IdentifierName, System.Type IdentifierType)
|
|
732 |
{
|
|
733 |
if (tblIdentifier.ContainsKey(IdentifierName))
|
|
734 |
{
|
|
735 |
LocalBuilder locb = tblIdentifier[IdentifierName];
|
|
736 |
|
|
737 |
if (locb.LocalType == IdentifierType)
|
|
738 |
{
|
|
739 |
_ILMethod.Emit(OpCodes.Stloc, tblIdentifier[IdentifierName]);
|
|
740 |
}
|
|
741 |
else
|
|
742 |
{
|
|
743 |
ExceptionHandler("'" + IdentifierName + "' is of type " + locb.LocalType.Name + " but saving in different type " + IdentifierType.Name);
|
|
744 |
}
|
|
745 |
}
|
|
746 |
else
|
|
747 |
{
|
|
748 |
ExceptionHandler("variable not declared '" + IdentifierName + "'");
|
|
749 |
}
|
|
750 |
}
|
|
751 |
|
|
752 |
public void DeclareArgument() { }
|
|
753 |
|
|
754 |
public void GenerateExpressionMethod(Expression _expression, System.Type expressionType)
|
|
755 |
{
|
|
756 |
System.Type typeOfExpression;
|
|
757 |
|
|
758 |
if (_expression is AlphaNumericValue)
|
|
759 |
{
|
|
760 |
typeOfExpression = typeof(string);
|
|
761 |
_ILMethod.Emit(OpCodes.Ldstr, ((AlphaNumericValue)_expression).Value);
|
|
762 |
}
|
|
763 |
else if (_expression is NumericValue)
|
|
764 |
{
|
|
765 |
typeOfExpression = typeof(int);
|
|
766 |
_ILMethod.Emit(OpCodes.Ldc_I4, ((NumericValue)_expression).Value);
|
|
767 |
}
|
|
768 |
|
|
769 |
else if (_expression is ArithmaticExpression)
|
|
770 |
{
|
|
771 |
typeOfExpression = GetExpressionTypeMethod(_expression);
|
|
772 |
|
|
773 |
ArithmaticExpression arithmaticExpression = (ArithmaticExpression)_expression;
|
|
774 |
GenerateExpressionMethod(arithmaticExpression.Left, GetExpressionTypeMethod(arithmaticExpression.Left));
|
|
775 |
GenerateExpressionMethod(arithmaticExpression.Right, GetExpressionTypeMethod(arithmaticExpression.Right));
|
|
776 |
if (arithmaticExpression.Operand == ArithmaticOperands.Add)
|
|
777 |
{
|
|
778 |
_ILMethod.Emit(OpCodes.Add);
|
|
779 |
}
|
|
780 |
else if (arithmaticExpression.Operand == ArithmaticOperands.Subtract)
|
|
781 |
{
|
|
782 |
_ILMethod.Emit(OpCodes.Sub);
|
|
783 |
}
|
|
784 |
else if (arithmaticExpression.Operand == ArithmaticOperands.Multiply)
|
|
785 |
{
|
|
786 |
_ILMethod.Emit(OpCodes.Mul);
|
|
787 |
}
|
|
788 |
else if (arithmaticExpression.Operand == ArithmaticOperands.Division)
|
|
789 |
{
|
|
790 |
_ILMethod.Emit(OpCodes.Div);
|
|
791 |
}
|
|
792 |
}
|
|
793 |
|
|
794 |
|
|
795 |
else if (_expression is Identifier)
|
|
796 |
{
|
|
797 |
string identifier = ((Identifier)_expression).IdentifierName;
|
|
798 |
typeOfExpression = GetExpressionTypeMethod(_expression);
|
|
799 |
|
|
800 |
if (!tblIdentifier.ContainsKey(identifier) && !tblArguments.ContainsKey(identifier))
|
|
801 |
{
|
|
802 |
ExceptionHandler("undeclared variable '" + identifier + "'");
|
|
803 |
}
|
|
804 |
|
|
805 |
if (tblIdentifier.ContainsKey(identifier))
|
|
806 |
_ILMethod.Emit(OpCodes.Ldloc, tblIdentifier[identifier]);
|
|
807 |
else
|
|
808 |
_ILMethod.Emit(OpCodes.Ldloc, tblArguments[identifier]);
|
|
809 |
}
|
|
810 |
|
|
811 |
else
|
|
812 |
{
|
|
813 |
ExceptionHandler("can't generate " + _expression.GetType().Name);
|
|
814 |
typeOfExpression = null;
|
|
815 |
}
|
|
816 |
|
|
817 |
if (typeOfExpression != expressionType)
|
|
818 |
{
|
|
819 |
if (typeOfExpression == typeof(int) &&
|
|
820 |
expressionType == typeof(string))
|
|
821 |
{
|
|
822 |
_ILMethod.Emit(OpCodes.Box, typeof(int));
|
|
823 |
_ILMethod.Emit(OpCodes.Callvirt, typeof(object).GetMethod("ToString"));
|
|
824 |
}
|
|
825 |
else
|
|
826 |
{
|
|
827 |
ExceptionHandler("can't convert " + typeOfExpression.Name + " to " + expressionType.Name);
|
|
828 |
}
|
|
829 |
}
|
|
830 |
|
|
831 |
}
|
|
832 |
|
|
833 |
public System.Type GetExpressionTypeMethod(Expression _expression)
|
|
834 |
{
|
|
835 |
if (_expression is AlphaNumericValue)
|
|
836 |
{
|
|
837 |
return typeof(string);
|
|
838 |
}
|
|
839 |
else if (_expression is NumericValue)
|
|
840 |
{
|
|
841 |
return typeof(int);
|
|
842 |
}
|
|
843 |
else if (_expression is Identifier)
|
|
844 |
{
|
|
845 |
Identifier var = (Identifier)_expression;
|
|
846 |
if (tblIdentifier.ContainsKey(var.IdentifierName))
|
|
847 |
{
|
|
848 |
LocalBuilder locb = tblIdentifier[var.IdentifierName];
|
|
849 |
return locb.LocalType;
|
|
850 |
}
|
|
851 |
else if (tblArguments.ContainsKey(var.IdentifierName))
|
|
852 |
{
|
|
853 |
LocalBuilder locb = tblArguments[var.IdentifierName];
|
|
854 |
return locb.LocalType;
|
|
855 |
}
|
|
856 |
else
|
|
857 |
{
|
|
858 |
ExceptionHandler("variable not declared '" + var.IdentifierName + "'");
|
|
859 |
return null;
|
|
860 |
}
|
|
861 |
}
|
|
862 |
else if (_expression is ArithmaticExpression)
|
|
863 |
{
|
|
864 |
return typeof(ArithmaticExpression);
|
|
865 |
}
|
|
866 |
else
|
|
867 |
{
|
|
868 |
ExceptionHandler("type cannot be generated for " + _expression.GetType().Name);
|
|
869 |
return null;
|
|
870 |
}
|
|
871 |
}
|
|
872 |
#endregion
|
|
873 |
}
|
|
874 |
|