Exemple #1
0
        private void EmitExpression(ILGenerator il, Expression expression, SymbolTable symbolTable)
        {
            if (expression is BinaryExpression)
            {
                EmitExpression(il, ((BinaryExpression)expression).Left, symbolTable);
                EmitExpression(il, ((BinaryExpression)expression).Right, symbolTable);

                switch (((BinaryExpression)expression).BinaryOperatorType)
                {
                    case BinaryOperatorType.Add:
                        il.Emit(OpCodes.Add);
                        break;
                    case BinaryOperatorType.Subtract:
                        il.Emit(OpCodes.Sub);
                        break;
                    case BinaryOperatorType.Multiply:
                        il.Emit(OpCodes.Mul);
                        break;
                    case BinaryOperatorType.Divide:
                        il.Emit(OpCodes.Div);
                        break;
                    case BinaryOperatorType.Modulo:
                        il.Emit(OpCodes.Rem);
                        break;
                    case BinaryOperatorType.Equal:
                        il.Emit(OpCodes.Ceq);
                        break;
                    case BinaryOperatorType.NotEqual:
                        il.Emit(OpCodes.Ceq);
                        il.Emit(OpCodes.Ldc_I4_0);
                        il.Emit(OpCodes.Ceq);
                        break;
                    case BinaryOperatorType.GreaterThen:
                        il.Emit(OpCodes.Cgt);
                        break;
                    case BinaryOperatorType.LessThen:
                        il.Emit(OpCodes.Clt);
                        break;
                    case BinaryOperatorType.GraterOrEqualTo:
                        il.Emit(OpCodes.Clt);
                        il.Emit(OpCodes.Ldc_I4_0);
                        il.Emit(OpCodes.Ceq);
                        break;
                    case BinaryOperatorType.LessOrEqualTo:
                        il.Emit(OpCodes.Cgt);
                        il.Emit(OpCodes.Ldc_I4_0);
                        il.Emit(OpCodes.Ceq);
                        break;
                    case BinaryOperatorType.And:
                        il.Emit(OpCodes.And);
                        break;
                    case BinaryOperatorType.Or:
                        il.Emit(OpCodes.Or);
                        break;
                }
            }
            else if (expression is UnaryExpression)
            {
                UnaryExpression unaryExpression = expression as UnaryExpression;

                switch (unaryExpression.UnaryOperatorType)
                {
                    case UnaryOperatorType.Indexer:
                        EmitExpression(il, unaryExpression.Value, symbolTable);
                        EmitExpression(il, unaryExpression.Indexer, symbolTable);
                        il.Emit(OpCodes.Ldelem_I4);
                        break;
                    case UnaryOperatorType.Negative:
                        EmitExpression(il, unaryExpression.Value, symbolTable);
                        il.Emit(OpCodes.Neg);
                        break;
                    case UnaryOperatorType.Not:
                        EmitExpression(il, unaryExpression.Value, symbolTable);
                        il.Emit(OpCodes.Not);
                        break;

                }
            }
            else if (expression is Literal)
            {
                Literal literal = expression as Literal;

                switch (literal.LiteralType)
                {
                    case LiteralType.Integer:
                        il.Emit(OpCodes.Ldc_I4, Int32.Parse(literal.Value));
                        break;
                    case LiteralType.Real:
                        il.Emit(OpCodes.Ldc_R4, float.Parse(literal.Value));
                        break;
                    case LiteralType.Character:
                        il.Emit(OpCodes.Ldc_I4, char.GetNumericValue(literal.Value, 0));
                        break;
                    case LiteralType.Boolean:
                        if (literal.Value == "true")
                            il.Emit(OpCodes.Ldc_I4, 1);
                        else if (literal.Value == "false")
                            il.Emit(OpCodes.Ldc_I4, 0);
                        break;
                    case LiteralType.String:
                        il.Emit(OpCodes.Ldstr, literal.Value);
                        break;
                }
            }
            else if (expression is Name)
            {
                Name name = expression as Name;

                Symbol variable = symbolTable.Find(name.Value, SymbolType.Variable);
                if (variable == null)
                    Error("Assignment variable " + name.Value + " unknown.");

                if (variable.CodeObject is LocalBuilder)
                    il.Emit(OpCodes.Ldloc, (LocalBuilder)variable.CodeObject);
                else if (variable.CodeObject is FieldBuilder)
                    il.Emit(OpCodes.Ldsfld, (FieldBuilder)variable.CodeObject);
                else if (variable.CodeObject is ParameterBuilder)
                {
                    Parameter p = variable.SyntaxObject as Parameter;
                    il.Emit(OpCodes.Ldarg_S, ((ParameterBuilder)variable.CodeObject).Position - 1);
                    if (p.PassMethod == PassMethod.ByReference)
                        il.Emit(OpCodes.Ldind_I4);
                }

            }
            else if (expression is Call)
            {
                EmitCall(il, expression as Call, symbolTable);
            }
        }
