public ResolvedType FindCommonAncestor(ResolvedType typeA, ResolvedType typeB) { if (typeA == this.typeContext.ANY || typeB == this.typeContext.ANY) { return(this.typeContext.ANY); } if (typeA == typeB) { return(typeA); } if ((typeA == this.typeContext.INTEGER && typeB == this.typeContext.FLOAT) || (typeA == this.typeContext.FLOAT && typeB == this.typeContext.INTEGER)) { return(this.typeContext.FLOAT); } if (typeA == this.typeContext.NULL || typeB == this.typeContext.NULL) { ResolvedType nonNull = typeA == this.typeContext.NULL ? typeB : typeA; switch (nonNull.Category) { case ResolvedTypeCategory.STRING: case ResolvedTypeCategory.LIST: case ResolvedTypeCategory.DICTIONARY: case ResolvedTypeCategory.FUNCTION_POINTER: case ResolvedTypeCategory.INSTANCE: case ResolvedTypeCategory.CLASS_DEFINITION: return(nonNull); default: return(this.typeContext.OBJECT); } } if (typeA.Category != typeB.Category) { return(this.typeContext.OBJECT); } switch (typeA.Category) { case ResolvedTypeCategory.LIST: case ResolvedTypeCategory.DICTIONARY: return(this.typeContext.OBJECT); case ResolvedTypeCategory.INSTANCE: ClassDefinition c1 = typeA.ClassTypeOrReference; ClassDefinition c2 = typeB.ClassTypeOrReference; ClassDefinition commonParent = c1.GetCommonAncestor(c2); if (commonParent == null) { return(this.typeContext.OBJECT); } return(ResolvedType.GetInstanceType(this.typeContext, commonParent)); default: throw new System.NotImplementedException(); } }
internal override Expression ResolveTypes(ParserContext parser, TypeResolver typeResolver) { ClassDefinition cd = this.Class; if (this.ConstructorReference != null) { ResolvedType[] expectedArgTypes = this.ConstructorReference.ResolvedArgTypes; for (int i = 0; i < this.Args.Length; ++i) { this.Args[i] = this.Args[i].ResolveTypes(parser, typeResolver); ResolvedType expectedType = expectedArgTypes[i]; ResolvedType actualType = this.Args[i].ResolvedType; if (actualType == ResolvedType.ANY && expectedType != ResolvedType.ANY && expectedType != ResolvedType.OBJECT) { this.Args[i] = new Cast(this.Args[i].FirstToken, expectedType, this.Args[i], this.Owner, false); } else if (!this.Args[i].ResolvedType.CanAssignToA(expectedArgTypes[i])) { throw new ParserException(this.Args[i], "Cannot pass an argument of this type."); } } } this.ResolvedType = ResolvedType.GetInstanceType(cd); return(this); }
public ResolvedType ResolveType(AType type) { if (type.IsAnyType) { return(this.typeContext.ANY); } switch (type.RootType) { case "void": return(this.typeContext.VOID); case "int": return(this.typeContext.INTEGER); case "bool": return(this.typeContext.BOOLEAN); case "float": return(this.typeContext.FLOAT); case "string": return(this.typeContext.STRING); case "object": return(this.typeContext.OBJECT); case "[": case "List": if (type.Generics.Length != 1) { throw new ParserException(type.FirstToken, "A list type has 1 generic."); } return(ResolvedType.ListOrArrayOf(ResolveType(type.Generics[0]))); case "Dictionary": if (type.Generics.Length != 2) { throw new ParserException(type.FirstToken, "A dictionary type has 2 generics."); } ResolvedType keyType = ResolveType(type.Generics[0]); ResolvedType valueType = ResolveType(type.Generics[1]); switch (keyType.Category) { case ResolvedTypeCategory.INSTANCE: case ResolvedTypeCategory.INTEGER: case ResolvedTypeCategory.STRING: // This is fine. break; default: throw new ParserException(type.Generics[0].FirstToken, "This is not a valid key type for a dictionary."); } return(ResolvedType.GetDictionaryType(keyType, valueType)); default: ClassDefinition classDef = this.owner.FileScope.DoClassLookup(this.owner, type.FirstToken, type.RootType); return(ResolvedType.GetInstanceType(this.typeContext, classDef)); } }
internal override Expression ResolveTypes(ParserContext parser, TypeResolver typeResolver) { Node walker = this.Owner; while (!(walker is ClassDefinition)) { walker = walker.Owner; if (walker == null) { throw new System.Exception(); // already verified exists in a ClassDefinition in ResolveEntityNames, so this should never happen. } } this.ResolvedType = ResolvedType.GetInstanceType(parser.TypeContext, (ClassDefinition)walker); return(this); }