diff --git a/projects/shoggoth/src/python/ichor/state.py b/projects/shoggoth/src/python/ichor/state.py index ba5b006..e40bd6b 100644 --- a/projects/shoggoth/src/python/ichor/state.py +++ b/projects/shoggoth/src/python/ichor/state.py @@ -6,35 +6,13 @@ import typing as t from ichor.isa import Opcode -from lark import Lark +from lark import Lark, Transformer, v_args, Token class Identifier(t.NamedTuple): name: str -class FunctionSignature(t.NamedTuple): - raw: str - type_params: list - name: str - args: list - ret: list - - @staticmethod - def parse_list(l): - return [e for e in l.split(",") if e] - - @classmethod - def parse(cls, raw: str): - vars, name, args, ret = raw.split(";") - return cls( - raw, - cls.parse_list(vars), - name, - cls.parse_list(args), - cls.parse_list(ret) - ) - GRAMMAR = r""" fun: constraints ";" name ";" arguments ";" ret @@ -44,7 +22,7 @@ constraints: (constraint ","?)* constraint: type var: constraints ";" name ";" arms -arms: (arm ("," arms)?)? +arms: (arm ","?)+ arm: name "(" bindings ")" bindings: (binding ","?)* @@ -52,10 +30,37 @@ binding: name ":" type type: NAME name: NAME -NAME: /[^;,:⊢]+/ +NAME: /[^;,:⊢()<>\[\]{}|]+/ """ -FUNC = Lark(GRAMMAR, start="fun") +class FuncT(Transformer): + @v_args(inline=True) + def fun(self, constraints, name, arguments, ret): + return (constraints, name, arguments, ret) + + def constraints(self, args): + return (*args,) + + def arguments(self, args): + return tuple(args) + + def ret(self, args): + return tuple(args) + + @v_args(inline=True) + def NAME(self, name: Token): + return name.value + + @v_args(inline=True) + def name(self, name): + return name + + @v_args(inline=True) + def type(self, name): + return name + + +FUNC = Lark(GRAMMAR, start="fun", parser='lalr', transformer=FuncT()) class FunctionRef(t.NamedTuple): @@ -90,8 +95,36 @@ class Function(t.NamedTuple): typeconstraints: t.List[t.Any] = [] metadata: dict = {} + @classmethod + def build(cls, name: str, instructions: t.List[Opcode]): + pass -VAR = Lark(GRAMMAR, start="var") + +class VarT(FuncT): + @v_args(inline=True) + def var(self, constraints, name, arms): + return (constraints, name, arms) + + @v_args(inline=True) + def constraint(self, name): + return name + + def arms(self, arms): + return tuple(arms) + + def binding(self, binding): + return tuple(binding) + + def bindings(self, bindings): + return tuple(bindings) + + @v_args(inline=True) + def arm(self, name, bindings): + return (name, bindings) + + + +VAR = Lark(GRAMMAR, start="var", parser='lalr', transformer=VarT()) class Type(t.NamedTuple): name: str diff --git a/projects/shoggoth/test/python/ichor/test_parsers.py b/projects/shoggoth/test/python/ichor/test_parsers.py index 60ce168..1b9a6c6 100644 --- a/projects/shoggoth/test/python/ichor/test_parsers.py +++ b/projects/shoggoth/test/python/ichor/test_parsers.py @@ -5,21 +5,18 @@ from ichor.state import FUNC, VAR import pytest -@pytest.mark.parametrize('sig', [ - ";not;bool;bool", - ";and;bool,bool;bool", - ";or;bool,bool,bool;bool", +@pytest.mark.parametrize('sig,parse', [ + (";not;bool;bool", ((), "not", ("bool",), ("bool",))), + (";and;bool,bool;bool", ((), "and", ("bool", "bool"), ("bool",))), + (";or;bool,bool,bool;bool", ((), "or", ("bool", "bool", "bool"), ("bool",))), ]) -def test_func_parses(sig): - assert FUNC.parse(sig) +def test_func_parses(sig, parse): + assert FUNC.parse(sig) == parse -@pytest.mark.parametrize('sig', [ - ";bool;true(),false()", - "A,B;pair;pair(a:A,b:B)", - "A,B,C;tripple;tripple(a:A,b:B,c:C)", - "A,B,C,D;quad;quad(a:A,b:B,c:C,d:D)", - "A,B,C,D,E;quint;quint(a:A,b:B,c:C,d:D,e:E)", +@pytest.mark.parametrize('sig,parse', [ + (";bool;true(),false()", ((), "bool", (("true", ()), ("false", ())))), + ("A,B;pair;pair(a:A,b:B)", (("A", "B"), "pair", (("pair", (("a", "A"), ("b", "B"))),))), ]) -def test_var_parses(sig): - assert VAR.parse(sig) +def test_var_parses(sig, parse): + assert VAR.parse(sig) == parse