Ejemplo n.º 1
0
        void EmitIterationStatement(CodeIterationStatement Iterate)
        {
            Depth++;
            Debug("Emitting iteration statement");

            // Used for break and continue later on
            var Meta = new LoopMetadata {
                Begin = Generator.DefineLabel(),
                End   = Generator.DefineLabel(),
            };

            Loops.Push(Meta);

            EmitStatement(Iterate.InitStatement, false);

            // The beginning of our loop: check the limit
            Generator.MarkLabel(Meta.Begin);

            EmitExpression(Iterate.TestExpression, false);
            Generator.Emit(OpCodes.Brfalse, Meta.End);

            // Emit the actual statements within
            EmitStatementCollection(Iterate.Statements);

            // Increase the counter by one
            EmitStatement(Iterate.IncrementStatement, false);

            // Start all over again
            Generator.Emit(OpCodes.Br, Meta.Begin);
            Generator.MarkLabel(Meta.End);

            Loops.Pop();
            Depth--;
        }
Ejemplo n.º 2
0
        Type EmitTernaryOperator(CodeTernaryOperatorExpression ternary)
        {
            Label FalseLabel = Generator.DefineLabel();
            Label EndLabel   = Generator.DefineLabel();
            Type  Top;

            EmitExpression(ternary.Condition);
            Generator.Emit(OpCodes.Brfalse, FalseLabel);
            Top = EmitExpression(ternary.TrueBranch);
            ForceTopStack(Top, typeof(object));
            Generator.Emit(OpCodes.Br, EndLabel);
            Generator.MarkLabel(FalseLabel);
            Top = EmitExpression(ternary.FalseBranch);
            ForceTopStack(Top, typeof(object));
            Generator.MarkLabel(EndLabel);

            return(typeof(object));
        }
Ejemplo n.º 3
0
        private void EmitConditionStatement(CodeConditionStatement Condition)
        {
            Label False = Generator.DefineLabel();
            Label End   = Generator.DefineLabel();

            // TODO: emitting condition statements could probably be done more efficiently
            EmitExpression(Condition.Condition);
            Generator.Emit(OpCodes.Ldc_I4_0);
            Generator.Emit(OpCodes.Beq, False);

            // Execute code for true and jump to end
            EmitStatementCollection(Condition.TrueStatements);
            Generator.Emit(OpCodes.Br, End);

            // Execute code for false and move on
            Generator.MarkLabel(False);
            EmitStatementCollection(Condition.FalseStatements);

            Generator.MarkLabel(End);
        }
Ejemplo n.º 4
0
        private LabelMetadata LookupLabel(string Name)
        {
            if (!Labels.ContainsKey(Name))
            {
                // Create the label if it does not exist yet.
                // Remember, labels can be referenced before they are declared

                var Add = new LabelMetadata();
                Add.Label    = Generator.DefineLabel();
                Add.Name     = Name;
                Add.Resolved = false;

                Labels.Add(Name, Add);

                return(Add);
            }
            else
            {
                return(Labels[Name]);
            }
        }
Ejemplo n.º 5
0
        Type EmitBinaryOperator(CodeBinaryOperatorExpression Binary, bool ForceTypes)
        {
            bool  Shortcut = Binary.Operator == CodeBinaryOperatorType.BooleanAnd || Binary.Operator == CodeBinaryOperatorType.BooleanOr;
            Label EndLabel = Generator.DefineLabel();

            if (Binary.Operator == CodeBinaryOperatorType.Assign)
            {
                return(EmitAssignment(Binary.Left, Binary.Right, ForceTypes));
            }

            Type Generated;

            Depth++;
            Debug("Emitting binary operator, left hand side");
            Generated = EmitExpression(Binary.Left);

            if (Shortcut && Generated == typeof(bool))
            {
                Debug("Short-circuiting expression for " + Binary.Operator);
                Generator.Emit(OpCodes.Dup);

                if (Binary.Operator == CodeBinaryOperatorType.BooleanAnd)
                {
                    Generator.Emit(OpCodes.Brfalse, EndLabel); // BooleanAnd jumps if left branch evals false
                }
                else if (Binary.Operator == CodeBinaryOperatorType.BooleanOr)
                {
                    Generator.Emit(OpCodes.Brtrue, EndLabel); // BooleanOr jumps if left branch evals true
                }
            }

            if (ForceTypes)
            {
                ForceTopStack(Generated, typeof(float));
            }
            Debug("Emitting binary operator, right hand side");
            Generated = EmitExpression(Binary.Right);
            if (ForceTypes)
            {
                ForceTopStack(Generated, typeof(float));
            }

            if (Shortcut)
            {
                if (Binary.Operator == CodeBinaryOperatorType.BooleanAnd)
                {
                    Generator.Emit(OpCodes.And);
                }
                else if (Binary.Operator == CodeBinaryOperatorType.BooleanOr)
                {
                    Generator.Emit(OpCodes.Or);
                }

                // Handy side-effect: one bool caused by the "dup" stays on the stack
                // Resulting in the whole expression evaluating correctly anyway.
                Generator.MarkLabel(EndLabel);

                Depth--;
                return(typeof(bool));
            }

            switch (Binary.Operator)
            {
            case CodeBinaryOperatorType.Add:
                Generator.Emit(OpCodes.Add);
                Generated = typeof(float);
                break;

            case CodeBinaryOperatorType.Subtract:
                Generator.Emit(OpCodes.Sub);
                Generated = typeof(float);
                break;

            case CodeBinaryOperatorType.Multiply:
                Generator.Emit(OpCodes.Mul);
                Generated = typeof(float);
                break;

            case CodeBinaryOperatorType.Divide:
                Generator.Emit(OpCodes.Div);
                Generated = typeof(float);
                break;

            case CodeBinaryOperatorType.LessThan:
                Generator.Emit(OpCodes.Clt);
                Generated = typeof(bool);
                break;

            case CodeBinaryOperatorType.GreaterThan:
                Generator.Emit(OpCodes.Cgt);
                Generated = typeof(bool);
                break;

            case CodeBinaryOperatorType.ValueEquality:
                Generator.Emit(OpCodes.Ceq);
                Generated = typeof(bool);
                break;

            default:
                Debug("Unhandled operator: " + Binary.Operator);
                Generated = null;
                break;
            }

            Depth--;

            return(Generated);
        }