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); }
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); }
//// <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)); }
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); }
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); }
/// * 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); }