This commit is contained in:
Michael Zhang 2021-06-08 19:56:30 -05:00
commit 323c7a6282
Signed by: michael
GPG Key ID: BDA47A31A3C8EE6B
7 changed files with 120 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
.mypy_cache
gen/

2
Justfile Normal file
View File

@ -0,0 +1,2 @@
watch:
watchexec -ce py -i gen 'mypy *.py && python gen.py && mypy gen/*.py'

13
arith.ag Normal file
View File

@ -0,0 +1,13 @@
iface Node {
val: int,
}
node Expr : Node {
<l:Expr> "+" <r:Expr> => {
self.val = l.val + r.val;
}
<l:Expr> "*" <r:Expr> => {
self.val = l.val * r.val;
}
<n:r"[0-9]+"> => { self.val = parseInt(n); }
}

22
gen.py Normal file
View File

@ -0,0 +1,22 @@
import textwrap
import os
from lark import Lark
p = Lark(open("grammar.lark").read())
if __name__ == "__main__":
with open("arith.ag") as f:
data = f.read()
t = p.parse(data)
print(t)
if not os.path.exists("gen"):
os.makedirs("gen")
with open("gen/arith.py", "w") as f:
f.write(textwrap.dedent("""
from typing import Generic, TypeVar
T = TypeVar('T')
class Thunk(Generic[T]):
pass
"""))

44
grammar.lark Normal file
View File

@ -0,0 +1,44 @@
start: decl*
decl: iface
| node
iface: IFACE IDENT "{" iface_field (COMMA iface_field)? COMMA? "}"
iface_field: IDENT COLON IDENT
node: NODE IDENT COLON IDENT "{" node_prod* "}"
node_prod: prod THICCARROW "{" (equation SEMI)* "}"
prod: sym*
sym: IDENT
| LANG IDENT COLON node_ref RANG
| STRING
node_ref: IDENT
| STRING
equation: expr EQ expr
expr: expr DOT expr
| expr ADD expr
| expr MUL expr
| expr LPAR args RPAR
| IDENT
args: expr (COMMA expr)? COMMA?
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
%ignore WS

35
main.py Normal file
View File

@ -0,0 +1,35 @@
from typing import Generic, TypeVar, Optional, Callable
T = TypeVar("T")
class Thunk(Generic[T]):
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
class Node:
value: Thunk[int]
class Add(Node):
def __init__(self, left: Node, right: Node):
self.value = Thunk(lambda: left.value.get() + right.value.get())
class Mul(Node):
def __init__(self, left: Node, right: Node):
self.value = Thunk(lambda: left.value.get() * right.value.get())
class Lit(Node):
def __init__(self, num: int):
self.num = num
self.value = Thunk(lambda: num)
if __name__ == "__main__":
tree = Add(Mul(Lit(3), Lit(4)), Lit(5))
print(tree.value.get())

2
mypy.ini Normal file
View File

@ -0,0 +1,2 @@
[mypy]
strict = True