public override object Exec(UnionType d, object arg) { // * Infinite loop detection if (previousDot.Contains(d)) { return(new UnionType()); } previousDot.Add(d); // * If all the types in typeset generate a constraint, we simply generate one constraint using the whole union type if (d.IsFreshVariable() && methodAnalyzed != null) { // * A constraint is added to the method analyzed DotConstraint constraint = new DotConstraint(d, this.memberName, this.location); methodAnalyzed.AddConstraint(constraint); return(constraint.ReturnType); } TypeExpression returnType = null; foreach (TypeExpression type in d.TypeSet) { TypeExpression ret; if (!d.IsDynamic) { // * Static Behaviour: All the types must accept the attribute access ret = (TypeExpression)type.AcceptOperation(this, arg); if (ret == null) { return(null); } } else { // * Dynamic Behaviour: Only one type must accept the attribute access ret = (TypeExpression)type.AcceptOperation(new UnconstrainedDotOperation(this.memberName, previousDot), arg); } if (ret != null) { returnType = UnionType.collect(returnType, ret); } } // * If it is a dynamic union, one type must accept the attribute access if (returnType == null) { ErrorManager.Instance.NotifyError(new NoTypeHasMember(d.FullName, this.memberName, this.location)); } return(returnType); }
public override object Exec(TypeVariable d, object arg) { if (d.Substitution != null) { DynVarOptions.Instance.AssignDynamism(d.Substitution, d.IsDynamic); return(d.Substitution.AcceptOperation(this, arg)); } if (methodAnalyzed != null) { // * A attribute access constraint is added to the method analyzed DotConstraint constraint = new DotConstraint(d, this.memberName, this.location); methodAnalyzed.AddConstraint(constraint); return(constraint.ReturnType); } ErrorManager.Instance.NotifyError(new OperationNotAllowedError(".", d.FullName, this.location)); return(null); }