public override object Exec(StringType firstOperand, object arg)
        {
            // * String WriteType and bounded type variables
            if (TypeExpression.As <StringType>(this.secondOperand) != null)
            {
                return(0);
            }
            // * WriteType variable
            TypeVariable typeVariable = this.secondOperand as TypeVariable;

            if (typeVariable != null && typeVariable.Substitution == null)
            {
                // * A free variable is complete promotion
                return(0);
            }
            // * Union type
            UnionType unionType = TypeExpression.As <UnionType>(this.secondOperand);

            if (unionType != null)
            {
                return(unionType.SuperType(firstOperand));
            }
            // * Field type and bounded type variable
            FieldType fieldType = TypeExpression.As <FieldType>(this.secondOperand);

            if (fieldType != null)
            {
                return(firstOperand.AcceptOperation(new PromotionLevelOperation(fieldType.FieldTypeExpression), arg));
            }
            // * Use the BCL object oriented approach
            return(firstOperand.AsClassType().AcceptOperation(this, arg));
        }
 /// <summary>
 /// Performs an assigment operation between a Class type and the typeExpression stored in this.rightOperand.
 /// The type to asign to the array must be promotable to an ClassType, and the only allowable operator is AssignmentOperator
 /// </summary>
 /// <param name="leftOperand">The left operand of the assignmet operator.</param>
 /// <returns>A type expression one all checks and promotions are tried to make the assignment right.</returns>
 public override object Exec(ClassType leftOperand, object arg)   // the unique allowable operator
 {
     if (this.op == AssignmentOperator.Assign)
     {
         if (this.rightOperand.AcceptOperation(PromotionOperation.Create(leftOperand, this.op, this.methodAnalyzed, this.location), arg) == null)
         {
             return(null);
         }
         if (!leftOperand.HasTypeVariables())
         {
             return(leftOperand);
         }
         // * If the left expression of the assignment has type variables,
         //   we must return the concrete type (not the abstract one)
         // * Then whe unify the concrete types
         FieldType fieldType = TypeExpression.As <FieldType>(this.rightOperand);
         if (fieldType != null)
         {
             this.rightOperand = fieldType.FieldTypeExpression;
         }
         if (leftOperand.Unify(this.rightOperand, this.unification, new List <Pair <TypeExpression, TypeExpression> >()))
         {
             leftOperand.ValidTypeExpression = false;
             return(leftOperand);
         }
     }
     ErrorManager.Instance.NotifyError(new OperationNotAllowedError(this.op.ToString(), leftOperand.FullName, rightOperand.FullName, this.location));
     return(null);
 }
예제 #3
0
        private static TypeExpression getFieldType(TypeExpression type, string fieldName)
        {
            ClassType classType = TypeExpression.As <ClassType>(type);

            if (classType != null)
            {
                if (!classType.Fields.ContainsKey(fieldName))
                {
                    return(null);
                }
                TypeExpression field     = classType.Fields[fieldName].Type;
                FieldType      fieldType = TypeExpression.As <FieldType>(field);
                if (fieldType == null)
                {
                    return(field);
                }
                return(fieldType.FieldTypeExpression);
            }
            UnionType unionType = TypeExpression.As <UnionType>(type);

            if (unionType != null)
            {
                UnionType newUnionType = new UnionType();
                foreach (TypeExpression typeInUnion in unionType.TypeSet)
                {
                    TypeExpression newType = SSAHelper.getFieldType(typeInUnion, fieldName);
                    newUnionType.AddType(newType);
                }
                return(newUnionType);
            }
            return(null);
        }
 public override object Exec(MethodType actualMethod, object arg)
 {
     // * 1.1 The implicit object has a known type and can a lso have candidate methods maybe a candidate objec
     if (this.firstTime)
     {
         this.firstTime = false;
         this.areThereNonValidObjects = TypeExpression.As <UnionType>(((FieldAccessExpression)this.node.Identifier).Expression.ExpressionType) != null;
         if (areThereNonValidObjects)
         {
             this.nonValidObjectsLabel = codeGenerator.NewLabel;
             this.node.Identifier.Accept(this.visitor, this.objArgs);
             this.codeGenerator.isinst(this.indent, actualMethod.MemberInfo.Class);
             this.codeGenerator.brfalse(this.indent, nonValidObjectsLabel);
         }
         this.InvokeSingleMethod(actualMethod, arg);
         if (areThereNonValidObjects)
         {
             string end = codeGenerator.NewLabel;
             this.codeGenerator.br(this.indent, end);
             this.codeGenerator.WriteLabel(this.indent, this.nonValidObjectsLabel);
             this.node.Identifier.Accept(this.visitor, this.objArgs);
             this.codeGenerator.WriteThrowMissingMethodException(this.indent, ((AST.FieldAccessExpression)(this.node.Identifier)).FieldName.ILName);
             this.codeGenerator.WriteLabel(this.indent, end);
         }
         return(null);
     }
     this.InvokeUnionMethod(actualMethod, arg);
     return(null);
 }