Exemple #2
0
        private void EmitAssignment(ILGenerator il, Assignment assignment, SymbolTable symbolTable)
        {
            Symbol variable = symbolTable.Find(assignment.Name, SymbolType.Variable);
            if (variable == null)
                Error("Assignment variable " + assignment.Name + " unknown.");

            // Не массив
            if (assignment.Index == null)
            {
                if (variable.CodeObject is ParameterBuilder)
                {
                    Parameter p = variable.SyntaxObject as Parameter;
                    if (p.PassMethod == PassMethod.ByReference)
                        il.Emit(OpCodes.Ldarg_S, ((ParameterBuilder)variable.CodeObject).Position - 1);
                }

                // Получаем значение
                EmitExpression(il, assignment.Value, symbolTable);

                // Сохраняем
                if (variable.CodeObject is LocalBuilder)
                    il.Emit(OpCodes.Stloc, (LocalBuilder)variable.CodeObject);
                else if (variable.CodeObject is FieldBuilder)
                    il.Emit(OpCodes.Stsfld, (FieldBuilder)variable.CodeObject);
                else if (variable.CodeObject is ParameterBuilder)
                {
                    Parameter p = variable.SyntaxObject as Parameter;
                    if (p.PassMethod == PassMethod.ByReference)
                        il.Emit(OpCodes.Stind_I4);
                    else
                        il.Emit(OpCodes.Starg, ((ParameterBuilder)variable.CodeObject).Position - 1);
                }
            }
            else
            {
                // Загружаем массив
                if (variable.CodeObject is LocalBuilder)
                    il.Emit(OpCodes.Ldloc, (LocalBuilder)variable.CodeObject);
                else if (variable.CodeObject is FieldBuilder)
                    il.Emit(OpCodes.Ldsfld, (FieldBuilder)variable.CodeObject);
                // Индекс
                EmitExpression(il, assignment.Index, symbolTable);
                // Значение
                EmitExpression(il, assignment.Value, symbolTable);
                // Устанавливаем значение
                il.Emit(OpCodes.Stelem_I4);
            }
        }
