|
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 |