예제 #5
0
        //// <summary>
        /// Returns an int value encapsulated in an object item that indicates a promotion level.
        /// </summary>
        /// <param name="firstOperand">An array to promote.</param>
        /// <returns>Returns a promotion value.</returns>
        public override object Exec(ArrayType firstOperand, object arg)
        {
            // * Array and bounded type variable
            ArrayType array = TypeExpression.As <ArrayType>(this.secondOperand);

            if (array != null)
            {
                return(firstOperand.ArrayTypeExpression.Equals(array.ArrayTypeExpression) ? 0 : -1);
            }
            // * A free variable is a complete promotion
            TypeVariable typeVariable = this.secondOperand as TypeVariable;

            if (typeVariable != null && typeVariable.Substitution == null)
            {
                return(0);
            }
            // * Union type and bounded type variable
            UnionType unionType = TypeExpression.As <UnionType>(this.secondOperand);

            if (unionType != null)
            {
                return(unionType.SuperType(firstOperand));
            }
            // * Field type and bounded type variable
            FieldType fieldType = TypeExpression.As <FieldType>(this.secondOperand);

            if (fieldType != null)
            {
                return(firstOperand.AcceptOperation(new PromotionLevelOperation(fieldType.FieldTypeExpression), arg));
            }
            // * Use the BCL object oriented approach
            return(firstOperand.AsClassType().AcceptOperation(this, arg));
        }