Exemple #3
0
        private void EmitCallStatement(ILGenerator il, CallStatement call, SymbolTable symbolTable)
        {
            Symbol symbol = symbolTable.Find(call.Name, SymbolType.Function);

            if (symbol != null)
            {
                Function function = symbol.SyntaxObject as Function;

                //
                // Проверка аргументов
                //
                if (call.Arguments == null && function.Parameters == null)
                {
                    goto Hack;
                }
                else if (call.Arguments.Count != function.Parameters.Count)
                {
                    Error("Argument mismatch [" + call.Name + "]");
                }
                else if (call.Arguments.Count != function.Parameters.Count)
                {
                    Error("Argument mismatch [" + call.Name + "]");
                }
                else
                {
                    for (int x = 0; x < call.Arguments.Count; x++)
                    {
                        if (call.Arguments[x].PassMethod != function.Parameters[x].PassMethod)
                        {
                            Error("Argument error [" + call.Name + "], argument [" + x + "] is wrong.");
                        }
                    }
                }

                if (call.Arguments != null)
                {
                    foreach (Argument argument in call.Arguments)
                    {
                        if (argument.PassMethod == PassMethod.ByReference)
                        {
                            // Если параметр передан по ссылке
                            if (argument.Value is Name)
                            {
                                Symbol variable = symbolTable.Find(((Name)argument.Value).Value, SymbolType.Variable);
                                if (variable.CodeObject is LocalBuilder)
                                {
                                    if (((Variable)variable.SyntaxObject).Type.VariableType == VariableType.PrimitiveArray)
                                        Error("ref cannot be applied to arrays");
                                    il.Emit(OpCodes.Ldloca, variable.CodeObject as LocalBuilder);
                                }
                                else if (variable.CodeObject is FieldBuilder)
                                {
                                    if (((Variable)variable.SyntaxObject).Type.VariableType == VariableType.PrimitiveArray)
                                        Error("ref cannot be applied to arrays");
                                    il.Emit(OpCodes.Ldsflda, variable.CodeObject as FieldBuilder);
                                }
                                else if (variable.CodeObject is ParameterBuilder)
                                {
                                    if (((Parameter)variable.SyntaxObject).Type.VariableType == VariableType.PrimitiveArray)
                                        Error("ref cannot be applied to arrays");
                                    il.Emit(OpCodes.Ldarga, ((ParameterBuilder)variable.CodeObject).Position - 1);
                                }
                            }
                            else if (argument.Value is UnaryExpression && ((UnaryExpression)argument.Value).UnaryOperatorType == UnaryOperatorType.Indexer)
                            {
                                Symbol variable = symbolTable.Find(((Name)argument.Value).Value, SymbolType.Variable);
                                if (variable.CodeObject is LocalBuilder)
                                {
                                    il.Emit(OpCodes.Ldloc, variable.CodeObject as LocalBuilder);
                                }
                                else if (variable.CodeObject is FieldBuilder)
                                {
                                    il.Emit(OpCodes.Ldsfld, variable.CodeObject as FieldBuilder);
                                }
                                else if (variable.CodeObject is ParameterBuilder)
                                {
                                    il.Emit(OpCodes.Ldarga, ((ParameterBuilder)variable.CodeObject).Position - 1);
                                }

                                EmitExpression(il, ((UnaryExpression)argument.Value).Indexer, symbolTable);
                                il.Emit(OpCodes.Ldelema);
                            }
                            else
                            {
                                Error("ref may only be applied to variables");
                            }
                        }
                        else
                        {
                            EmitExpression(il, argument.Value, symbolTable);
                        }
                    }
                }

            Hack:
                il.Emit(OpCodes.Call, ((MethodBuilder)symbol.CodeObject));
            }
            else
            {
                if (call.Name == "Read")
                {
                    il.Emit(OpCodes.Ldstr, "Input > ");
                    MethodInfo write = System.Type.GetType("System.Console").GetMethod("Write", new System.Type[] { typeof(string) });
                    il.EmitCall(OpCodes.Call, write, null);

                    MethodInfo read = System.Type.GetType("System.Console").GetMethod("ReadLine");
                    MethodInfo parse = System.Type.GetType("System.Int32").GetMethod("Parse", new System.Type[] { typeof(string) });
                    il.EmitCall(OpCodes.Call, read, null);
                    il.EmitCall(OpCodes.Call, parse, null);

                }
                else if (call.Name == "Write")
                {
                    EmitExpression(il, call.Arguments[0].Value, symbolTable);
                    MethodInfo write = null;

                    if (call.Arguments[0].Value is Literal)
                    {
                        Literal temp = call.Arguments[0].Value as Literal;
                        System.Type type = null;
                        switch (temp.LiteralType)
                        {
                            case LiteralType.Boolean:
                                type = typeof(bool);
                                break;
                            case LiteralType.Character:
                                type = typeof(char);
                                break;
                            case LiteralType.Integer:
                                type = typeof(int);
                                break;
                            case LiteralType.Real:
                                type = typeof(double);
                                break;
                            case LiteralType.String:
                                type = typeof(string);
                                break;
                        }
                        write = System.Type.GetType("System.Console").GetMethod("WriteLine", new System.Type[] { type });
                    }
                    else
                    {
                        write = System.Type.GetType("System.Console").GetMethod("WriteLine", new System.Type[] { typeof(int) });
                    }
                    il.EmitCall(OpCodes.Call, write, null);
                }
                else
                {
                    Error("Unknown function name. [" + call.Name + "]");
                }
            }
        }
Exemple #4
0
        public Type GetExpressionType(SymbolTable symbolTable, Expression expression)
        {
            if (expression is UnaryExpression)
            {
                UnaryExpression unary = (UnaryExpression)expression;
                return FindType(GetExpressionType(symbolTable, unary.Value), unary.UnaryOperatorType);
            }
            else if (expression is BinaryExpression)
            {
                BinaryExpression binary = (BinaryExpression)expression;
                return FindType(GetExpressionType(symbolTable, binary.Left), GetExpressionType(symbolTable, binary.Right), binary.BinaryOperatorType);
            }
            else if (expression is Literal)
            {
                Literal literal = expression as Literal;

                if (literal.LiteralType == LiteralType.Boolean)
                    return new Type(PrimitiveType.Boolean);
                if (literal.LiteralType == LiteralType.Character)
                    return new Type(PrimitiveType.Character);
                if (literal.LiteralType == LiteralType.Integer)
                    return new Type(PrimitiveType.Integer);
                if (literal.LiteralType == LiteralType.Real)
                    return new Type(PrimitiveType.Real);
                if (literal.LiteralType == LiteralType.String)
                    return new Type(PrimitiveType.Void);
            }
            else if (expression is Name)
            {
                return ((Variable)symbolTable.Find(((Name)expression).Value, SymbolType.Variable).SyntaxObject).Type;
            }
            else if (expression is Call)
            {
                return ((Call)expression).Type;
            }
            return null;
        }