From 197dfd0089436b5a7b74ff6d8608f1ddcbfd5ec5 Mon Sep 17 00:00:00 2001
From: Reid 'arrdem' McKenzie <me@arrdem.com>
Date: Wed, 15 Jun 2022 01:12:22 -0600
Subject: [PATCH] Better parser tests

---
 projects/shoggoth/src/python/ichor/state.py   | 87 +++++++++++++------
 .../test/python/ichor/test_parsers.py         | 25 +++---
 2 files changed, 71 insertions(+), 41 deletions(-)

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