It is now part of the normal constraints. Added a special workaround for functions, since otherwise the output is a bit redundant and quite confusing. Also, constraints are now processed in order of complexity. This does not affect type safety. It uses a bit more CPU. But it makes the output that much easier to read. Also, removes the weird FunctionInstance hack. Instead, the more industry standard way of annotation the types on the function call is used. As always, this requires some hackyness for Subscriptable. Also, adds a few comments to the type unification to help with debugging. Also, prints out the new constraints that are received.
51 lines
1.3 KiB
Python
51 lines
1.3 KiB
Python
from .record import Record
|
|
from .typeexpr import (
|
|
AtomicType,
|
|
TypeApplication,
|
|
TypeConstructor,
|
|
TypeExpr,
|
|
TypeLevelNat,
|
|
TypeVariable,
|
|
)
|
|
|
|
|
|
class TypeRouter[T]:
|
|
def when_atomic(self, typ: AtomicType) -> T:
|
|
raise NotImplementedError(typ)
|
|
|
|
def when_application(self, typ: TypeApplication) -> T:
|
|
raise NotImplementedError(typ)
|
|
|
|
def when_constructor(self, typ: TypeConstructor) -> T:
|
|
raise NotImplementedError(typ)
|
|
|
|
def when_record(self, typ: Record) -> T:
|
|
raise NotImplementedError(typ)
|
|
|
|
def when_type_level_nat(self, typ: TypeLevelNat) -> T:
|
|
raise NotImplementedError(typ)
|
|
|
|
def when_variable(self, typ: TypeVariable) -> T:
|
|
raise NotImplementedError(typ)
|
|
|
|
def __call__(self, typ: TypeExpr) -> T:
|
|
if isinstance(typ, AtomicType):
|
|
if isinstance(typ, Record):
|
|
return self.when_record(typ)
|
|
|
|
return self.when_atomic(typ)
|
|
|
|
if isinstance(typ, TypeApplication):
|
|
return self.when_application(typ)
|
|
|
|
if isinstance(typ, TypeConstructor):
|
|
return self.when_constructor(typ)
|
|
|
|
if isinstance(typ, TypeLevelNat):
|
|
return self.when_type_level_nat(typ)
|
|
|
|
if isinstance(typ, TypeVariable):
|
|
return self.when_variable(typ)
|
|
|
|
raise NotImplementedError(typ)
|