From d91eb65d4db0ebce6adc8e8e0614f09b43df9994 Mon Sep 17 00:00:00 2001
From: Michael Zhang <mail@mzhang.io>
Date: Wed, 9 Jun 2021 01:48:34 -0500
Subject: [PATCH] get rid of terminal aliases

---
 Justfile     |  2 +-
 agast.py     |  8 ++++----
 agtypeck.py  | 14 +++++++++++++-
 gen.py       | 20 ++++++++++++++------
 grammar.lark | 30 ++++++++----------------------
 watch.ps1    |  2 +-
 6 files changed, 41 insertions(+), 35 deletions(-)

diff --git a/Justfile b/Justfile
index 029ae70..f7cb75d 100644
--- a/Justfile
+++ b/Justfile
@@ -1,2 +1,2 @@
 watch:
-	watchexec -ce py -i gen 'mypy *.py && python gen.py && mypy gen/*.py'
+	watchexec -ce py,lark -i gen 'mypy *.py && python gen.py && mypy gen/*.py'
diff --git a/agast.py b/agast.py
index 6ff1e03..117dcc7 100644
--- a/agast.py
+++ b/agast.py
@@ -85,16 +85,16 @@ class Parser(Transformer[List[Decl]]):
 	def node_ref_name(self, items: List[str]) -> NodeRefByName: return NodeRefByName(items[0])
 
 	def expr_dot(self, items: List[Expr]) -> Expr:
-		[left, _, right] = items
+		[left, right] = items
 		return ExprDot(left, right)
 	def expr_add(self, items: List[Expr]) -> Expr:
-		[left, _, right] = items
+		[left, right] = items
 		return ExprAdd(left, right)
 	def expr_mul(self, items: List[Expr]) -> Expr:
-		[left, _, right] = items
+		[left, right] = items
 		return ExprMul(left, right)
 	def expr_call(self, items: List[Expr]) -> Expr:
-		[func, _, args, _] = items
+		[func, args] = items
 		return ExprMul(func, args)
 
 	def sep_trail(self, items: List[Tree]) -> List[T]:
diff --git a/agtypeck.py b/agtypeck.py
index 24f2cc1..638027d 100644
--- a/agtypeck.py
+++ b/agtypeck.py
@@ -1,7 +1,12 @@
 from typing import *
 from agast import *
 
-def typecheck(program: List[Decl]) -> None:
+class TypecheckResult:
+	def __init__(self, pd: str):
+		self.parser_data = pd
+
+
+def typecheck(program: List[Decl]) -> TypecheckResult:
 	i = 0
 	def gen(name: str = "") -> str:
 		return f"__ag{i:03}{name}"
@@ -13,5 +18,12 @@ def typecheck(program: List[Decl]) -> None:
 			program)))
 	print(ifaces)
 
+	# a high-level dictionary of productions; this has sub-productions
+	# that should be further expanded at a later step before converting
+	# into lark code
+	productions_hi: Dict[str, Union[str, List[str]]] = dict()
+
 	for node in filter(lambda c: isinstance(c, Node), program):
 		print(node)
+
+	return TypecheckResult("")
\ No newline at end of file
diff --git a/gen.py b/gen.py
index ed33aa9..cdbcc8a 100644
--- a/gen.py
+++ b/gen.py
@@ -18,18 +18,26 @@ if __name__ == "__main__":
 	ast = trans.transform(cst)
 	print("ast", ast)
 
-	typecheck(ast)
-
-	parser_data = ""
+	res = typecheck(ast)
 
 	if not os.path.exists("gen"):
 		os.makedirs("gen")
 	with open("gen/arith.py", "w") as f:
 		f.write(textwrap.dedent(f"""
-			from typing import Generic, TypeVar
-			from lark import Lark
+			from typing import Generic, TypeVar, Optional, Callable
+			from lark import Lark, Transformer
 			T = TypeVar('T')
 			class Thunk(Generic[T]):
+				''' A thunk represents a value that may be computed lazily. '''
+				value: Optional[T]
+				def __init__(self, func: Callable[[], T]):
+					self.func = func
+					self.value = None
+				def get(self) -> T:
+					if self.value is None:
+						self.value = self.func()
+					return self.value
+			parser = Lark('''{res.parser_data}''')
+			class Trans(Transformer[None]):
 				pass
-			parser = Lark('''{parser_data}''')
 		"""))
diff --git a/grammar.lark b/grammar.lark
index 4d02bbc..95fe0a3 100644
--- a/grammar.lark
+++ b/grammar.lark
@@ -8,7 +8,7 @@ sep_trail{item, punc}: item (punc item)? punc?
 iface: "iface" ident "{" sep_trail{iface_field, ","} "}"
 iface_field: ident ":" ident
 
-node: NODE ident ":" ident "{" variant* "}"
+node: "node" ident ":" ident "{" variant* "}"
 variant: prod "=>" "{" equation_* "}"
 prod: sym*
 sym: sym_rename
@@ -17,37 +17,23 @@ sym_rename: "<" ident ":" node_ref ">"
 node_ref: node_ref_name
 	| STRING
 node_ref_name: ident
-equation_: equation SEMI
-equation: expr EQ expr
+equation_: equation ";"
+equation: expr "=" expr
 
 expr: expr_dot
 	| expr_add
 	| expr_mul
 	| expr_call
 	| expr_name
-expr_dot: expr DOT expr
-expr_add: expr ADD expr
-expr_mul: expr MUL expr
-expr_call: expr LPAR args RPAR
+expr_dot: expr "." expr
+expr_add: expr "+" expr
+expr_mul: expr "*" expr
+expr_call: expr "(" args ")"
 expr_name: ident
-args: expr (COMMA expr)? COMMA?
+args: sep_trail{expr, ","}
 
 ident: IDENT
 IDENT: /([a-zA-Z][a-zA-Z0-9_]*)|(_[a-zA-Z0-9_]+)/
-IFACE: "iface"
-NODE: "node"
-LANG: "<"
-RANG: ">"
-ADD: "+"
-MUL: "*"
-COMMA: ","
-COLON: ":"
-LPAR: "("
-RPAR: ")"
-EQ: "="
-DOT: "."
-SEMI: ";"
-THICCARROW: "=>"
 
 %import python.STRING
 %import common.WS
diff --git a/watch.ps1 b/watch.ps1
index 2bcc73f..5d2498c 100644
--- a/watch.ps1
+++ b/watch.ps1
@@ -1 +1 @@
-watchexec --shell=powershell -ce py -i gen './run.ps1'
+watchexec --shell=powershell -ce py,lark -i gen './run.ps1'