Beispiel #1
0
        public void Emit(CompilationContext context)
        {
            context.EmitComment(";Boolean expression");

            ((ICodeEmitter)Tokens[0]).Emit(context);

            var expressionType = ((IHasType)Tokens[0]).GetExpressionType(context);

            if (Tokens.Count > 1)
            {
                TypeChecking.CheckExpressionTypeIsBoolean(expressionType);
            }

            for (int i = 1; i < Tokens.Count; i += 2)
            {
                string op = ((DefaultLanguageTerminalToken)Tokens[i]).Value;

                ((ICodeEmitter)Tokens[i + 1]).Emit(context);

                expressionType = ((IHasType)Tokens[i + 1]).GetExpressionType(context);

                TypeChecking.CheckExpressionTypeIsBoolean(expressionType);

                context.EmitInstruction(new IRPop()
                {
                    To = "ebx"
                });
                context.EmitInstruction(new IRPop()
                {
                    To = "eax"
                });

                var trueLabel = new LabelAddressValue(context.CreateNewLabel());

                switch (op)
                {
                case "&&":
                    context.EmitInstruction(new IRAnd()
                    {
                        Left = "eax", Right = "ebx", To = "ecx"
                    });
                    context.EmitInstruction(new IRCompareImmediate()
                    {
                        Left = "ecx", Right = new ImmediateValue(0)
                    });
                    context.EmitInstruction(new IRJumpNE()
                    {
                        Address = trueLabel
                    });
                    break;

                case "||":
                    context.EmitInstruction(new IROr()
                    {
                        Left = "eax", Right = "ebx", To = "ecx"
                    });
                    context.EmitInstruction(new IRCompareImmediate()
                    {
                        Left = "ecx", Right = new ImmediateValue(0)
                    });
                    context.EmitInstruction(new IRJumpNE()
                    {
                        Address = trueLabel
                    });
                    break;
                }

                var skipTrueLabel = new LabelAddressValue(context.CreateNewLabel());

                context.EmitInstruction(new IRPushImmediate()
                {
                    Value = new ImmediateValue(0)
                });
                context.EmitInstruction(new IRJumpImmediate()
                {
                    Address = skipTrueLabel
                });
                context.EmitLabel(trueLabel.Value);
                context.EmitInstruction(new IRPushImmediate()
                {
                    Value = new ImmediateValue(1)
                });
                context.EmitLabel(skipTrueLabel.Value);
            }
        }