Example #1
0
        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]);
        }
Example #2
0
        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();
        }
Example #3
0
        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)));
        }
Example #4
0
        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();
        }
Example #5
0
        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);
        }
Example #6
0
        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));
        }
Example #7
0
        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));
        }
Example #8
0
        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));
        }
Example #9
0
        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));
        }
Example #10
0
        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));
        }
Example #11
0
        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));
            }
        }
Example #12
0
        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);
        }