예제 #1
0
        public override int GenerateCode(int loc, IVirtualMachine vm, CheckerInformation info)
        {
            loc = Term.GenerateCode(loc, vm, info);
            //Only execute RepTerm if no conditional BoolOpr or if the left hand side is not enough to determine result
            if (Operator != Operators.COR && Operator != Operators.CAND)
            {
                loc = RepTerm.GenerateCode(loc, vm, info);
            }

            var type = GetExpressionType(info);

            if (type == Type.BOOL)
            {
                switch (Operator)
                {
                case Operators.AND:
                    //Can only work with int operations:
                    //If both terms are true (=1), they result in 2 (1+1=2)
                    vm.IntAdd(loc++);
                    //Test if result == 2
                    vm.IntLoad(loc++, 2);
                    vm.IntEQ(loc++);
                    break;

                case Operators.OR:
                    vm.IntAdd(loc++);
                    vm.IntLoad(loc++, 1);
                    vm.IntGE(loc++);     //>=1 => only one term has to be true
                    break;

                case Operators.CAND:
                    //If true is on the top of the stack, the second condition has to be evaluated
                    //1. Jump if left hand side was false
                    int conditionalJump = loc++;
                    //2. a. Evaluate right hand side if left hand side was true
                    loc = RepTerm.GenerateCode(loc, vm, info);
                    vm.CondJump(conditionalJump, loc + 1); //Step 1: Only now the jump destination is known!
                    vm.UncondJump(loc, loc + 2);
                    ++loc;                                 //Leap over the load(0) instruction
                    //2. b. Evaluate to false
                    vm.IntLoad(loc++, 0);
                    break;

                case Operators.COR:
                    //If false is on the top of the stack, the second condition has to be evaluated
                    //1. Invert top of stack:
                    vm.IntLoad(loc++, 1);
                    vm.IntNE(loc++);
                    //2. Jump if left hand side was true
                    int conditionalJump2 = loc++;
                    //3. a. Evaluate right hand side if left hand side was false
                    loc = RepTerm.GenerateCode(loc, vm, info);
                    vm.CondJump(conditionalJump2, loc + 1);
                    vm.UncondJump(loc, loc + 2);
                    ++loc;
                    //3. b. Evaluate to true (without evaluating right hand side)
                    vm.IntLoad(loc++, 1);
                    break;

                default:
                    throw new IVirtualMachine.InternalError(
                              "There's an invalid operator in ASTBoolOpr. Operator: " + Operator.ToString());
                }
            }
            else
            {
                throw new IVirtualMachine.InternalError(
                          "There's an invalid operand in ASTBoolOpr. Oprand: " + type.ToString());
            }
            return(loc);
        }
예제 #2
0
        public override int GenerateCode(int loc, IVirtualMachine vm, CheckerInformation info)
        {
            loc = Term.GenerateCode(loc, vm, info);
            loc = RepTerm.GenerateCode(loc, vm, info);

            var termType    = ((ASTExpression)Term).GetExpressionType(info);
            var repTermType = ((ASTExpression)RepTerm).GetExpressionType(info);

            if ((termType == Type.INT32 && repTermType == Type.INT32) || (termType == Type.BOOL && repTermType == Type.BOOL))
            {
                switch (Operator)
                {
                case Operators.EQ:
                    vm.IntEQ(loc++);
                    break;

                case Operators.NE:
                    vm.IntNE(loc++);
                    break;

                case Operators.LT:
                    vm.IntLT(loc++);
                    break;

                case Operators.LE:
                    vm.IntLE(loc++);
                    break;

                case Operators.GT:
                    vm.IntGT(loc++);
                    break;

                case Operators.GE:
                    vm.IntGE(loc++);
                    break;

                default:
                    throw new IVirtualMachine.InternalError("There's an invalid operator in ASTRelOpr. Operator: " + Operator.ToString());
                }
            }
            else if ((termType == Type.INT32 && repTermType == Type.DECIMAL) ||
                     (termType == Type.DECIMAL && repTermType == Type.INT32) ||
                     (termType == Type.DECIMAL && repTermType == Type.DECIMAL))
            {
                switch (Operator)
                {
                case Operators.EQ:
                    vm.DecimalEQ(loc++);
                    break;

                case Operators.NE:
                    vm.DecimalNE(loc++);
                    break;

                case Operators.LT:
                    vm.DecimalLT(loc++);
                    break;

                case Operators.LE:
                    vm.DecimalLE(loc++);
                    break;

                case Operators.GT:
                    vm.DecimalGT(loc++);
                    break;

                case Operators.GE:
                    vm.DecimalGE(loc++);
                    break;

                default:
                    throw new IVirtualMachine.InternalError("There's an invalid operator in ASTRelOpr. Operator: " + Operator.ToString());
                }
            }
            else
            {
                throw new IVirtualMachine.InternalError("There's an invalid operand in ASTRelOpr. Operand: " + termType.ToString() + ", " + repTermType.ToString());
            }


            return(loc);
        }