def __missing__(self, key) -> TypeScheme: from xotl.fl.utils import tvarsupply from xotl.fl.match import MatchLiteral, Extract from xotl.fl.ast.types import TypeVariable # Constructors of tuples are not fixed, since now you can have (1, 2, # 3..., 10000); that's a long tuple with a single constructor # (,,...,,); i.e 9999 commas. if isinstance(key, str) and TUPLE_CONS.match(key): items = len(key) + 1 names = list(tvarsupply(limit=items)) type: Type = TypeCons(key, names) for name in reversed(names): type = name >> type return TypeScheme.from_typeexpr(type) elif isinstance(key, Extract) and TUPLE_CONS.match(key.name): # The type of 'extract' for tuple varies with the number of # components of the tuple. Example, for a triple, Extract(',,', # 2) -- i.e. extracting the second element; has the type scheme # 'forall a b c r. (a, b, c) -> (b -> r) -> r'. type_ = self[key.name].type_ assert isinstance(type_, TypeCons) res = TypeVariable(".r", check=False) return TypeScheme.from_typeexpr(type_ >> ( (type_.subtypes[key.arg - 1] >> res) >> res)) elif isinstance(key, MatchLiteral): # The match has type 'a -> (a -> r) -> r'; where a is the type of # the literal. We must ensure to generate a new variable not free # in type a. Everywhere else we generate types '.a0', '.a1'. # Let's use '.r' as the result type. a = key.value.type_ res = TypeVariable(".r", check=False) return TypeScheme.from_typeexpr(a >> ((a >> res) >> res)) else: raise KeyError(key) # pragma: no cover
def result(name: str) -> Type: missing = object() restype: Type = missing # type: ignore pos = 0 while restype is missing and pos < len(lst): generic, newvar = lst[pos] pos += 1 if generic == name: restype = newvar if restype is missing: return TypeVariable(name, check=False) else: return restype
def type_variable(self, tree): token: Token = tree.children[0] return TypeVariable(token.value)
def __missing__(self, key) -> TypeSchema: try: return super().__missing__(key) except KeyError: var = TypeVariable(key, check=False) return TypeSchema.from_typeexpr(var)
def __next__(self) -> TypeVariable: name = next(self.ns) return TypeVariable(name, check=False)
def __call__(self, s: str) -> Type: return self.type_ if s == self.vname else TypeVariable(s, check=False)
def __call__(self, s: str) -> Type: return TypeVariable(s, check=False)
def __call__(self, s: str) -> Type: if s not in self.ts.generics: return self.phi(s) else: return TypeVariable(s, check=False)