Ejemplo n.º 1
0
        private void GenerateStatement(Expression pStatement, Type pExpectedType)
        {
            if (pStatement is DeclareVar)
            {
                DeclareVar curStmnt = (DeclareVar)pStatement;

                DeclareSymbolInTable(curStmnt.Identifier, curStmnt.GetSystemType());
            }
            else if (pStatement is ReadInt)
            {
                ReadInt curStmnt = (ReadInt)pStatement;

                _ilGenerator.Emit(Emit.OpCodes.Call, GetMSILMethod("ReadLine", typeof(String)));
                _ilGenerator.Emit(Emit.OpCodes.Call, GetMSILMethod("Parse", typeof(Int32)));

                ValidateSymbolType(curStmnt._Identifier, typeof(Int32));
                _ilGenerator.Emit(Emit.OpCodes.Stloc, GetValueFromSymbolTable(curStmnt._Identifier, -1));
            }
            else if (pStatement is StringLiteral)
            {
                StringLiteral curStmnt = (StringLiteral)pStatement;

                _ilGenerator.Emit(Emit.OpCodes.Ldstr, curStmnt._Value);

                if (pExpectedType != typeof(String))
                {
                    throw new Exception("can't coerce a " + typeof(Int32).Name + " to a " + pExpectedType.Name);
                }
            }
            else if (pStatement is IntLiteral)
            {
                IntLiteral curStmnt = (IntLiteral)pStatement;

                //Sample ASM:   IL_0001:  ldc.i4.3 (pushes 3 onto stack)
                _ilGenerator.Emit(Emit.OpCodes.Ldc_I4, curStmnt._Value);

                //Casting Possibility
                if (pExpectedType != typeof(Int32))
                {
                    if (pExpectedType == typeof(String))
                    {
                        _ilGenerator.Emit(Emit.OpCodes.Box, typeof(Int32));
                        _ilGenerator.Emit(Emit.OpCodes.Callvirt, GetMSILMethod("toString", null));
                    }
                    else
                    {
                        throw new Exception("can't coerce a " + typeof(Int32).Name + " to a " + pExpectedType.Name);
                    }
                }
            }
            else if (pStatement is Variable)
            {
                Variable curStmnt = (Variable)pStatement;

                _ilGenerator.Emit(Emit.OpCodes.Ldloc, GetValueFromSymbolTable(curStmnt._Identifier, -1));
                if (pExpectedType != TypeOfExpression(pStatement))
                {
                    if (TypeOfExpression(pStatement) == typeof(Int32) && pExpectedType == typeof(String))
                    {
                        _ilGenerator.Emit(Emit.OpCodes.Box, typeof(Int32));
                        _ilGenerator.Emit(Emit.OpCodes.Callvirt, GetMSILMethod("toString", null));
                    }
                    else
                    {
                        throw new Exception("can't coerce a " + TypeOfExpression(pStatement).Name +
                                            " to a " + pExpectedType.Name);
                    }
                }
            }
            else if (pStatement is LinkedList)
            {
                LinkedList seq = (LinkedList)pStatement;

                GenerateStatement(seq.First, null);
                GenerateStatement(seq.Second, null);
            }
            else if (pStatement is Assign)
            {
                //retrieve info about variable, including address, type
                //LHS addrs <--addr;
                //LHS type <-- type;
                //getToken();
                //match(TK_ASSIGN);

                //a = b+c;
                //push b
                //push c
                //add
                //pop a


                Assign curStmnt = (Assign)pStatement;

                GenerateStatement(curStmnt._Expression, TypeOfExpression(curStmnt._Expression));

                //ValidateSymbolType(curStmnt._Identifier, TypeOfExpression(curStmnt._Expression));
                //Pops the current value from the top of the evaluation stack and stores it in a the local variable list at index 0.
                _ilGenerator.Emit(Emit.OpCodes.Stloc, GetValueFromSymbolTable(curStmnt._Identifier, -1));
            }
            else if (pStatement is Print)
            {
                Print curStmnt = (Print)pStatement;

                GenerateStatement(curStmnt._Expr, TypeOfExpression(curStmnt._Expr));
                _ilGenerator.Emit(Emit.OpCodes.Call, GetMSILMethod("Print", TypeOfExpression(curStmnt._Expr)));
            }
            else if (pStatement is ForLoop)
            {
                ForLoop curStmnt = (ForLoop)pStatement;

                Assign assign = new Assign(curStmnt._Identifier, curStmnt._From, -1);
                GenerateStatement(assign, null);

                // jump to the test
                Emit.Label test = _ilGenerator.DefineLabel();
                Emit.Label body = _ilGenerator.DefineLabel();

                _ilGenerator.Emit(Emit.OpCodes.Br, test);
                _ilGenerator.MarkLabel(body);

                GenerateStatement(curStmnt._Body, null);

                // to (increment the value of x)
                _ilGenerator.Emit(Emit.OpCodes.Ldloc, GetValueFromSymbolTable(curStmnt._Identifier, -1));
                _ilGenerator.Emit(Emit.OpCodes.Ldc_I4, 1);
                _ilGenerator.Emit(Emit.OpCodes.Add);

                ValidateSymbolType(curStmnt._Identifier, typeof(Int32));
                _ilGenerator.Emit(Emit.OpCodes.Stloc, GetValueFromSymbolTable(curStmnt._Identifier, -1));

                _ilGenerator.MarkLabel(test);
                _ilGenerator.Emit(Emit.OpCodes.Ldloc, GetValueFromSymbolTable(curStmnt._Identifier, -1));
                GenerateStatement(curStmnt._To, typeof(Int32));

                _ilGenerator.Emit(Emit.OpCodes.Blt, body);
            }
            else
            {
                throw new Exception("don't know how to generate a " + pStatement.GetType().Name);
            }
        }