Ejemplo n.º 1
0
        public override AstNode Visit(BinaryOperation node)
        {
            // Process the left expression.
            Expression left = node.GetLeftExpression();
            left = (Expression)left.Accept(this);
            node.SetLeftExpression(left);

            // Process the right expression.
            Expression right = node.GetRightExpression();
            right = (Expression)right.Accept(this);
            node.SetRightExpression(node);

            // Get the node type.
            IChelaType nodeType = node.GetNodeType();
            if(!nodeType.IsConstant())
                return node;

            // Perform left constant coercion.
            ConstantValue leftConstant = (ConstantValue)left.GetNodeValue();
            IChelaType leftType = left.GetNodeType();
            IChelaType leftCoercion = node.GetCoercionType();
            if(leftType != leftCoercion)
                leftConstant = leftConstant.Cast(leftCoercion);

            // Perform right constant coercion.
            ConstantValue rightConstant = (ConstantValue)right.GetNodeValue();
            IChelaType rightType = right.GetNodeType();
            IChelaType rightCoercion = node.GetSecondCoercion();
            if(rightType != rightCoercion)
                rightConstant = rightConstant.Cast(rightCoercion);

            // Perform the constant operation.
            ConstantValue res = null;
            switch(node.GetOperation())
            {
            case BinaryOperation.OpAdd:
                res = leftConstant + rightConstant;
                break;
            case BinaryOperation.OpSub:
                res = leftConstant - rightConstant;
                break;
            case BinaryOperation.OpMul:
                res = leftConstant * rightConstant;
                break;
            case BinaryOperation.OpDiv:
                res = leftConstant / rightConstant;
                break;
            case BinaryOperation.OpMod:
                res = leftConstant % rightConstant;
                break;
            case BinaryOperation.OpEQ:
                res = ConstantValue.Equals(leftConstant, rightConstant);
                break;
            case BinaryOperation.OpNEQ:
                res = ConstantValue.NotEquals(leftConstant, rightConstant);
                break;
            case BinaryOperation.OpLT:
                res = leftConstant < rightConstant;
                break;
            case BinaryOperation.OpLEQ:
                res = leftConstant <= rightConstant;
                break;
            case BinaryOperation.OpGT:
                res = leftConstant > rightConstant;
                break;
            case BinaryOperation.OpGEQ:
                res = leftConstant >= rightConstant;
                break;
            case BinaryOperation.OpBitAnd:
                res = leftConstant & rightConstant;
                break;
            case BinaryOperation.OpBitOr:
                res = leftConstant | rightConstant;
                break;
            case BinaryOperation.OpBitXor:
                res = leftConstant ^ rightConstant;
                break;
            case BinaryOperation.OpBitLeft:
                res = ConstantValue.BitLeft(leftConstant, rightConstant);
                break;
            case BinaryOperation.OpBitRight:
                res = ConstantValue.BitRight(leftConstant, rightConstant);
                break;
            case BinaryOperation.OpLAnd:
                res = new ConstantValue(leftConstant.GetBoolValue() && rightConstant.GetBoolValue());
                break;
            case BinaryOperation.OpLOr:
                res = new ConstantValue(leftConstant.GetBoolValue() || rightConstant.GetBoolValue());
                break;
            default:
                throw new System.NotImplementedException();
            }

            // Return the result node.
            return res.ToAstNode(node.GetPosition());
        }
