2021-06-09 06:33:53 +00:00
|
|
|
from typing import *
|
2021-06-09 07:44:52 +00:00
|
|
|
import textwrap
|
|
|
|
import re
|
2021-06-09 06:33:53 +00:00
|
|
|
from agast import *
|
|
|
|
|
2021-06-09 07:44:52 +00:00
|
|
|
global i
|
|
|
|
i = 0
|
|
|
|
|
2021-06-09 06:48:34 +00:00
|
|
|
class TypecheckResult:
|
2021-06-09 07:44:52 +00:00
|
|
|
def __init__(self, pd: str = "", ex: str = ""):
|
2021-06-09 06:48:34 +00:00
|
|
|
self.parser_data = pd
|
2021-06-09 07:44:52 +00:00
|
|
|
self.extra = ex
|
2021-06-09 06:48:34 +00:00
|
|
|
|
|
|
|
def typecheck(program: List[Decl]) -> TypecheckResult:
|
2021-06-09 07:44:52 +00:00
|
|
|
res = TypecheckResult()
|
|
|
|
def gen(prefix: str = "", suffix: str = "") -> str:
|
|
|
|
global i
|
|
|
|
presan = re.sub("[^0-9a-zA-Z]+", "_", prefix)
|
|
|
|
sufsan = re.sub("[^0-9a-zA-Z]+", "_", suffix)
|
|
|
|
i += 1
|
|
|
|
return f"{presan}{i}{sufsan}"
|
|
|
|
def v(name: str) -> str:
|
|
|
|
return f"__ag_{name}"
|
2021-06-09 06:33:53 +00:00
|
|
|
|
|
|
|
# collect a list of name -> iface declarations
|
|
|
|
ifaces: Dict[str, Decl] = dict(
|
|
|
|
map(lambda c: (c.name, c),
|
|
|
|
filter(lambda c: isinstance(c, Iface),
|
|
|
|
program)))
|
|
|
|
print(ifaces)
|
|
|
|
|
2021-06-09 06:48:34 +00:00
|
|
|
# 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()
|
|
|
|
|
2021-06-09 06:33:53 +00:00
|
|
|
for node in filter(lambda c: isinstance(c, Node), program):
|
2021-06-09 07:44:52 +00:00
|
|
|
node = cast(Node, node)
|
|
|
|
n_class_name = gen(node.name)
|
|
|
|
class_decl = textwrap.dedent(f"""
|
|
|
|
class {v(n_class_name)}: pass
|
|
|
|
""")
|
|
|
|
res.extra += class_decl
|
|
|
|
|
|
|
|
print(node.name, node.ifaces)
|
|
|
|
|
|
|
|
for variant in node.variants:
|
|
|
|
v_class_name = gen(f"{n_class_name}_var")
|
|
|
|
class_decl = textwrap.dedent(f"""
|
|
|
|
class {v(v_class_name)}({v(n_class_name)}):
|
|
|
|
''' '''
|
|
|
|
pass
|
|
|
|
""")
|
|
|
|
res.extra += class_decl
|
|
|
|
|
|
|
|
prod_name = gen(node.name)
|
|
|
|
print(prod_name)
|
|
|
|
|
|
|
|
for sym in variant.prod:
|
|
|
|
print("sym", sym)
|
|
|
|
|
|
|
|
# for each of the equations, find out what the equation is
|
|
|
|
# trying to compute, and generate a thunk corresponding to
|
|
|
|
# that value.
|
|
|
|
for eq in variant.equations:
|
|
|
|
print("--eq", eq)
|
|
|
|
print(eq.lhs)
|
|
|
|
eq_name = gen(f"eq_{node.name}")
|
|
|
|
thunk_name = gen(f"thunk_{node.name}")
|
|
|
|
|
|
|
|
func_impl = textwrap.dedent(f"""
|
|
|
|
def {eq_name}() -> None:
|
|
|
|
''' {repr(eq)} '''
|
|
|
|
pass
|
|
|
|
def {thunk_name}() -> Thunk[None]:
|
|
|
|
return Thunk({eq_name})
|
|
|
|
""")
|
|
|
|
print(f"```py\n{func_impl}\n```")
|
|
|
|
res.extra += func_impl
|
|
|
|
|
|
|
|
# this is a "type alias" that connects it to one of the generated
|
|
|
|
# names above
|
|
|
|
res.extra += f"{node.name} = {v(n_class_name)}"
|
2021-06-09 06:48:34 +00:00
|
|
|
|
2021-06-09 07:44:52 +00:00
|
|
|
return res
|