agtest/agtypeck.py
2021-06-09 02:44:52 -05:00

85 lines
2.2 KiB
Python

from typing import *
import textwrap
import re
from agast import *
global i
i = 0
class TypecheckResult:
def __init__(self, pd: str = "", ex: str = ""):
self.parser_data = pd
self.extra = ex
def typecheck(program: List[Decl]) -> TypecheckResult:
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}"
# 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)
# 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):
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)}"
return res