diff -r a751aa1ee4f7 -r 7545b1bc1514 Fahad/MCG-CS/CodeGenerator.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Fahad/MCG-CS/CodeGenerator.cs Wed Nov 12 12:24:26 2014 +0000 @@ -0,0 +1,874 @@ +using System; +using System.Collections.Generic; +using System.Text; +// Added +using System.Reflection; +using System.Reflection.Emit; +using System.IO; + +public sealed class CodeGenerator +{ + + Dictionary tblIdentifier; + Dictionary tblArguments; + TypeBuilder _typeBuilder = null; + System.Reflection.Emit.ILGenerator _ILGenerator = null; + MemberInfo WriteLine = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }); + + #region Statement + public CodeGenerator(Statement statement, string fileName) + { + string strFileName = Path.GetFileNameWithoutExtension(fileName); + + #region Define Assembly + //AssemblyName _AssemblyName = new AssemblyName(Path.GetFileNameWithoutExtension(fileName)); + AssemblyName _AssemblyName = new AssemblyName(strFileName); + AppDomain currentDomain = AppDomain.CurrentDomain; + AssemblyBuilder _AssemblyBuilder = currentDomain.DefineDynamicAssembly(_AssemblyName, AssemblyBuilderAccess.Save); + #endregion + + #region Define Module + ModuleBuilder _ModuleBuilder = _AssemblyBuilder.DefineDynamicModule(fileName); + #endregion + + _typeBuilder = _ModuleBuilder.DefineType("CodeGenerator"); + MethodBuilder _MethodBuilder = _typeBuilder.DefineMethod + ("Main", + MethodAttributes.Static, + typeof(void), + System.Type.EmptyTypes); + + _ILGenerator = _MethodBuilder.GetILGenerator(); + tblIdentifier = new Dictionary(); + tblArguments = new Dictionary(); + + // CIL generation + GenerateStatement(statement); + + _ILGenerator.Emit(OpCodes.Ret); + _typeBuilder.CreateType(); + _ModuleBuilder.CreateGlobalFunctions(); + _AssemblyBuilder.SetEntryPoint(_MethodBuilder); + _AssemblyBuilder.Save(fileName); + tblIdentifier = null; + _ILGenerator = null; + } + + public void GenerateStatement(Statement _statement) + { + if (_statement is StatementSequence) + { + StatementSequence _StatementSequence = (StatementSequence)_statement; + GenerateStatement(_StatementSequence.Left); + GenerateStatement(_StatementSequence.Right); + } + + else if (_statement is DeclareVariable) + { + // declare a variable in symbol table + DeclareVariable declare = (DeclareVariable)_statement; + tblIdentifier[declare.Identifier] = + _ILGenerator.DeclareLocal(GetExpressionType(declare.Expression)); + + // set the initial value + Assignment assign = new Assignment(); + assign.Identifier = declare.Identifier; + assign.Expression = declare.Expression; + GenerateStatement(assign); + } + + else if (_statement is Assignment) + { + Assignment assign = (Assignment)_statement; + GenerateExpression(assign.Expression, + GetExpressionType(assign.Expression)); + if (GetExpressionType(assign.Expression) == typeof(ArithmaticExpression)) + { + SaveIdentifier(assign.Identifier, typeof(Int32)); + } + else + { + SaveIdentifier(assign.Identifier, + GetExpressionType(assign.Expression)); + } + + } + + else if (_statement is DeclareFunction) + { + GenerateStatementMethod(_statement); + } + + else if (_statement is Write) + { + // for print keyword, call .net method for printscreen + GenerateExpression(((Write)_statement).Expression, + typeof(string)); + _ILGenerator.Emit(OpCodes.Call, + typeof(System.Console).GetMethod("WriteLine", + new System.Type[] { typeof(string) })); + } + + else if (_statement is ReadInput) + { + // call the readline method and parse input method + _ILGenerator.Emit(OpCodes.Call, + typeof(System.Console).GetMethod("ReadLine", + BindingFlags.Public | BindingFlags.Static, + null, new System.Type[] { }, null)); + _ILGenerator.Emit(OpCodes.Call, + typeof(int).GetMethod("Parse", + BindingFlags.Public | BindingFlags.Static, + null, new System.Type[] { typeof(string) }, null)); + // store the input value in local builder + SaveIdentifier(((ReadInput)_statement).Identifier, typeof(int)); + } + else if (_statement is IfThenElse) + { + + //IfThenElse ifThenElse = (IfThenElse)stmt; + //RelationalExpression relExpr = (RelationalExpression)ifThenElse.If; + //// if, left side only + //il.Emit(OpCodes.Stloc, symbolTable[relExpr.Left.ToString()]); + //Label lblIf = il.DefineLabel(); + //il.Emit(OpCodes.Br, lblIf); + //// then + //Label lblThen = il.DefineLabel(); + //il.MarkLabel(lblThen); + + } + + else if (_statement is While) + { + While _while = (While)_statement; + Label lblTest = _ILGenerator.DefineLabel(); + Label lblEnd = _ILGenerator.DefineLabel(); + + if (_while.Operand == RelationalOperands.GreaterThan) + { + _ILGenerator.MarkLabel(lblTest); + GenerateExpression(_while.LeftExpression, typeof(int)); + GenerateExpression(_while.RightExpression, typeof(int)); + _ILGenerator.Emit(OpCodes.Cgt); + _ILGenerator.Emit(OpCodes.Brfalse, lblEnd); + GenerateStatement(_while.Body); + _ILGenerator.Emit(OpCodes.Br, lblTest); + + _ILGenerator.MarkLabel(lblEnd); + } + else if (_while.Operand == RelationalOperands.EqualTo) + { + _ILGenerator.MarkLabel(lblTest); + GenerateExpression(_while.LeftExpression, typeof(int)); + GenerateExpression(_while.RightExpression, typeof(int)); + _ILGenerator.Emit(OpCodes.Ceq); + _ILGenerator.Emit(OpCodes.Brfalse, lblEnd); + GenerateStatement(_while.Body); + _ILGenerator.Emit(OpCodes.Br, lblTest); + + _ILGenerator.MarkLabel(lblEnd); + } + else if (_while.Operand == RelationalOperands.LessThan) + { + _ILGenerator.MarkLabel(lblTest); + GenerateExpression(_while.LeftExpression, typeof(int)); + GenerateExpression(_while.RightExpression, typeof(int)); + _ILGenerator.Emit(OpCodes.Clt); + _ILGenerator.Emit(OpCodes.Brfalse, lblEnd); + GenerateStatement(_while.Body); + _ILGenerator.Emit(OpCodes.Br, lblTest); + + _ILGenerator.MarkLabel(lblEnd); + } + } + else if (_statement is IfThen) + { + #region + //////Label body = il.DefineLabel(); + + //////il.Emit(OpCodes.Ldc_I4, 1000); + + + + /* + // var x = 0; + // if x < 5 then + // print "less than 5"; + // endif; + + IfThen ifThen = (IfThen)stmt; + // jump to test + + + // **test** if x LessThan 5? (do the test) + il.MarkLabel(test); + GenExpr(ifThen.LeftExpression, typeof(int)); + + */ + + //Label greaterThan = il.DefineLabel(); + + //IfThen ifThen = (IfThen)stmt; + //GenExpr(ifThen.LeftExpression, typeof(int)); + //GenExpr(ifThen.RightExpression, typeof(int)); + //if (ifThen.Operand == RelationalOperands.GreaterThan) + //{ + // + //} + #endregion + + IfThen ifThen = (IfThen)_statement; + Label lblElse = _ILGenerator.DefineLabel(); + Label lblEnd = _ILGenerator.DefineLabel(); + + #region GreaterThan + if (ifThen.Operand == RelationalOperands.GreaterThan) + { + GenerateExpression(ifThen.LeftExpression, typeof(int)); + GenerateExpression(ifThen.RightExpression, typeof(int)); + _ILGenerator.Emit(OpCodes.Cgt); + _ILGenerator.Emit(OpCodes.Brfalse, lblElse); + GenerateStatement(ifThen.ThenBody); + _ILGenerator.Emit(OpCodes.Br, lblEnd); + + _ILGenerator.MarkLabel(lblElse); + GenerateStatement(ifThen.ElseBody); + + _ILGenerator.MarkLabel(lblEnd); + } + #endregion + #region EqualTo + else if (ifThen.Operand == RelationalOperands.EqualTo) + { + GenerateExpression(ifThen.LeftExpression, typeof(int)); + GenerateExpression(ifThen.RightExpression, typeof(int)); + _ILGenerator.Emit(OpCodes.Ceq); + _ILGenerator.Emit(OpCodes.Brfalse, lblElse); + GenerateStatement(ifThen.ThenBody); + _ILGenerator.Emit(OpCodes.Br, lblEnd); + + _ILGenerator.MarkLabel(lblElse); + GenerateStatement(ifThen.ElseBody); + + _ILGenerator.MarkLabel(lblEnd); + } + #endregion + #region LessThan + else if (ifThen.Operand == RelationalOperands.LessThan) + { + GenerateExpression(ifThen.LeftExpression, typeof(int)); + GenerateExpression(ifThen.RightExpression, typeof(int)); + _ILGenerator.Emit(OpCodes.Clt); + _ILGenerator.Emit(OpCodes.Brfalse, lblElse); + GenerateStatement(ifThen.ThenBody); + _ILGenerator.Emit(OpCodes.Br, lblEnd); + + _ILGenerator.MarkLabel(lblElse); + GenerateStatement(ifThen.ElseBody); + + _ILGenerator.MarkLabel(lblEnd); + } + #endregion + + #region + /* + Label gtTrue = il.DefineLabel(); + Label gtFalse = il.DefineLabel(); + + + */ + #endregion + + } + else if (_statement is For) + { + // example: + // for x = 0 to 100 do + // print "hello"; + // end; + + // x = 0 + For forLoop = (For)_statement; + Assignment assign = new Assignment(); + assign.Identifier = forLoop.Identifier; + assign.Expression = forLoop.From; + GenerateStatement(assign); + // jump to the test + Label test = _ILGenerator.DefineLabel(); + _ILGenerator.Emit(OpCodes.Br, test); + + // body statement + Label body = _ILGenerator.DefineLabel(); + _ILGenerator.MarkLabel(body); + GenerateStatement(forLoop.Body); + + // increase x + _ILGenerator.Emit(OpCodes.Ldloc, tblIdentifier[forLoop.Identifier]); + _ILGenerator.Emit(OpCodes.Ldc_I4, 1); + _ILGenerator.Emit(OpCodes.Add); + SaveIdentifier(forLoop.Identifier, typeof(int)); + + // check if x is equal to 100 + _ILGenerator.MarkLabel(test); + _ILGenerator.Emit(OpCodes.Ldloc, tblIdentifier[forLoop.Identifier]); + GenerateExpression(forLoop.To, typeof(int)); + _ILGenerator.Emit(OpCodes.Blt, body); + } + + else + { + ExceptionHandler("unable to generate " + _statement.GetType().Name); + } + } + + public void ExceptionHandler(string strException) + { + throw new Exception(strException); + } + + public void SaveIdentifier(string IdentifierName, System.Type IdentifierType) + { + if (tblIdentifier.ContainsKey(IdentifierName)) + { + LocalBuilder locb = tblIdentifier[IdentifierName]; + + if (locb.LocalType == IdentifierType) + { + _ILGenerator.Emit(OpCodes.Stloc, tblIdentifier[IdentifierName]); + } + else + { + ExceptionHandler("'" + IdentifierName + "' is of type " + locb.LocalType.Name + " but saving in different type " + IdentifierType.Name); + } + } + else + { + ExceptionHandler("variable not declared '" + IdentifierName + "'"); + } + } + + public void GenerateExpression(Expression _expression, System.Type expressionType) + { + System.Type typeOfExpression; + + if (_expression is AlphaNumericValue) + { + typeOfExpression = typeof(string); + _ILGenerator.Emit(OpCodes.Ldstr, ((AlphaNumericValue)_expression).Value); + } + else if (_expression is NumericValue) + { + typeOfExpression = typeof(int); + _ILGenerator.Emit(OpCodes.Ldc_I4, ((NumericValue)_expression).Value); + } + + else if (_expression is ArithmaticExpression) + { + typeOfExpression = GetExpressionType(_expression); + + ArithmaticExpression arithmaticExpression = (ArithmaticExpression)_expression; + GenerateExpression(arithmaticExpression.Left, GetExpressionType(arithmaticExpression.Left)); + GenerateExpression(arithmaticExpression.Right, GetExpressionType(arithmaticExpression.Right)); + if (arithmaticExpression.Operand == ArithmaticOperands.Add) + { + _ILGenerator.Emit(OpCodes.Add); + } + else if (arithmaticExpression.Operand == ArithmaticOperands.Subtract) + { + _ILGenerator.Emit(OpCodes.Sub); + } + else if (arithmaticExpression.Operand == ArithmaticOperands.Multiply) + { + _ILGenerator.Emit(OpCodes.Mul); + } + else if (arithmaticExpression.Operand == ArithmaticOperands.Division) + { + _ILGenerator.Emit(OpCodes.Div); + } + } + + + else if (_expression is Identifier) + { + string identifier = ((Identifier)_expression).IdentifierName; + typeOfExpression = GetExpressionType(_expression); + + if (!tblIdentifier.ContainsKey(identifier)) + { + ExceptionHandler("undeclared variable '" + identifier + "'"); + } + + _ILGenerator.Emit(OpCodes.Ldloc, tblIdentifier[identifier]); + } + + else + { + ExceptionHandler("can't generate " + _expression.GetType().Name); + typeOfExpression = null; + } + + if (typeOfExpression != expressionType) + { + if (typeOfExpression == typeof(int) && + expressionType == typeof(string)) + { + _ILGenerator.Emit(OpCodes.Box, typeof(int)); + _ILGenerator.Emit(OpCodes.Callvirt, typeof(object).GetMethod("ToString")); + } + else + { + ExceptionHandler("can't convert " + typeOfExpression.Name + " to " + expressionType.Name); + } + } + + } + + public System.Type GetExpressionType(Expression _expression) + { + if (_expression is AlphaNumericValue) + { + return typeof(string); + } + else if (_expression is NumericValue) + { + return typeof(int); + } + else if (_expression is Identifier) + { + Identifier var = (Identifier)_expression; + if (tblIdentifier.ContainsKey(var.IdentifierName)) + { + LocalBuilder locb = tblIdentifier[var.IdentifierName]; + return locb.LocalType; + } + else + { + ExceptionHandler("variable not declared '" + var.IdentifierName + "'"); + return null; + } + } + else if (_expression is ArithmaticExpression) + { + return typeof(ArithmaticExpression); + } + else + { + ExceptionHandler("type cannot be generated for " + _expression.GetType().Name); + return null; + } + } + + #endregion + + #region Method + + System.Reflection.Emit.ILGenerator _ILMethod = null; + public void GenerateStatementMethod(Statement _statement) + { + #region Statement + if (_statement is StatementSequence) + { + StatementSequence _StatementSequence = (StatementSequence)_statement; + GenerateStatementMethod(_StatementSequence.Left); + GenerateStatementMethod(_StatementSequence.Right); + } + #endregion + + #region Declare Variable + else if (_statement is DeclareVariable) + { + // declare a variable in symbol table + DeclareVariable declare = (DeclareVariable)_statement; + tblIdentifier[declare.Identifier] = + _ILMethod.DeclareLocal(GetExpressionTypeMethod(declare.Expression)); + + // set the initial value + Assignment assign = new Assignment(); + assign.Identifier = declare.Identifier; + assign.Expression = declare.Expression; + GenerateStatementMethod(assign); + } + #endregion + + #region Assignment + else if (_statement is Assignment) + { + Assignment assign = (Assignment)_statement; + GenerateExpressionMethod(assign.Expression, GetExpressionTypeMethod(assign.Expression)); + if (GetExpressionTypeMethod(assign.Expression) == typeof(ArithmaticExpression)) + { + SaveIdentifierMethod(assign.Identifier, typeof(Int32)); + } + else + { + SaveIdentifierMethod(assign.Identifier, + GetExpressionTypeMethod(assign.Expression)); + } + + } + #endregion + + else if (_statement is DeclareFunction) + { + DeclareFunction _DeclareFunction = (DeclareFunction)_statement; + + string strFunctionName = _DeclareFunction.FunctionName; + + Type ParameterType1 = GetExpressionTypeMethod(_DeclareFunction.Parameter1.Expression); + Type ParameterType2 = GetExpressionTypeMethod(_DeclareFunction.Parameter2.Expression); + Type ParameterType3 = GetExpressionTypeMethod(_DeclareFunction.Parameter3.Expression); + Type[] InputParameters = { ParameterType1, ParameterType2, ParameterType3 }; + + Type ReturnType = typeof(void); + if(_DeclareFunction.ReturnType == "void") + ReturnType = typeof(void); + else if (_DeclareFunction.ReturnType == "string") + ReturnType = typeof(string); + else if (_DeclareFunction.ReturnType == "numeric") + ReturnType = typeof(int); + + + + //FieldBuilder Parameter1 = _typeBuilder.DefineField(_DeclareFunction.Parameter1.Identifier, ParameterType1, FieldAttributes.Private); + //FieldBuilder Parameter2 = _typeBuilder.DefineField(_DeclareFunction.Parameter2.Identifier, ParameterType2, FieldAttributes.Private); + //FieldBuilder Parameter3 = _typeBuilder.DefineField(_DeclareFunction.Parameter3.Identifier, ParameterType3, FieldAttributes.Private); + + MethodBuilder NewMethod = + _typeBuilder.DefineMethod + (strFunctionName, + MethodAttributes.Static, + ReturnType, + InputParameters); + + //ParameterBuilder poolRefBuilder = NewMethod.DefineParameter(1, ParameterAttributes.In, _DeclareFunction.Parameter1.Identifier); + + _ILMethod = NewMethod.GetILGenerator(); + + + //tblArguments[_DeclareFunction.Parameter0.Identifier] = _ILMethod. + + tblArguments[_DeclareFunction.Parameter1.Identifier] = _ILMethod.DeclareLocal(ParameterType1); + GenerateExpressionMethod(_DeclareFunction.Parameter1.Expression, ParameterType1); + //_ILMethod.Emit(OpCodes.Starg, 0); + + tblArguments[_DeclareFunction.Parameter1.Identifier] = _ILMethod.DeclareLocal(ParameterType2); + GenerateExpressionMethod(_DeclareFunction.Parameter1.Expression, ParameterType2); + //_ILMethod.Emit(OpCodes.Starg, 1); + + tblArguments[_DeclareFunction.Parameter2.Identifier] = _ILMethod.DeclareLocal(ParameterType3); + GenerateExpressionMethod(_DeclareFunction.Parameter2.Expression, ParameterType3); + //_ILMethod.Emit(OpCodes.Starg, 2); + + //GenerateStatementMethod(_DeclareFunction.Body); + //_ILMethod.Emit(OpCodes.Ret); + } + + #region write-read + else if (_statement is Write) + { + // for print keyword, call .net method for printscreen + GenerateExpressionMethod(((Write)_statement).Expression, + typeof(string)); + _ILMethod.Emit(OpCodes.Call, + typeof(System.Console).GetMethod("WriteLine", + new System.Type[] { typeof(string) })); + } + + else if (_statement is ReadInput) + { + // call the readline method and parse input method + _ILMethod.Emit(OpCodes.Call, + typeof(System.Console).GetMethod("ReadLine", + BindingFlags.Public | BindingFlags.Static, + null, new System.Type[] { }, null)); + _ILMethod.Emit(OpCodes.Call, + typeof(int).GetMethod("Parse", + BindingFlags.Public | BindingFlags.Static, + null, new System.Type[] { typeof(string) }, null)); + // store the input value in local builder + SaveIdentifierMethod(((ReadInput)_statement).Identifier, typeof(int)); + } + #endregion + + #region While + else if (_statement is While) + { + While _while = (While)_statement; + Label lblTest = _ILMethod.DefineLabel(); + Label lblEnd = _ILMethod.DefineLabel(); + + if (_while.Operand == RelationalOperands.GreaterThan) + { + _ILMethod.MarkLabel(lblTest); + GenerateExpressionMethod(_while.LeftExpression, typeof(int)); + GenerateExpressionMethod(_while.RightExpression, typeof(int)); + _ILMethod.Emit(OpCodes.Cgt); + _ILMethod.Emit(OpCodes.Brfalse, lblEnd); + GenerateStatementMethod(_while.Body); + _ILMethod.Emit(OpCodes.Br, lblTest); + + _ILMethod.MarkLabel(lblEnd); + } + else if (_while.Operand == RelationalOperands.EqualTo) + { + _ILMethod.MarkLabel(lblTest); + GenerateExpressionMethod(_while.LeftExpression, typeof(int)); + GenerateExpressionMethod(_while.RightExpression, typeof(int)); + _ILMethod.Emit(OpCodes.Ceq); + _ILMethod.Emit(OpCodes.Brfalse, lblEnd); + GenerateStatementMethod(_while.Body); + _ILMethod.Emit(OpCodes.Br, lblTest); + + _ILMethod.MarkLabel(lblEnd); + } + else if (_while.Operand == RelationalOperands.LessThan) + { + _ILMethod.MarkLabel(lblTest); + GenerateExpressionMethod(_while.LeftExpression, typeof(int)); + GenerateExpressionMethod(_while.RightExpression, typeof(int)); + _ILMethod.Emit(OpCodes.Clt); + _ILMethod.Emit(OpCodes.Brfalse, lblEnd); + GenerateStatementMethod(_while.Body); + _ILMethod.Emit(OpCodes.Br, lblTest); + + _ILMethod.MarkLabel(lblEnd); + } + } + #endregion + + #region If-Then + else if (_statement is IfThen) + { + IfThen ifThen = (IfThen)_statement; + Label lblElse = _ILMethod.DefineLabel(); + Label lblEnd = _ILMethod.DefineLabel(); + + #region GreaterThan + if (ifThen.Operand == RelationalOperands.GreaterThan) + { + GenerateExpressionMethod(ifThen.LeftExpression, typeof(int)); + GenerateExpressionMethod(ifThen.RightExpression, typeof(int)); + _ILMethod.Emit(OpCodes.Cgt); + _ILMethod.Emit(OpCodes.Brfalse, lblElse); + GenerateStatementMethod(ifThen.ThenBody); + _ILMethod.Emit(OpCodes.Br, lblEnd); + + _ILMethod.MarkLabel(lblElse); + GenerateStatementMethod(ifThen.ElseBody); + + _ILMethod.MarkLabel(lblEnd); + } + #endregion + #region EqualTo + else if (ifThen.Operand == RelationalOperands.EqualTo) + { + GenerateExpressionMethod(ifThen.LeftExpression, typeof(int)); + GenerateExpressionMethod(ifThen.RightExpression, typeof(int)); + _ILMethod.Emit(OpCodes.Ceq); + _ILMethod.Emit(OpCodes.Brfalse, lblElse); + GenerateStatementMethod(ifThen.ThenBody); + _ILMethod.Emit(OpCodes.Br, lblEnd); + + _ILMethod.MarkLabel(lblElse); + GenerateStatementMethod(ifThen.ElseBody); + + _ILMethod.MarkLabel(lblEnd); + } + #endregion + #region LessThan + else if (ifThen.Operand == RelationalOperands.LessThan) + { + GenerateExpressionMethod(ifThen.LeftExpression, typeof(int)); + GenerateExpressionMethod(ifThen.RightExpression, typeof(int)); + _ILMethod.Emit(OpCodes.Clt); + _ILMethod.Emit(OpCodes.Brfalse, lblElse); + GenerateStatementMethod(ifThen.ThenBody); + _ILMethod.Emit(OpCodes.Br, lblEnd); + + _ILMethod.MarkLabel(lblElse); + GenerateStatementMethod(ifThen.ElseBody); + + _ILMethod.MarkLabel(lblEnd); + } + #endregion + } + #endregion + + #region for + else if (_statement is For) + { + For forLoop = (For)_statement; + Assignment assign = new Assignment(); + assign.Identifier = forLoop.Identifier; + assign.Expression = forLoop.From; + GenerateStatementMethod(assign); + + Label test = _ILMethod.DefineLabel(); + _ILMethod.Emit(OpCodes.Br, test); + + Label body = _ILMethod.DefineLabel(); + _ILMethod.MarkLabel(body); + GenerateStatementMethod(forLoop.Body); + + _ILMethod.Emit(OpCodes.Ldloc, tblIdentifier[forLoop.Identifier]); + _ILMethod.Emit(OpCodes.Ldc_I4, 1); + _ILMethod.Emit(OpCodes.Add); + SaveIdentifierMethod(forLoop.Identifier, typeof(int)); + + _ILMethod.MarkLabel(test); + _ILMethod.Emit(OpCodes.Ldloc, tblIdentifier[forLoop.Identifier]); + GenerateExpressionMethod(forLoop.To, typeof(int)); + _ILMethod.Emit(OpCodes.Blt, body); + } + #endregion + + else + { + ExceptionHandler("unable to generate " + _statement.GetType().Name); + } + } + + public void SaveIdentifierMethod(string IdentifierName, System.Type IdentifierType) + { + if (tblIdentifier.ContainsKey(IdentifierName)) + { + LocalBuilder locb = tblIdentifier[IdentifierName]; + + if (locb.LocalType == IdentifierType) + { + _ILMethod.Emit(OpCodes.Stloc, tblIdentifier[IdentifierName]); + } + else + { + ExceptionHandler("'" + IdentifierName + "' is of type " + locb.LocalType.Name + " but saving in different type " + IdentifierType.Name); + } + } + else + { + ExceptionHandler("variable not declared '" + IdentifierName + "'"); + } + } + + public void DeclareArgument() { } + + public void GenerateExpressionMethod(Expression _expression, System.Type expressionType) + { + System.Type typeOfExpression; + + if (_expression is AlphaNumericValue) + { + typeOfExpression = typeof(string); + _ILMethod.Emit(OpCodes.Ldstr, ((AlphaNumericValue)_expression).Value); + } + else if (_expression is NumericValue) + { + typeOfExpression = typeof(int); + _ILMethod.Emit(OpCodes.Ldc_I4, ((NumericValue)_expression).Value); + } + + else if (_expression is ArithmaticExpression) + { + typeOfExpression = GetExpressionTypeMethod(_expression); + + ArithmaticExpression arithmaticExpression = (ArithmaticExpression)_expression; + GenerateExpressionMethod(arithmaticExpression.Left, GetExpressionTypeMethod(arithmaticExpression.Left)); + GenerateExpressionMethod(arithmaticExpression.Right, GetExpressionTypeMethod(arithmaticExpression.Right)); + if (arithmaticExpression.Operand == ArithmaticOperands.Add) + { + _ILMethod.Emit(OpCodes.Add); + } + else if (arithmaticExpression.Operand == ArithmaticOperands.Subtract) + { + _ILMethod.Emit(OpCodes.Sub); + } + else if (arithmaticExpression.Operand == ArithmaticOperands.Multiply) + { + _ILMethod.Emit(OpCodes.Mul); + } + else if (arithmaticExpression.Operand == ArithmaticOperands.Division) + { + _ILMethod.Emit(OpCodes.Div); + } + } + + + else if (_expression is Identifier) + { + string identifier = ((Identifier)_expression).IdentifierName; + typeOfExpression = GetExpressionTypeMethod(_expression); + + if (!tblIdentifier.ContainsKey(identifier) && !tblArguments.ContainsKey(identifier)) + { + ExceptionHandler("undeclared variable '" + identifier + "'"); + } + + if (tblIdentifier.ContainsKey(identifier)) + _ILMethod.Emit(OpCodes.Ldloc, tblIdentifier[identifier]); + else + _ILMethod.Emit(OpCodes.Ldloc, tblArguments[identifier]); + } + + else + { + ExceptionHandler("can't generate " + _expression.GetType().Name); + typeOfExpression = null; + } + + if (typeOfExpression != expressionType) + { + if (typeOfExpression == typeof(int) && + expressionType == typeof(string)) + { + _ILMethod.Emit(OpCodes.Box, typeof(int)); + _ILMethod.Emit(OpCodes.Callvirt, typeof(object).GetMethod("ToString")); + } + else + { + ExceptionHandler("can't convert " + typeOfExpression.Name + " to " + expressionType.Name); + } + } + + } + + public System.Type GetExpressionTypeMethod(Expression _expression) + { + if (_expression is AlphaNumericValue) + { + return typeof(string); + } + else if (_expression is NumericValue) + { + return typeof(int); + } + else if (_expression is Identifier) + { + Identifier var = (Identifier)_expression; + if (tblIdentifier.ContainsKey(var.IdentifierName)) + { + LocalBuilder locb = tblIdentifier[var.IdentifierName]; + return locb.LocalType; + } + else if (tblArguments.ContainsKey(var.IdentifierName)) + { + LocalBuilder locb = tblArguments[var.IdentifierName]; + return locb.LocalType; + } + else + { + ExceptionHandler("variable not declared '" + var.IdentifierName + "'"); + return null; + } + } + else if (_expression is ArithmaticExpression) + { + return typeof(ArithmaticExpression); + } + else + { + ExceptionHandler("type cannot be generated for " + _expression.GetType().Name); + return null; + } + } + #endregion +} +