예제 #6
0
        public override Object Visit(InvocationExpression node, Object obj)
        {
            InheritedAttributes ia        = (InheritedAttributes)obj;
            Object     objArgs            = obj;
            MethodType actualMethodCalled = TypeExpression.As <MethodType>(node.ActualMethodCalled);

            if (actualMethodCalled != null)
            {
                objArgs = new InheritedAttributes(ia.CurrentMethod, ia.Assignment, ia.Reference, ia.ArrayAccessFound, actualMethodCalled, ia.IsParentNodeAnInvocation);
            }

            FieldAccessExpression fieldAccessExpression = node.Identifier as FieldAccessExpression;

            if (fieldAccessExpression != null)
            {
                // * A message has been sent with the syntax "obj.method(...)"
                Object o = node.Identifier.Accept(this, obj);
                node.Arguments.Accept(this, objArgs);
                if ((o is SynthesizedAttributes) && (((SynthesizedAttributes)o).IdentifierExpressionMode == IdentifierMode.Instance))
                {
                    TypeExpression klass = null; // * When the implicit object is a fresh var reference
                    if (actualMethodCalled != null)
                    {
                        klass = actualMethodCalled.MemberInfo.Class;
                    }
                    this.codeGenerator.CallVirt(this.indent, actualMethodCalled, klass, fieldAccessExpression.FieldName.Identifier, node.Arguments);
                }
                else
                {
                    this.codeGenerator.Call(this.indent, actualMethodCalled, actualMethodCalled.MemberInfo.Class, actualMethodCalled.MemberInfo.MemberIdentifier);
                }
            }
            else
            {
                // * A message is sent with without the implicit object "method(...)"
                if (node.Identifier is SingleIdentifierExpression)
                {
                    if ((((MethodType)node.Identifier.ExpressionType).MemberInfo.ModifierMask & Modifier.Static) == 0)
                    {
                        this.codeGenerator.ldarg(this.indent, 0);
                    }
                    node.Arguments.Accept(this, objArgs);
                    this.codeGenerator.Call(this.indent, actualMethodCalled, actualMethodCalled.MemberInfo.Class, ((SingleIdentifierExpression)node.Identifier).Identifier);
                }
                else
                {
                    if (node.Identifier is BaseExpression)
                    {
                        node.Arguments.Accept(this, objArgs);
                        this.codeGenerator.constructorCall(this.indent, actualMethodCalled, ((BaseExpression)node.Identifier).ExpressionType, ".ctor");
                    }
                }
            }
            //TODO: OJO AQUÏ: MIRAR DONDE SE CORRESPONDE CON CODEGENERATOR, PORQUE GENERAR UNA LÍNEA DESDE EL VISITOR
            // ES un poco chapuzaCHAPUZA
            this.codeGenerator.WriteLine();
            return(null);
        }
        public override object Exec(BaseExpression b, object arg)
        {
            // * 2.2 A constructor is called
            MethodType actualMethodCalled = TypeExpression.As <MethodType>(node.ActualMethodCalled);

            this.node.Arguments.Accept(this.visitor, this.objArgs);
            this.codeGenerator.constructorCall(this.indent, actualMethodCalled, b.ExpressionType, ".ctor");

            return(null);
        }
        public override object Exec(SingleIdentifierExpression s, object arg)
        {
            // * 2. A message is sent with without the implicit object "method(...)"
            //// * 2.1 A method is called (not a constructor)
            MethodType actualMethodCalled = TypeExpression.As <MethodType>(node.ActualMethodCalled);

            if ((((MethodType)node.ActualMethodCalled).MemberInfo.ModifierMask & Modifier.Static) == 0)
            {
                this.codeGenerator.ldarg(this.indent, 0);
            }
            this.node.Arguments.Accept(this.visitor, this.objArgs);
            this.codeGenerator.Call(this.indent, actualMethodCalled, actualMethodCalled.MemberInfo.Class, s.Identifier);
            return(null);
        }
 public override object Exec(MethodType actualMethod, object arg)
 {
     // * 1.1 The implicit object has a known type and can a lso have candidate methods maybe a candidate objec
     if (this.firstTime)
     {
         this.firstTime = false;
         this.areThereNonValidObjects = TypeExpression.As <UnionType>(((FieldAccessExpression)this.node.Identifier).Expression.ExpressionType) != null;
         this.InvokeSingleMethod(actualMethod, arg);
         //this.EndInvocationMethod();
         return(null);
     }
     this.InvokeUnionMethod(actualMethod, arg);
     return(null);
 }
예제 #10
0
 public override object Exec(FieldType d, object arg)
 {
     if (d.FieldTypeExpression != null)
     {
         // * If the field type is a dynamic union type, so it is the union
         UnionType unionType = TypeExpression.As <UnionType>(d.FieldTypeExpression);
         if (unionType != null)
         {
             DynVarOptions.Instance.AssignDynamism(d.FieldTypeExpression, d.IsDynamic);
         }
         return(d.FieldTypeExpression.AcceptOperation(this, arg));
     }
     return(null);
 }
        public override object Exec(NullType firstOperand, object arg)
        {
            // * Built-in types: no promotion, except string
            if (this.secondOperand is BoolType || this.secondOperand is CharType || this.secondOperand is DoubleType || this.secondOperand is IntType || this.secondOperand is VoidType)
            {
                return(-1);
            }
            // * BCL Value Types (structs): No promotion
            BCLClassType bclClass = TypeExpression.As <BCLClassType>(this.secondOperand);

            if (bclClass != null)
            {
                if (bclClass.TypeInfo.IsValueType)
                {
                    return(-1);
                }
                // * Correct promotion to classes that are not value types
                return(0);
            }
            // * WriteType variable
            TypeVariable typeVariable = this.secondOperand as TypeVariable;

            if (typeVariable != null)
            {
                if (typeVariable.Substitution != null)
                {
                    // * If the variable is bounded, the promotion is the one of its substitution
                    return(firstOperand.AcceptOperation(new PromotionLevelOperation(typeVariable.EquivalenceClass.Substitution), arg));
                }
                // * A free variable is complete promotion
                return(0);
            }
            // * Union type
            UnionType unionType = TypeExpression.As <UnionType>(this.secondOperand);

            if (unionType != null)
            {
                return(unionType.SuperType(firstOperand));
            }
            // * Field type and bounded type variable
            FieldType fieldType = TypeExpression.As <FieldType>(this.secondOperand);

            if (fieldType != null)
            {
                return(firstOperand.AcceptOperation(new PromotionLevelOperation(fieldType.FieldTypeExpression), arg));
            }
            // * Correct Promotion
            return(0);
        }