Ejemplo n.º 2
0
        public override AstNode Visit(BinaryOperation node)
        {
            // Begin the node.
            builder.BeginNode(node);

            // Get the expressions.
            Expression left = node.GetLeftExpression();
            Expression right = node.GetRightExpression();

            // Get the types.
            IChelaType leftType = left.GetNodeType();
            IChelaType rightType = right.GetNodeType();
            IChelaType coercionType = node.GetCoercionType();
            IChelaType secondCoercion = node.GetSecondCoercion();
            IChelaType operationType = node.GetOperationType();
            IChelaType destType = node.GetNodeType();

            // Special pipeline for operator overloading.
            Function overload = node.GetOverload();
            if(overload != null)
            {
                FunctionType overloadType = overload.GetFunctionType();
                coercionType = overloadType.GetArgument(0);
                secondCoercion = overloadType.GetArgument(1);

                // Send first the left operand.
                left.Accept(this);
                if(leftType != coercionType)
                    Cast(node, left.GetNodeValue(), leftType, coercionType);

                // Now send the right operand.
                right.Accept(this);
                if(rightType != secondCoercion)
                    Cast(node, right.GetNodeValue(), rightType, secondCoercion);

                // Perform the call.
                builder.CreateCall(overload, 2);

                // Return the node.
                return builder.EndNode();
            }

            // Send the left operand.
            left.Accept(this);
            if(leftType != coercionType)
                Cast(node, left.GetNodeValue(), leftType, coercionType);

            // Short circuit operations has special evaluation orders.
            if(node.GetOperation() == BinaryOperation.OpLAnd ||
               node.GetOperation() == BinaryOperation.OpLOr)
            {
                BasicBlock continueBlock = CreateBasicBlock();
                continueBlock.SetName("shc");

                BasicBlock stopBlock = CreateBasicBlock();
                stopBlock.SetName("shs");

                BasicBlock mergeBlock = CreateBasicBlock();
                mergeBlock.SetName("shm");

                // Perform left branch.
                if(node.GetOperation() == BinaryOperation.OpLAnd)
                    builder.CreateBr(continueBlock, stopBlock);
                else
                    builder.CreateBr(stopBlock, continueBlock);

                // Build stop.
                builder.SetBlock(stopBlock);
                builder.CreateLoadBool(node.GetOperation() == BinaryOperation.OpLOr);
                builder.CreateJmp(mergeBlock);

                // Build continue block.
                builder.SetBlock(continueBlock);

                // Send the right operand verbatim.
                right.Accept(this);
                if(rightType != secondCoercion)
                    Cast(node, right.GetNodeValue(), rightType, secondCoercion);
                builder.CreateJmp(mergeBlock);

                // Continue with the control flow.
                builder.SetBlock(mergeBlock);
                return builder.EndNode();
            }

            // Send the right operand.
            right.Accept(this);
            if(rightType != secondCoercion)
                Cast(node, right.GetNodeValue(), rightType, secondCoercion);

            switch(node.GetOperation())
            {
            case BinaryOperation.OpAdd:
                builder.CreateAdd();
                break;
            case BinaryOperation.OpSub:
                builder.CreateSub();
                break;
            case BinaryOperation.OpMul:
                if(node.IsMatrixMul())
                    builder.CreateMatMul();
                else
                    builder.CreateMul();
                break;
            case BinaryOperation.OpDiv:
                builder.CreateDiv();
                break;
            case BinaryOperation.OpMod:
                builder.CreateMod();
                break;
            case BinaryOperation.OpBitAnd:
                builder.CreateAnd();
                break;
            case BinaryOperation.OpBitOr:
                builder.CreateOr();
                break;
            case BinaryOperation.OpBitXor:
                builder.CreateXor();
                break;
            case BinaryOperation.OpBitLeft:
                builder.CreateShLeft();
                break;
            case BinaryOperation.OpBitRight:
                builder.CreateShRight();
                break;
            case BinaryOperation.OpLT:
                builder.CreateCmpLT();
                break;
            case BinaryOperation.OpGT:
                builder.CreateCmpGT();
                break;
            case BinaryOperation.OpEQ:
                builder.CreateCmpEQ();
                break;
            case BinaryOperation.OpNEQ:
                builder.CreateCmpNE();
                break;
            case BinaryOperation.OpLEQ:
                builder.CreateCmpLE();
                break;
            case BinaryOperation.OpGEQ:
                builder.CreateCmpGE();
                break;
            case BinaryOperation.OpLAnd:
            case BinaryOperation.OpLOr:
                // Shouldn't reach here.
                break;
            }

            // Cast the result.
            if(operationType != destType)
                Cast(node, null, operationType, destType);

            return builder.EndNode();
        }