/*private void Store(string name, System.Type type, ref ILGenerator il, SymbolTable symbolTable) * { * if (symbolTable.locals.ContainsKey(name)) * { * LocalBuilder locb = symbolTable.locals[name]; * * if (locb.LocalType == type) * { * il.Emit(OpCodes.Stloc, symbolTable.locals[name]); * } * else * { * throw new System.Exception("'" + name + "' is of type " + locb.LocalType.Name + " but attempted to store value of type " + type.Name); * } * } * else * { * throw new System.Exception("undeclared variable '" + name + "'"); * } * }*/ private void GenExpr(ParseTreeNode expr, System.Type expectedType, ILGenerator il, SymbolTable symbolTable) { Type deliveredType; if (expr.Term.Name == "stringLiteral") { deliveredType = typeof(string); il.Emit(OpCodes.Ldstr, expr.Token.ValueString); } else if (expr.Term.Name == "number") { if (expr.Token.Value is int) { deliveredType = typeof(int); il.Emit(OpCodes.Ldc_I4, (int)expr.Token.Value); } else { deliveredType = typeof(float); il.Emit(OpCodes.Ldc_R4, float.Parse(expr.Token.ValueString)); } } else if (expr.Term.Name == "binExpr") { deliveredType = TypeOfExpr(expr.ChildNodes[0], symbolTable); GenExpr(expr.ChildNodes[0], deliveredType, il, symbolTable); GenExpr(expr.ChildNodes[2], deliveredType, il, symbolTable); switch (expr.ChildNodes[1].Term.Name) { case "+": il.Emit(OpCodes.Add); break; case "*": il.Emit(OpCodes.Mul); break; case "-": il.Emit(OpCodes.Sub); break; case "/": il.Emit(OpCodes.Div); break; case "mod": il.Emit(OpCodes.Rem); break; default: throw new Exception("Unrecognized operator " + expr.ChildNodes[1].Term.Name); } } else if (expr.Term.Name == "identifier") { string ident = expr.Token.ValueString; symbolTable.PushVar(ident, ref il); deliveredType = this.TypeOfExpr(expr, symbolTable); } else if (expr.Term.Name == "functionCall") { deliveredType = TypeOfExpr(expr, symbolTable); string funcName = expr.ChildNodes[0].Token.ValueString; if (!this.functionTable.ContainsKey(funcName)) { throw new System.Exception("undeclared function or procedure '" + funcName + "'"); } var parameters = this.functionTable[funcName].arguments; int currentArgument = 0; if (expr.ChildNodes[1].ChildNodes.Count > 0) {//push all the arguments onto the stack ParseTreeNode argItem = expr.ChildNodes[1]; while (true) { this.GenExpr(argItem.ChildNodes[0], parameters[currentArgument].argType, il, symbolTable); if (argItem.ChildNodes.Count == 1) { break; } argItem = argItem.ChildNodes[1]; currentArgument++; } } il.Emit(OpCodes.Call, this.functionTable[funcName].methodDefinition); } else { throw new System.Exception("don't know how to generate " + expr.GetType().Name); } if (deliveredType != expectedType) { if (deliveredType == typeof(int) && expectedType == typeof(string)) { il.Emit(OpCodes.Box, typeof(int)); il.Emit(OpCodes.Callvirt, typeof(object).GetMethod("ToString")); } else if (deliveredType == typeof(float) && expectedType == typeof(string)) { il.Emit(OpCodes.Box, typeof(float)); il.Emit(OpCodes.Callvirt, typeof(object).GetMethod("ToString")); } else { throw new System.Exception("can't coerce a " + deliveredType.Name + " to a " + expectedType.Name); } } }
/*private void Store(string name, System.Type type, ref ILGenerator il, SymbolTable symbolTable) { if (symbolTable.locals.ContainsKey(name)) { LocalBuilder locb = symbolTable.locals[name]; if (locb.LocalType == type) { il.Emit(OpCodes.Stloc, symbolTable.locals[name]); } else { throw new System.Exception("'" + name + "' is of type " + locb.LocalType.Name + " but attempted to store value of type " + type.Name); } } else { throw new System.Exception("undeclared variable '" + name + "'"); } }*/ private void GenExpr(ParseTreeNode expr, System.Type expectedType, ILGenerator il, SymbolTable symbolTable) { Type deliveredType; if (expr.Term.Name == "stringLiteral") { deliveredType = typeof(string); il.Emit(OpCodes.Ldstr, expr.Token.ValueString); } else if (expr.Term.Name == "number") { if (expr.Token.Value is int) { deliveredType = typeof(int); il.Emit(OpCodes.Ldc_I4, (int)expr.Token.Value); } else { deliveredType = typeof(float); il.Emit(OpCodes.Ldc_R4, float.Parse(expr.Token.ValueString)); } } else if (expr.Term.Name == "binExpr") { deliveredType = TypeOfExpr(expr.ChildNodes[0], symbolTable); GenExpr(expr.ChildNodes[0], deliveredType, il, symbolTable); GenExpr(expr.ChildNodes[2], deliveredType, il, symbolTable); switch (expr.ChildNodes[1].Term.Name) { case "+": il.Emit(OpCodes.Add); break; case "*": il.Emit(OpCodes.Mul); break; case "-": il.Emit(OpCodes.Sub); break; case "/": il.Emit(OpCodes.Div); break; case "mod": il.Emit(OpCodes.Rem); break; default: throw new Exception("Unrecognized operator " + expr.ChildNodes[1].Term.Name); } } else if (expr.Term.Name == "identifier") { string ident = expr.Token.ValueString; symbolTable.PushVar(ident, ref il); deliveredType = this.TypeOfExpr(expr, symbolTable); } else if (expr.Term.Name == "functionCall") { deliveredType = TypeOfExpr(expr, symbolTable); string funcName = expr.ChildNodes[0].Token.ValueString; if (!this.functionTable.ContainsKey(funcName)) { throw new System.Exception("undeclared function or procedure '" + funcName+ "'"); } var parameters = this.functionTable[funcName].arguments; int currentArgument = 0; if (expr.ChildNodes[1].ChildNodes.Count > 0) {//push all the arguments onto the stack ParseTreeNode argItem = expr.ChildNodes[1]; while (true) { this.GenExpr(argItem.ChildNodes[0], parameters[currentArgument].argType, il, symbolTable); if (argItem.ChildNodes.Count == 1) break; argItem = argItem.ChildNodes[1]; currentArgument++; } } il.Emit(OpCodes.Call, this.functionTable[funcName].methodDefinition); } else { throw new System.Exception("don't know how to generate " + expr.GetType().Name); } if (deliveredType != expectedType) { if (deliveredType == typeof(int) && expectedType == typeof(string)) { il.Emit(OpCodes.Box, typeof(int)); il.Emit(OpCodes.Callvirt, typeof(object).GetMethod("ToString")); } else if (deliveredType==typeof(float)&&expectedType==typeof(string)) { il.Emit(OpCodes.Box, typeof(float)); il.Emit(OpCodes.Callvirt, typeof(object).GetMethod("ToString")); } else { throw new System.Exception("can't coerce a " + deliveredType.Name + " to a " + expectedType.Name); } } }