Exemple #1
0
        public override AstNode Visit(BinaryAssignOperation node)
        {
            // Begin the node.
            builder.BeginNode(node);

            // Get the expressions.
            Expression left = node.GetVariable();
            Expression right = node.GetValue();

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

            // Get the variable.
            Variable variable = (Variable)left.GetNodeValue();
            left.Accept(this);

            // Duplicate the variable reference.
            DuplicateReference(node, variable);

            // If the variable is an event,
            if(variable.IsEvent())
            {
                // Use event functions.
                EventVariable eventVar = (EventVariable)variable;

                // Send the argument.
                right.Accept(this);
                Cast(node, right.GetNodeValue(), rightType, secondCoercion);

                // Select the correct function.
                Function modifier = null;
                if(node.GetOperation() == BinaryOperation.OpAdd)
                    modifier = eventVar.AddModifier;
                else
                    modifier = eventVar.RemoveModifier;

                // Invoke the modifier.
                if(!modifier.IsStatic())
                {
                    Method method = (Method)modifier;
                    if(method.IsVirtual())
                        builder.CreateCallVirtual(method, 2);
                    else
                        builder.CreateCall(method, 2);
                }
                else
                {
                    builder.CreateCall(modifier, 1);
                }

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

            // Duplicate again.
            DuplicateReference(node, variable);

            // Read the variable.
            Cast(node, variable, leftType, coercionType);

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

            // Get the overloaded operator.
            Function op = node.GetOverload();

            // Perform the operation
            if(op != null)
            {
                // Use the overloaded operation.
                builder.CreateCall(op, 2);

                // Coerce the result.
                IChelaType opResult = op.GetFunctionType().GetReturnType();
                if(opResult != coercionType)
                    builder.CreateCast(coercionType);
            }
            else
            {
                switch(node.GetOperation())
                {
                case BinaryOperation.OpAdd:
                    builder.CreateAdd();
                    break;
                case BinaryOperation.OpSub:
                    builder.CreateSub();
                    break;
                case BinaryOperation.OpMul:
                    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:
                case BinaryOperation.OpGT:
                case BinaryOperation.OpEQ:
                case BinaryOperation.OpNEQ:
                case BinaryOperation.OpLEQ:
                case BinaryOperation.OpGEQ:
                case BinaryOperation.OpLAnd:
                case BinaryOperation.OpLOr:
                    // Shouldn't reach here.
                    break;
                }
            }

            // Now, perform the assignment.
            PerformAssignment(node, variable);

            // Set the node value.
            node.SetNodeValue(variable);

            return builder.EndNode();
        }
Exemple #2
0
        public override AstNode Visit(BinaryAssignOperation node)
        {
            // Get the expressions.
            Expression left = node.GetVariable();
            Expression right = node.GetValue();

            // Visit the expressions.
            left.Accept(this);
            right.Accept(this);

            // Check the types.
            IChelaType leftType = left.GetNodeType();
            IChelaType rightType = right.GetNodeType();

            // The variable must be a reference.
            if(!leftType.IsReference())
                Error(node, "trying to set something that isn't a reference.");
            leftType = DeReferenceType(leftType);

            // Don't modify constants.
            if(leftType.IsConstant())
                Error(node, "cannot modify constants.");

            // Check coercion.
            // TODO: Add operator overloading.

            // Set the variable type.
            node.SetNodeType(left.GetNodeType());

            // Check for pointer arithmetic.
            if(leftType.IsPointer())
            {
                // Only addition and subtraction are accepted.
                int op = node.GetOperation();
                if(op != BinaryOperation.OpAdd && op != BinaryOperation.OpSub)
                    Error(node, "only addition and subtraction of pointers is supported.");

                // Make sure the right type is an integer or another pointer.
                if(rightType.IsReference())
                    rightType = DeReferenceType(rightType);

                // De-const the right operand.
                if(rightType.IsConstant())
                    rightType = DeConstType(rightType);

                // Don't allow right operand pointer.
                if(!rightType.IsInteger())
                    Error(node, "right operand must be integer.");

                // Set the coercion type and pointer arithmetic flags.
                node.SetCoercionType(leftType);
                node.SetSecondCoercion(rightType);
                node.SetPointerArithmetic(true);

                return node;
            }
            else if(leftType.IsReference())
            {
                // Handle the event subscription.
                leftType = DeReferenceType(leftType);

                if(!leftType.IsClass())
                    Error(node, "unsupported operation.");

                // Make sure its actually a delegate.
                Class delegateClass = currentModule.GetDelegateClass();
                Class delegateType = (Class)leftType;
                if(!delegateType.IsDerivedFrom(delegateClass))
                    Error(node, "cannot subscribe no delegates.");

                // Check the operation.
                int op = node.GetOperation();
                if(op != BinaryOperation.OpAdd && op != BinaryOperation.OpSub)
                    Error(node, "invalid event subscription/delegate operation.");

                // Perform coercion.
                leftType = ReferenceType.Create(delegateType);
                if(Coerce(node, leftType, rightType, right.GetNodeValue()) != leftType)
                    Error(node, "unexistent implicit cast for assignment.");

                // Get the overload operator.
                Variable variable = (Variable)left.GetNodeValue();
                if(!variable.IsEvent())
                {
                    string opName = op == BinaryOperation.OpAdd ? "Combine" : "Remove";

                    // Find the first no static function with 2 arguments.
                    FunctionGroup opGroup = (FunctionGroup)delegateClass.FindMember(opName);
                    Function overload = null;
                    foreach(FunctionGroupName gname in opGroup.GetFunctions())
                    {
                        // Ignore no static functions.
                        if(!gname.IsStatic())
                            continue;

                        // Select the first function with 2 arguments.
                        if(gname.GetFunctionType().GetArgumentCount() == 2)
                        {
                            overload = gname.GetFunction();
                            break;
                        }
                    }

                    // Make sure the function was found.
                    if(overload == null)
                        Error(node, "Runtime delegate doesn't have function " + opName);

                    // Use the overload.
                    node.SetOverload(overload);
                }

                node.SetCoercionType(leftType);
                node.SetSecondCoercion(leftType);
                return node;
            }

            if(Coerce(node, leftType, rightType, right.GetNodeValue()) != leftType)
                Error(node, "unexistent implicit cast for assignment.");
            node.SetCoercionType(leftType);
            node.SetSecondCoercion(leftType);

            // Perform validation
            switch(node.GetOperation())
            {
            case BinaryOperation.OpAdd:
            case BinaryOperation.OpSub:
            case BinaryOperation.OpMul:
            case BinaryOperation.OpDiv:
            case BinaryOperation.OpMod:
                if(leftType == ChelaType.GetBoolType())
                    Error(node, "Arithmetic operations aren't available with boolean values.");
                break;
            case BinaryOperation.OpBitAnd:
            case BinaryOperation.OpBitOr:
            case BinaryOperation.OpBitXor:
            case BinaryOperation.OpBitLeft:
            case BinaryOperation.OpBitRight:
                if(leftType.IsFloatingPoint() || leftType == ChelaType.GetBoolType())
                    Error(node, "Bitwise operations aren't available with floating point and boolean values.");
                break;
            case BinaryOperation.OpLT:
            case BinaryOperation.OpGT:
            case BinaryOperation.OpEQ:
            case BinaryOperation.OpNEQ:
            case BinaryOperation.OpLEQ:
            case BinaryOperation.OpGEQ:
            case BinaryOperation.OpLAnd:
            case BinaryOperation.OpLOr:
                Error(node, "Operation without assignment version.");
                break;
            default:
                Error(node, "Compiler bug, unknown binary operation.");
                break;
            }

            // Check for the read-only constraint.
            Variable variableSlot = left.GetNodeValue() as Variable;
            if(variableSlot != null && variableSlot.IsReadOnly())
                CheckReadOnlyConstraint(node, variableSlot);

            return node;
        }