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; }