diff --git a/tests/test_lang.py b/tests/test_lang.py index c7b609e..3677d6d 100644 --- a/tests/test_lang.py +++ b/tests/test_lang.py @@ -1,5 +1,6 @@ import unittest +from transforge.namespace import EX from transforge.type import TypeOperator, TypeAlias, \ _, Top, TypeVariable, TypeParameterError, UnexpectedVariableError from transforge.expr import Operator, Source @@ -187,6 +188,16 @@ def test_missing_input_default_sources(self): lang.parse("f 1", defaults=True).match(f(Source()), strict=False) ) + def test_parse_type_uri(self): + F = TypeOperator(params=2) + A = TypeOperator() + lang = Language(scope=locals(), namespace=EX, canon={F(F(A, A), A)}) + t = F(F(A, A), A) + s = F(A, F(A, A)) + self.assertEqual(lang.uri(t), EX["F-F-A-A-A"]) + self.assertEqual(lang.parse_type_uri(EX["F-F-A-A-A"]), t) + self.assertEqual(lang.parse_type_uri(EX["F-A-F-A-A"]), s) + if __name__ == '__main__': unittest.main() diff --git a/transforge/lang.py b/transforge/lang.py index 3f796f4..934f3e5 100644 --- a/transforge/lang.py +++ b/transforge/lang.py @@ -337,6 +337,20 @@ def parse_operator(self, token: str) -> Operator: except KeyError as e: raise UndefinedTokenError(token) from e + def parse_type_uri(self, uri: URIRef) -> TypeInstance: + """Parse an URI back to a concrete type instance. Inverse operation to + `.uri()`.""" + ops = [self.types[x] for x in uri[len(self.namespace):].split("-")] + types: list[TypeInstance] = [] + while ops: + op = ops.pop() + assert len(types) >= op.arity + t = op(*reversed(types[:op.arity])) + types = types[op.arity:] + types.append(t) + assert len(types) == 1 + return types[0] + def parse_type(self, value: str | Iterator[str]) -> TypeInstance: if isinstance(value, str): consume_all = True