public static LocalObjectDef AllocateLocal(Type type, string name = "") { List <LocalObjectDef> duplicatedLocals = new List <LocalObjectDef>(); int number = 0; int i; for (i = 0; i < Locals_.Count; i++) { if (Locals_[i].Scope == enmObjectScope.Local && (Locals_[i] as LocalObjectDef).Name == name && name != "") { duplicatedLocals.Add(Locals_[i] as LocalObjectDef); Locals_[i].IsUsed = false; } } for (i = 0; i < Locals_.Count; i++) { if (Locals_[i].Type.Name == type.Name && !Locals_[i].IsUsed) { number = i; Locals_[i] = new LocalObjectDef(type, number, name); break; } } if (i == Locals_.Count) { var localVar = Generator_.DeclareLocal(type); number = localVar.LocalIndex; Locals_.Add(new LocalObjectDef(type, number, name)); } EmitSaveToLocal(number); return(Locals_[number]); }
protected void EmitFunction(ITree functionNode) { string functionName = functionNode.GetChild(0).Text; Type functionReturnType = GetType(functionNode.GetChild(1).Text); CurrentArgs_ = Functions_[CurrentTypeBuilder_.Name][functionName].Args; CurrentILGenerator_ = Functions_[CurrentTypeBuilder_.Name][functionName].MethodBuilder.GetILGenerator(); LocalObjectDef.InitGenerator(CurrentILGenerator_); var returnObjectDef = EmitExpression(functionNode.GetChild(2)); returnObjectDef.Load(); if (!functionReturnType.IsAssignableFrom(returnObjectDef.Type)) { //if (!returnObjectDef.Type.IsAssignableFrom(functionReturnType)) CompilerErrors.Add(new InvalidReturnTypeError( Functions_[CurrentTypeBuilder_.Name][functionName].MethodBuilder, returnObjectDef.Type, CompilerErrors.Count, functionNode.GetChild(2).Line, functionNode.GetChild(2).CharPositionInLine)); } if (Functions_[CurrentTypeBuilder_.Name][functionName].MethodBuilder.ReturnType == typeof(void)) { CurrentILGenerator_.Emit(OpCodes.Pop); } CurrentILGenerator_.Emit(OpCodes.Ret); returnObjectDef.Remove(); }
protected ObjectDef EmitIfBranch(ITree expressionNode) { // Возможна оптимизация (Brtrue, Brfalse_S). var checkObjectDef = EmitExpression(expressionNode.GetChild(0)); checkObjectDef.Load(); checkObjectDef.Remove(); if (checkObjectDef.Type != BoolType) { CompilerErrors.Add(new IfOperatorError(checkObjectDef.Type, CompilerErrors.Count, expressionNode.GetChild(0).Line, expressionNode.GetChild(0).CharPositionInLine)); } var exitLabel = CurrentILGenerator_.DefineLabel(); var elseLabel = CurrentILGenerator_.DefineLabel(); CurrentILGenerator_.Emit(OpCodes.Brfalse, elseLabel); var ifObjectDef = EmitExpression(expressionNode.GetChild(1)); ifObjectDef.Load(); ifObjectDef.Remove(); CurrentILGenerator_.Emit(OpCodes.Br, exitLabel); CurrentILGenerator_.MarkLabel(elseLabel); var elseObjectDef = EmitExpression(expressionNode.GetChild(2)); elseObjectDef.Load(); elseObjectDef.Remove(); CurrentILGenerator_.MarkLabel(exitLabel); return(LocalObjectDef.AllocateLocal(GetMostNearestAncestor(ifObjectDef.Type, elseObjectDef.Type))); }
protected void EmitField(ITree fieldNode) { CurrentILGenerator_ = Constructors_[CurrentTypeBuilder_.Name].GetILGenerator(); LocalObjectDef.InitGenerator(CurrentILGenerator_); ObjectDef returnObjectDef; if (fieldNode.ChildCount == 3) { returnObjectDef = EmitExpression(fieldNode.GetChild(2)); } else { returnObjectDef = EmitDefaultValue(GetType(fieldNode.GetChild(1).Text)); } if (!Constructors_[CurrentTypeBuilder_.Name].IsStatic) { CurrentILGenerator_.Emit(OpCodes.Ldarg_0); returnObjectDef.Load(); CurrentILGenerator_.Emit(OpCodes.Stfld, Fields_[CurrentTypeBuilder_.Name][fieldNode.GetChild(0).Text].FieldInfo); } else { returnObjectDef.Load(); CurrentILGenerator_.Emit(OpCodes.Stsfld, Fields_[CurrentTypeBuilder_.Name][fieldNode.GetChild(0).Text].FieldInfo); } returnObjectDef.Remove(); }
protected ObjectDef EmitLetOperation(ITree expressionNode) { List <ObjectDef> localObjectDefs = new List <ObjectDef>(); for (int i = 0; i < expressionNode.GetChild(0).ChildCount; i++) { var localOrFieldInitNode = expressionNode.GetChild(0).GetChild(i); var type = GetType(localOrFieldInitNode.GetChild(1).Text); ObjectDef localReturnObjectDef; if (localOrFieldInitNode.ChildCount == 3) { localReturnObjectDef = EmitExpression(localOrFieldInitNode.GetChild(2)); } else { localReturnObjectDef = EmitDefaultValue(type); } localReturnObjectDef.Load(); //localReturnObjectDef.Remove(); var localObjectDef = LocalObjectDef.AllocateLocal(type, localOrFieldInitNode.GetChild(0).Text); localObjectDefs.Add(localObjectDef); } var returnObjectDef = EmitExpression(expressionNode.GetChild(1)); foreach (var localObjectDef in localObjectDefs) { localObjectDef.Free(); } return(returnObjectDef); }
protected ObjectDef EmitNegOperation(ITree expressionNode) { var returnObject = EmitExpression(expressionNode.GetChild(0)); if (IsStaticType(returnObject.Type)) { CompilerErrors.Add(new NegOperationError(returnObject.Type, CompilerErrors.Count, expressionNode.GetChild(0).Line, expressionNode.GetChild(0).CharPositionInLine)); } else { returnObject.Load(); CurrentILGenerator_.Emit(OpCodes.Not); returnObject.Load(); } return(LocalObjectDef.AllocateLocal(IntegerType)); }
protected ObjectDef EmitIsVoidChecking(ITree expressionNode) { var returnObject = EmitExpression(expressionNode.GetChild(0)); if (IsStaticType(returnObject.Type)) { CompilerErrors.Add(new IsVoidCheckingError(CompilerErrors.Count, expressionNode.GetChild(0).Line, expressionNode.GetChild(0).CharPositionInLine)); } else { returnObject.Load(); CurrentILGenerator_.Emit(OpCodes.Ldnull); CurrentILGenerator_.Emit(OpCodes.Ceq); returnObject.Remove(); } return(LocalObjectDef.AllocateLocal(BoolType)); }
protected ObjectDef EmitComparsionOperation(ITree expressionNode) { var returnObject2 = EmitExpression(expressionNode.GetChild(1)); var returnObject1 = EmitExpression(expressionNode.GetChild(0)); if (returnObject1.Type != IntegerType || returnObject1.Type != returnObject2.Type) { CompilerErrors.Add(new ComparsionOperatorError(returnObject1.Type, returnObject2.Type, CompilerErrors.Count, expressionNode.Line, expressionNode.GetChild(0).CharPositionInLine, expressionNode.GetChild(1).CharPositionInLine)); } else { returnObject1.Load(); returnObject2.Load(); if (expressionNode.Type == CoolGrammarLexer.LT) { CurrentILGenerator_.Emit(OpCodes.Clt); } else if (expressionNode.Type == CoolGrammarLexer.LE) { CurrentILGenerator_.Emit(OpCodes.Cgt); CurrentILGenerator_.Emit(OpCodes.Ldc_I4_0); CurrentILGenerator_.Emit(OpCodes.Ceq); } else if (expressionNode.Type == CoolGrammarLexer.GT) { CurrentILGenerator_.Emit(OpCodes.Cgt); } else if (expressionNode.Type == CoolGrammarLexer.GE) { CurrentILGenerator_.Emit(OpCodes.Clt); CurrentILGenerator_.Emit(OpCodes.Ldc_I4_0); CurrentILGenerator_.Emit(OpCodes.Ceq); } returnObject1.Remove(); returnObject2.Remove(); } return(LocalObjectDef.AllocateLocal(BoolType)); }
protected ObjectDef EmitNotOperation(ITree expressionNode) { var returnObject = EmitExpression(expressionNode.GetChild(0)); if (returnObject.Type != BoolType) { CompilerErrors.Add(new NotOperationError(returnObject.Type, CompilerErrors.Count, expressionNode.GetChild(0).Line, expressionNode.GetChild(0).CharPositionInLine)); } else { returnObject.Load(); CurrentILGenerator_.Emit(OpCodes.Ldc_I4_0); CurrentILGenerator_.Emit(OpCodes.Ceq); returnObject.Remove(); } return(LocalObjectDef.AllocateLocal(BoolType)); }
protected ObjectDef EmitArithmeticOperation(ITree expressionNode) { var returnObject1 = EmitExpression(expressionNode.GetChild(0)); var returnObject2 = EmitExpression(expressionNode.GetChild(1)); if (returnObject1.Type != IntegerType || returnObject1.Type != returnObject2.Type) { CompilerErrors.Add(new ArithmeticOperatorError( returnObject1.Type, returnObject2.Type, CompilerErrors.Count, expressionNode.Line, expressionNode.GetChild(1).CharPositionInLine, expressionNode.GetChild(0).CharPositionInLine)); } else { returnObject1.Load(); returnObject2.Load(); if (expressionNode.Type == CoolGrammarLexer.PLUS) { CurrentILGenerator_.Emit(OpCodes.Add); } else if (expressionNode.Type == CoolGrammarLexer.MINUS) { CurrentILGenerator_.Emit(OpCodes.Sub); } else if (expressionNode.Type == CoolGrammarLexer.MULT) { CurrentILGenerator_.Emit(OpCodes.Mul); } else if (expressionNode.Type == CoolGrammarLexer.DIV) { CurrentILGenerator_.Emit(OpCodes.Div); } returnObject1.Remove(); returnObject2.Remove(); } return(LocalObjectDef.AllocateLocal(IntegerType)); }
protected ObjectDef EmitIdValue(ITree expressionNode) { var idValue = expressionNode.Text; LocalObjectDef localObjectDef; if ((localObjectDef = LocalObjectDef.GetLocalObjectDef(idValue)) != null) { return(localObjectDef); } else if (CurrentArgs_.ContainsKey(idValue)) { return(CurrentArgs_[idValue]); } else if (Fields_[CurrentTypeBuilder_.Name].ContainsKey(idValue)) { return(Fields_[CurrentTypeBuilder_.Name][idValue]); } else { CompilerErrors.Add(new UndefinedIdError(idValue, CompilerErrors.Count, expressionNode.Line, expressionNode.CharPositionInLine)); return(new ValueObjectDef(typeof(object), null)); } }
protected ObjectDef EmitInvoke(ITree invokeExpressionNode, ITree atSignNode, ITree functionNode, ITree argsExpressionNode) { var functionName = functionNode.Text; ObjectDef invokeObjectDef; MethodBuilder methodBuilder; string invokeObjectName; if (invokeExpressionNode != null) { invokeObjectDef = EmitExpression(invokeExpressionNode); invokeObjectName = invokeObjectDef.Type.Name; } else { invokeObjectDef = new ArgObjectDef(CurrentTypeBuilder_, 0, "this"); invokeObjectName = CurrentTypeBuilder_.Name; } ObjectDef result; if (!Functions_.ContainsKey(invokeObjectName) || !Functions_[invokeObjectName].ContainsKey(functionName)) { CompilerErrors.Add(new UndefinedFunctionError(functionName, invokeObjectName, CompilerErrors.Count, functionNode.Line, functionNode.CharPositionInLine)); result = LocalObjectDef.AllocateLocal(typeof(object)); } else { methodBuilder = Functions_[invokeObjectName][functionName].MethodBuilder; var args = new List <ObjectDef>(); args.Add(invokeObjectDef); if (argsExpressionNode != null) { for (int i = 0; i < argsExpressionNode.ChildCount; i++) { var objectDef = EmitExpression(argsExpressionNode.GetChild(i)); args.Add(objectDef); } List <ArgObjectDef> args2 = new List <ArgObjectDef>(); foreach (var arg in Functions_[invokeObjectDef.Type.Name][functionName].Args) { args2.Add(arg.Value); } if (!CheckTypes(args, args2)) { var args2types = new List <Type>(); foreach (var arg in args2) { args2types.Add(arg.Type); } CompilerErrors.Add(new FunctionArgumentsError(functionName, args2types, CompilerErrors.Count, functionNode.Line, functionNode.CharPositionInLine)); } } foreach (var arg in args) { arg.Load(); } if (invokeExpressionNode == null) { CurrentILGenerator_.Emit(OpCodes.Call, methodBuilder); } else { CurrentILGenerator_.Emit(OpCodes.Callvirt, methodBuilder); } foreach (var arg in args) { arg.Remove(); } invokeObjectDef.Remove(); if (functionNode.Parent.Parent.Type == CoolGrammarLexer.Exprs && functionNode.Parent.ChildIndex != functionNode.Parent.Parent.ChildCount - 1) { CurrentILGenerator_.Emit(OpCodes.Pop); result = new ValueObjectDef(Functions_[invokeObjectDef.Type.Name][functionName].MethodBuilder.ReturnType, null); } else { result = LocalObjectDef.AllocateLocal(Functions_[invokeObjectDef.Type.Name][functionName].MethodBuilder.ReturnType); } } return(result); }