예제 #12
0
        ///  * ld       <implicit object>
        ///  * <for each method of UnionMethods>
        ///  *    // check the invocation reference
        ///  *    dup
        ///  *    isinst <class type of actualMethod>
        ///  *    brfalse <check NextMethod> (Unbox needed for value types (not Unbox.any))
        ///  *    // check arguments
        ///  *    <for each argument>
        ///  *       dup
        ///  *       isinst <current parameter of actualMethod> (If param is ValueType, is the argument of this type or can promote to this type?)
        ///  *       brfalse <NextMethod> (Box needed for value types)
        ///  *    call <current method>
        ///  *    br <EndLabel>
        ///  *    // check NextMethod
        ///  *    <NextMethod>
        ///  *    <clean elements on the stack>
        ///  *  // There are some mistakes
        ///  *  call <WrongMethodException>
        ///  *  <EndLabel>

        #endregion
        public override Object Visit(InvocationExpression node, Object obj)
        {
            InheritedAttributes ia = (InheritedAttributes)obj; //Simple cast to shorten thee expression
            Object objArgs         = obj;
            //Object o = null;
            InheritedAttributes objInv             = new InheritedAttributes(ia.CurrentMethod, ia.Assignment, ia.Reference, ia.ArrayAccessFound, ia.ActualMethodCalled, true);
            MethodType          actualMethodCalled = TypeExpression.As <MethodType>(node.ActualMethodCalled);

            if (actualMethodCalled != null)
            {
                objArgs = new InheritedAttributes(ia.CurrentMethod, ia.Assignment, ia.Reference, ia.ArrayAccessFound, actualMethodCalled, true);
            }

            return(node.Identifier.AcceptOperation(new CGILInvocationExpressionOperation <T>(this.indent, this, this.codeGenerator, node, ia, objInv, objArgs), null));
        }
        public override object Exec(TypeVariable t, object arg)
        {
            if (!t.IsFreshVariable())
            {
                return(t.Substitution.AcceptOperation(this, arg));
            }

            this.hasTypeVariable = true;
            if (this.firstTime)
            {
                this.firstTime = false;
                this.areThereNonValidObjects = TypeExpression.As <UnionType>(((FieldAccessExpression)this.node.Identifier).Expression.ExpressionType) != null;
                this.EndInvocationMethod(false);
            }
            return(null);
        }
 /// <summary>
 /// It delegates the operation in several types.
 /// </summary>
 /// <param name="operand"></param>
 /// <returns></returns>
 public override object Exec(TypeVariable operand, object arg)
 {
     if (!operand.IsValueType())
     {
         return(null);
     }
     if (TypeExpression.Is <IntType>(operand))
     {
         return(this.Exec(TypeExpression.As <IntType>(operand), arg));
     }
     if (TypeExpression.Is <DoubleType>(operand))
     {
         return(this.Exec(TypeExpression.As <DoubleType>(operand), arg));
     }
     return(this.Exec((TypeExpression)operand, arg));
 }
        public override object Exec(SingleIdentifierExpression s, object arg)
        {
            // * 2. A message is sent with without the implicit object "method(...)"
            //// * 2.1 A method is called (not a constructor)
            MethodType actualMethodCalled = TypeExpression.As <MethodType>(node.ActualMethodCalled);

            if ((((MethodType)node.ActualMethodCalled).MemberInfo.ModifierMask & Modifier.Static) == 0)
            {
                this.codeGenerator.ldarg(this.indent, 0);
            }
            this.node.Arguments.Accept(this.visitor, this.objArgs);
            this.codeGenerator.Call(this.indent, actualMethodCalled, actualMethodCalled.MemberInfo.Class, s.Identifier);
            //If the actualMethodCalled returns a TypeVariable and the InvocationExpression returns a ValueType an unboxing is needed, becasue there is not auto-unboxing from object to a ValueType.
            //if (actualMethodCalled.Return is TypeVariable && actualMethodCalled.Return.IsFreshVariable() && node.ExpressionType.IsValueType())
            //  this.codeGenerator.UnboxAny(this.indent, node.ExpressionType);
            return(null);
        }
        public override object Exec(ArrayType operand1, object arg)
        {
            // * Is it an array?
            ArrayType arrayType = TypeExpression.As <ArrayType>(this.operand2);

            if (arrayType != null)
            {
                return(operand1.ArrayTypeExpression.AcceptOperation(new EquivalentOperation(arrayType.ArrayTypeExpression), arg));
            }

            // * It can be a System.Array
            BCLClassType bclClassType = TypeExpression.As <BCLClassType>(this.operand2);

            if (bclClassType.TypeInfo.IsArray)
            {
                TypeExpression elementType = TypeTable.Instance.GetType(bclClassType.TypeInfo.GetElementType().FullName, new Location());
                return(elementType.AcceptOperation(new EquivalentOperation(operand1), arg));
            }

            return(false);
        }
        /// <summary>
        /// Tries to unify the constraints of a method call
        /// </summary>
        /// <param name="methodAnalyzed">The method that is being analyzed when the operation is performed.</param>
        /// <param name="actualImplicitObject">Only suitable in an assignment constraint. It represents the actual object used to pass the message.</param>
        /// <param name="showInvocationMessage">To show the invocation line and column in case an error exists</param>
        /// <param name="activeSortOfUnification">The active sort of unification used (Equivalent is the default
        /// one and Incremental is used in the SSA bodies of the while, for and do statements)</param>
        /// <param name="location">The location where the location is called</param>
        /// <returns>If the unification has been satisfied</returns>
        public override TypeExpression Check(MethodType methodAnalyzed, TypeExpression actualImplicitObject, bool showInvocationMessage,
                                             SortOfUnification activeSortOfUnification, Location location)
        {
            // * If the actual implicit object is a field, we take its field's type
            FieldType      implicitObjectAsField = TypeExpression.As <FieldType>(this.actualImplicitObject);
            ClassType      implicitObjectAsClass;
            TypeExpression implicitObject = this.ActualImplicitObject;

            if (implicitObjectAsField != null)
            {
                implicitObject        = implicitObjectAsField.FieldTypeExpression;
                implicitObjectAsClass = TypeExpression.As <ClassType>(implicitObjectAsField.FieldTypeExpression);
            }
            else
            {
                implicitObjectAsClass = TypeExpression.As <ClassType>(this.actualImplicitObject);
            }
            // * If the actual implicit object is concrete, so it is the saved implicit object
            if (ClassType.IsConcreteType(actualImplicitObject) != null && implicitObjectAsClass != null)
            {
                implicitObjectAsClass.ConcreteType = true;
            }

            // * If the unification in the method call is incremental, this is the one to be used
            SortOfUnification unification = activeSortOfUnification == SortOfUnification.Incremental ? SortOfUnification.Incremental : this.sortOfUnification;
            // * Checks the parenthesis operation
            TypeExpression result = (TypeExpression)this.FirstOperand.AcceptOperation(new ParenthesisOperation(implicitObject, this.Parameters, methodAnalyzed, unification, this.Location), null);

            if (result == null && showInvocationMessage)
            {
                ErrorManager.Instance.NotifyError(new ConstraintError(location));
                return(null);
            }
            // * If no error exists, we unify the return type variable with the actual result
            this.ReturnType.Unify(result, SortOfUnification.Equivalent, new List <Pair <TypeExpression, TypeExpression> >());
            this.ReturnType.ValidTypeExpression = this.ValidTypeExpression = false;
            return(this.ReturnType);
        }
        public override object Exec(BCLClassType operand1, object arg)
        {
            if (this.operand2 == null)
            {
                return(false);
            }

            if (operand1.FullName.Equals(this.operand2.FullName))
            {
                return(true);
            }

            if ((bool)BCLClassType.BCLtoTypeSystemMapping.ContainsKey(operand1.FullName) && (bool)BCLClassType.BCLtoTypeSystemMapping[operand1.FullName].AcceptOperation(new EquivalentOperation(operand2), null))
            {
                return(true);
            }

            if (operand1.TypeInfo.IsArray)
            {
                Type elementType = operand1.TypeInfo.GetElementType();

                if (this.operand2 is ArrayType)
                {
                    return(new BCLClassType(elementType.FullName, elementType).AcceptOperation(new EquivalentOperation(((ArrayType)this.operand2).ArrayTypeExpression), null));
                }

                BCLClassType bclType = TypeExpression.As <BCLClassType>(this.operand2);
                if (bclType != null && bclType.TypeInfo.IsArray)
                {
                    TypeExpression thisArrayType  = TypeTable.Instance.GetType(operand1.TypeInfo.GetElementType().FullName, new Location()),
                                   paramArrayType = TypeTable.Instance.GetType(bclType.TypeInfo.GetElementType().FullName, new Location());
                    return(thisArrayType.AcceptOperation(new EquivalentOperation(paramArrayType), null));
                }
            }
            return(false);
        }
        public override object Exec(InterfaceType firstOperand, object arg)
        {
            int aux, less = -1;

            // * Equivalent types
            if ((bool)firstOperand.AcceptOperation(new EquivalentOperation(this.secondOperand), arg))
            {
                less = 0;
            }

            // * WriteType variable
            TypeVariable typeVariable = this.secondOperand as TypeVariable;

            if (typeVariable != null)
            {
                if (typeVariable.Substitution != null)
                {
                    // * If the variable is bounded, the promotion is the one of its substitution
                    return(firstOperand.AcceptOperation(new PromotionLevelOperation(typeVariable.EquivalenceClass.Substitution), arg));
                }
                // * A free variable is complete promotion
                return(0);
            }

            // * Field type and bounded type variable
            FieldType fieldType = TypeExpression.As <FieldType>(this.secondOperand);

            if (fieldType != null)
            {
                return(firstOperand.AcceptOperation(new PromotionLevelOperation(fieldType.FieldTypeExpression), arg));
            }

            // * Interface List
            if (firstOperand.InterfaceList.Count != 0)
            {
                for (int i = 0; i < firstOperand.InterfaceList.Count; i++)
                {
                    if ((bool)firstOperand.InterfaceList[i].AcceptOperation(new EquivalentOperation(this.secondOperand), arg))
                    {
                        if ((less > 1) || (less == -1))
                        {
                            less = 1;
                        }
                    }
                    else
                    {
                        aux = (int)firstOperand.InterfaceList[i].AcceptOperation(this, arg);
                        if (aux != -1)
                        {
                            if (less > aux + 1 || less == -1)
                            {
                                less = aux + 1;
                            }
                        }
                    }
                }
            }
            if (less != -1)
            {
                return(less);
            }

            // * Union type
            UnionType unionType = TypeExpression.As <UnionType>(this.secondOperand);

            if (unionType != null)
            {
                return(unionType.SuperType(firstOperand));
            }

            // * No promotion
            return(-1);
        }
        /// <summary>
        /// Performs an assigment operation between a FieldType type and the typeExpression stored in this.rightOperand.
        /// The result of the operation is the resulting operation of doing PromotionOperation the operation.
        /// </summary>
        /// <param name="leftOperand">A FieldType, the left operand of the assignment/param>
        /// <returns> The result of the operation is the resulting operation of doing The Assignment operation.
        ///</returns>
        public override object Exec(FieldType leftOperand, object arg)
        {
            // * We check if a constraint must be generated. Is it an assignment of the implicit object's field?
            bool found = false;

            // * In case it has free variables and the reference used is this, we add a constraint to the method
            if (leftOperand.HasTypeVariables() && this.methodAnalyzed != null &&
                ClassType.IsConcreteType(this.actualImplicitObject) == null)
            {
                // * They should be the same exact (sub)classes. This represent the same instance, not another instance of the same class.
                ClassType methodSuperClass = (ClassType)this.methodAnalyzed.MemberInfo.Class;
                while (!(found = (leftOperand.MemberInfo.Class == methodSuperClass)) && methodSuperClass != null)
                {
                    methodSuperClass = methodSuperClass.BaseClass;
                }
                if (found)
                {
                    // * An assignment constraint is added, postponing the type inference
                    // * If an actual implicit object is used, we take its field's type
                    FieldType fieldType = leftOperand;
                    ClassType thisType  = TypeExpression.As <ClassType>(this.actualImplicitObject);
                    if (thisType == null)
                    {
                        FieldType field = TypeExpression.As <FieldType>(this.actualImplicitObject);
                        if (field != null)
                        {
                            thisType = TypeExpression.As <ClassType>(field.FieldTypeExpression);
                        }
                    }

                    if (thisType != null)
                    {
                        while (thisType != null && !thisType.Fields.ContainsKey(leftOperand.MemberInfo.MemberIdentifier))
                        {
                            thisType = thisType.BaseClass;
                        }
                        if (thisType != null)
                        {
                            fieldType = (FieldType)thisType.Fields[leftOperand.MemberInfo.MemberIdentifier].Type;
                        }
                    }

                    this.methodAnalyzed.AddConstraint(new FieldTypeAssignmentConstraint(fieldType, this.rightOperand,
                                                                                        this.unification));
                    this.methodAnalyzed.ValidTypeExpression = false;
                    if (leftOperand.FieldTypeExpression is TypeVariable && rightOperand is ArrayType)
                    {
                        TypeVariable typeVariable = (TypeVariable)leftOperand.FieldTypeExpression;
                        typeVariable.AcceptOperation(new AssignmentOperation(rightOperand, this.op, null, SortOfUnification.Override, null, this.location), arg);
                    }
                    else if (leftOperand.FieldTypeExpression is TypeVariable && TypeExpression.As <ClassType>(rightOperand) != null && ((TypeVariable)leftOperand.FieldTypeExpression).IsDynamic)
                    {
                        TypeVariable typeVariable = (TypeVariable)leftOperand.FieldTypeExpression;
                        typeVariable.AcceptOperation(new AssignmentOperation(rightOperand, this.op, null, SortOfUnification.Override, null, this.location), arg);
                    }
                    else if (leftOperand.FieldTypeExpression is TypeVariable && rightOperand is TypeVariable && ((TypeVariable)rightOperand).Substitution == null && ((TypeVariable)rightOperand).IsDynamic)
                    {
                        TypeVariable typeVariable = (TypeVariable)leftOperand.FieldTypeExpression;
                        typeVariable.AcceptOperation(new AssignmentOperation(rightOperand, this.op, null, SortOfUnification.Override, null, this.location), arg);
                    }
                    return(leftOperand.FieldTypeExpression);
                }
                if (leftOperand.FieldTypeExpression is TypeVariable)
                {
                    TypeVariable typeVariable = (TypeVariable)leftOperand.FieldTypeExpression;
                    if (typeVariable.Substitution != null)
                    {
                        return
                            (leftOperand.FieldTypeExpression.AcceptOperation(
                                 new AssignmentOperation(this.rightOperand, this.op, null,
                                                         SortOfUnification.Incremental, this.actualImplicitObject,
                                                         this.location), arg));
                    }
                }
            }

            if (leftOperand.FieldTypeExpression != null)
            {
                return
                    (leftOperand.FieldTypeExpression.AcceptOperation(
                         new AssignmentOperation(this.rightOperand, this.op, null, this.unification,
                                                 this.actualImplicitObject, this.location), arg));
            }

            return(null);
        }