tabs -> spaces
This commit is contained in:
parent
8c687c4d1c
commit
6e7563c84c
6 changed files with 304 additions and 304 deletions
220
agast.py
220
agast.py
|
@ -4,148 +4,148 @@ from lark import Transformer, Tree, Token
|
||||||
T = TypeVar("T")
|
T = TypeVar("T")
|
||||||
|
|
||||||
class Ast:
|
class Ast:
|
||||||
# def __new__(cls: Type[Ast], name: str, bases: Tuple[type], namespace: Dict[str, Any]) -> Ast:
|
# def __new__(cls: Type[Ast], name: str, bases: Tuple[type], namespace: Dict[str, Any]) -> Ast:
|
||||||
# x = super().__new__(cls, name, bases, namespace)
|
# x = super().__new__(cls, name, bases, namespace)
|
||||||
# x.id = cls.__gen()
|
# x.id = cls.__gen()
|
||||||
# return x
|
# return x
|
||||||
id: str
|
id: str
|
||||||
n = 0
|
n = 0
|
||||||
@classmethod
|
@classmethod
|
||||||
def __gen(cls, name: str = "") -> str:
|
def __gen(cls, name: str = "") -> str:
|
||||||
newid = cls.n
|
newid = cls.n
|
||||||
cls.n += 1
|
cls.n += 1
|
||||||
return f"_a{newid}{name}"
|
return f"_a{newid}{name}"
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.id = self.__gen()
|
self.id = self.__gen()
|
||||||
|
|
||||||
class Decl:
|
class Decl:
|
||||||
name: str
|
name: str
|
||||||
|
|
||||||
class IfaceRef(str): pass
|
class IfaceRef(str): pass
|
||||||
class IfaceField:
|
class IfaceField:
|
||||||
def __init__(self, name: str, ty: str):
|
def __init__(self, name: str, ty: str):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.ty = ty
|
self.ty = ty
|
||||||
class Iface(Decl):
|
class Iface(Decl):
|
||||||
def __init__(self, name: str, fields: List[IfaceField]):
|
def __init__(self, name: str, fields: List[IfaceField]):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.fields = fields
|
self.fields = fields
|
||||||
|
|
||||||
class Expr(Ast):
|
class Expr(Ast):
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
class NodeRef: pass
|
class NodeRef: pass
|
||||||
class NodeRefByName(NodeRef, str):
|
class NodeRefByName(NodeRef, str):
|
||||||
def __init__(self, name: str):
|
def __init__(self, name: str):
|
||||||
self.name = name
|
self.name = name
|
||||||
def __repr__(self) -> str: return f"NodeRefByName({self.name})"
|
def __repr__(self) -> str: return f"NodeRefByName({self.name})"
|
||||||
|
|
||||||
class Sym: pass
|
class Sym: pass
|
||||||
class SymRename(Sym):
|
class SymRename(Sym):
|
||||||
def __init__(self, name: str, ty: NodeRef):
|
def __init__(self, name: str, ty: NodeRef):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.ty = ty
|
self.ty = ty
|
||||||
def __repr__(self) -> str: return f"SymRename({self.name} : {self.ty})"
|
def __repr__(self) -> str: return f"SymRename({self.name} : {self.ty})"
|
||||||
class Equation:
|
class Equation:
|
||||||
def __init__(self, lhs: Expr, rhs: Expr):
|
def __init__(self, lhs: Expr, rhs: Expr):
|
||||||
self.lhs = lhs
|
self.lhs = lhs
|
||||||
self.rhs = rhs
|
self.rhs = rhs
|
||||||
def __repr__(self) -> str: return f"{self.lhs} = {self.rhs}"
|
def __repr__(self) -> str: return f"{self.lhs} = {self.rhs}"
|
||||||
|
|
||||||
class Variant:
|
class Variant:
|
||||||
def __init__(self, prod: List[Sym], equations: List[Equation]):
|
def __init__(self, prod: List[Sym], equations: List[Equation]):
|
||||||
self.prod = prod
|
self.prod = prod
|
||||||
self.equations = equations
|
self.equations = equations
|
||||||
def __repr__(self) -> str: return f"Variant({self.prod}, {self.equations})"
|
def __repr__(self) -> str: return f"Variant({self.prod}, {self.equations})"
|
||||||
|
|
||||||
class Node(Decl):
|
class Node(Decl):
|
||||||
def __init__(self, name: str, ifaces: List[IfaceRef], variants: List[Variant]):
|
def __init__(self, name: str, ifaces: List[IfaceRef], variants: List[Variant]):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.ifaces = ifaces
|
self.ifaces = ifaces
|
||||||
self.variants = variants
|
self.variants = variants
|
||||||
|
|
||||||
class ExprDot(Expr):
|
class ExprDot(Expr):
|
||||||
def __init__(self, left: Expr, right: str):
|
def __init__(self, left: Expr, right: str):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.left = left
|
self.left = left
|
||||||
self.right = right
|
self.right = right
|
||||||
def __repr__(self) -> str: return f"{self.left}.{self.right}"
|
def __repr__(self) -> str: return f"{self.left}.{self.right}"
|
||||||
class ExprAdd(Expr):
|
class ExprAdd(Expr):
|
||||||
def __init__(self, left: Expr, right: Expr):
|
def __init__(self, left: Expr, right: Expr):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.left = left
|
self.left = left
|
||||||
self.right = right
|
self.right = right
|
||||||
def __repr__(self) -> str: return f"{self.left} + {self.right}"
|
def __repr__(self) -> str: return f"{self.left} + {self.right}"
|
||||||
class ExprMul(Expr):
|
class ExprMul(Expr):
|
||||||
def __init__(self, left: Expr, right: Expr):
|
def __init__(self, left: Expr, right: Expr):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.left = left
|
self.left = left
|
||||||
self.right = right
|
self.right = right
|
||||||
def __repr__(self) -> str: return f"{self.left} * {self.right}"
|
def __repr__(self) -> str: return f"{self.left} * {self.right}"
|
||||||
class ExprCall(Expr):
|
class ExprCall(Expr):
|
||||||
def __init__(self, func: Expr, args: List[Expr]):
|
def __init__(self, func: Expr, args: List[Expr]):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.func = func
|
self.func = func
|
||||||
self.args = args
|
self.args = args
|
||||||
def __repr__(self) -> str: return f"{self.func}({self.args})"
|
def __repr__(self) -> str: return f"{self.func}({self.args})"
|
||||||
class ExprName(Expr):
|
class ExprName(Expr):
|
||||||
def __init__(self, name: str):
|
def __init__(self, name: str):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.name = name
|
self.name = name
|
||||||
def __repr__(self) -> str: return f"{self.name}"
|
def __repr__(self) -> str: return f"{self.name}"
|
||||||
|
|
||||||
class Parser(Transformer[List[Decl]]):
|
class Parser(Transformer[List[Decl]]):
|
||||||
def program(self, items: List[Decl]) -> List[Decl]: return items
|
def program(self, items: List[Decl]) -> List[Decl]: return items
|
||||||
|
|
||||||
# interfaces
|
# interfaces
|
||||||
def iface(self, items: List[Any]) -> Iface:
|
def iface(self, items: List[Any]) -> Iface:
|
||||||
[name, fields] = items
|
[name, fields] = items
|
||||||
return Iface(name, fields)
|
return Iface(name, fields)
|
||||||
def iface_field(self, items: List[str]) -> IfaceField:
|
def iface_field(self, items: List[str]) -> IfaceField:
|
||||||
[name, ty] = items
|
[name, ty] = items
|
||||||
return IfaceField(name, ty)
|
return IfaceField(name, ty)
|
||||||
def iface_ref(self, items: List[str]) -> str: return items[0]
|
def iface_ref(self, items: List[str]) -> str: return items[0]
|
||||||
def iface_refs(self, items: List[IfaceRef]) -> List[IfaceRef]: return items
|
def iface_refs(self, items: List[IfaceRef]) -> List[IfaceRef]: return items
|
||||||
|
|
||||||
# nodes
|
# nodes
|
||||||
def node(self, items: List[Any]) -> Node:
|
def node(self, items: List[Any]) -> Node:
|
||||||
[name, ifaces, variants] = items
|
[name, ifaces, variants] = items
|
||||||
return Node(name, ifaces, variants)
|
return Node(name, ifaces, variants)
|
||||||
def node_ref_name(self, items: List[str]) -> NodeRefByName: return NodeRefByName(items[0])
|
def node_ref_name(self, items: List[str]) -> NodeRefByName: return NodeRefByName(items[0])
|
||||||
|
|
||||||
# variants
|
# variants
|
||||||
def variants(self, items: List[Variant]) -> List[Variant]: return items
|
def variants(self, items: List[Variant]) -> List[Variant]: return items
|
||||||
def variant(self, items: List[Any]) -> Variant:
|
def variant(self, items: List[Any]) -> Variant:
|
||||||
[prod, equations] = items
|
[prod, equations] = items
|
||||||
return Variant(prod, equations)
|
return Variant(prod, equations)
|
||||||
def prod(self, items: List[Sym]) -> List[Sym]: return items
|
def prod(self, items: List[Sym]) -> List[Sym]: return items
|
||||||
|
|
||||||
def sym_rename(self, items: List[Any]) -> Sym: return SymRename(items[0], items[1])
|
def sym_rename(self, items: List[Any]) -> Sym: return SymRename(items[0], items[1])
|
||||||
|
|
||||||
# equations
|
# equations
|
||||||
def equations(self, items: List[Equation]) -> List[Equation]: return items
|
def equations(self, items: List[Equation]) -> List[Equation]: return items
|
||||||
def equation_semi(self, items: List[Equation]) -> Equation: return items[0]
|
def equation_semi(self, items: List[Equation]) -> Equation: return items[0]
|
||||||
def equation(self, items: List[Expr]) -> Equation: return Equation(items[0], items[1])
|
def equation(self, items: List[Expr]) -> Equation: return Equation(items[0], items[1])
|
||||||
|
|
||||||
# expr
|
# expr
|
||||||
def expr_dot(self, items: List[Any]) -> Expr:
|
def expr_dot(self, items: List[Any]) -> Expr:
|
||||||
[left, right] = items
|
[left, right] = items
|
||||||
return ExprDot(left, right)
|
return ExprDot(left, right)
|
||||||
def expr_add(self, items: List[Expr]) -> Expr:
|
def expr_add(self, items: List[Expr]) -> Expr:
|
||||||
[left, right] = items
|
[left, right] = items
|
||||||
return ExprAdd(left, right)
|
return ExprAdd(left, right)
|
||||||
def expr_mul(self, items: List[Expr]) -> Expr:
|
def expr_mul(self, items: List[Expr]) -> Expr:
|
||||||
[left, right] = items
|
[left, right] = items
|
||||||
return ExprMul(left, right)
|
return ExprMul(left, right)
|
||||||
def expr_call(self, items: List[Expr]) -> Expr:
|
def expr_call(self, items: List[Expr]) -> Expr:
|
||||||
[func, args] = items
|
[func, args] = items
|
||||||
# TODO: args should be a list of exprs -_ -
|
# TODO: args should be a list of exprs -_ -
|
||||||
return ExprCall(func, [args])
|
return ExprCall(func, [args])
|
||||||
def expr_name(self, items: List[str]) -> Expr:
|
def expr_name(self, items: List[str]) -> Expr:
|
||||||
return ExprName(items[0])
|
return ExprName(items[0])
|
||||||
|
|
||||||
def sep_trail(self, items: List[Tree]) -> List[T]:
|
def sep_trail(self, items: List[Tree]) -> List[T]:
|
||||||
return list(map(lambda it: cast(T, it), items))
|
return list(map(lambda it: cast(T, it), items))
|
||||||
|
|
||||||
def ident(self, items: List[Token]) -> str: return cast(str, items[0].value)
|
def ident(self, items: List[Token]) -> str: return cast(str, items[0].value)
|
||||||
|
|
228
aggen.py
228
aggen.py
|
@ -9,132 +9,132 @@ global i
|
||||||
i = 0
|
i = 0
|
||||||
|
|
||||||
class GenResult:
|
class GenResult:
|
||||||
def __init__(self, pd: str = "", ex: str = ""):
|
def __init__(self, pd: str = "", ex: str = ""):
|
||||||
self.parser_data = pd
|
self.parser_data = pd
|
||||||
self.extra = ex
|
self.extra = ex
|
||||||
|
|
||||||
def gen(program: List[Decl]) -> GenResult:
|
def gen(program: List[Decl]) -> GenResult:
|
||||||
res = GenResult()
|
res = GenResult()
|
||||||
def gen(prefix: str = "", suffix: str = "") -> str:
|
def gen(prefix: str = "", suffix: str = "") -> str:
|
||||||
global i
|
global i
|
||||||
presan = re.sub("[^0-9a-zA-Z]+", "_", prefix)
|
presan = re.sub("[^0-9a-zA-Z]+", "_", prefix)
|
||||||
sufsan = re.sub("[^0-9a-zA-Z]+", "_", suffix)
|
sufsan = re.sub("[^0-9a-zA-Z]+", "_", suffix)
|
||||||
i += 1
|
i += 1
|
||||||
return f"{presan}{i}{sufsan}"
|
return f"{presan}{i}{sufsan}"
|
||||||
def v(name: str) -> str:
|
def v(name: str) -> str:
|
||||||
return f"__ag_{name}"
|
return f"__ag_{name}"
|
||||||
|
|
||||||
# builtins
|
# builtins
|
||||||
builtins: Dict[str, str] = {
|
builtins: Dict[str, str] = {
|
||||||
"parseInt": "",
|
"parseInt": "",
|
||||||
}
|
}
|
||||||
|
|
||||||
# collect a list of name -> iface declarations
|
# collect a list of name -> iface declarations
|
||||||
ifaces: Dict[str, Iface] = dict(
|
ifaces: Dict[str, Iface] = dict(
|
||||||
map(lambda c: (c.name, cast(Iface, c)),
|
map(lambda c: (c.name, cast(Iface, c)),
|
||||||
filter(lambda c: isinstance(c, Iface),
|
filter(lambda c: isinstance(c, Iface),
|
||||||
program)))
|
program)))
|
||||||
|
|
||||||
# list of node -> iface mappings
|
# list of node -> iface mappings
|
||||||
what_ifaces: Dict[str, Set[str]] = dict()
|
what_ifaces: Dict[str, Set[str]] = dict()
|
||||||
what_fields: Dict[str, Dict[str, str]] = dict()
|
what_fields: Dict[str, Dict[str, str]] = dict()
|
||||||
for node in filter(lambda c: isinstance(c, Node), program):
|
for node in filter(lambda c: isinstance(c, Node), program):
|
||||||
node = cast(Node, node)
|
node = cast(Node, node)
|
||||||
# all_fields = dict()
|
# all_fields = dict()
|
||||||
what_ifaces[node.name] = set(node.ifaces)
|
what_ifaces[node.name] = set(node.ifaces)
|
||||||
this_fields = dict()
|
this_fields = dict()
|
||||||
for iface in node.ifaces:
|
for iface in node.ifaces:
|
||||||
fields = ifaces[iface].fields
|
fields = ifaces[iface].fields
|
||||||
for field in fields:
|
for field in fields:
|
||||||
if field.name in this_fields:
|
if field.name in this_fields:
|
||||||
raise Exception("duplicate field name")
|
raise Exception("duplicate field name")
|
||||||
this_fields[field.name] = field.ty
|
this_fields[field.name] = field.ty
|
||||||
what_fields[node.name] = this_fields
|
what_fields[node.name] = this_fields
|
||||||
print("what_ifaces:", what_ifaces)
|
print("what_ifaces:", what_ifaces)
|
||||||
print("what_fields:", what_fields)
|
print("what_fields:", what_fields)
|
||||||
|
|
||||||
# a high-level dictionary of productions; this has sub-productions
|
# a high-level dictionary of productions; this has sub-productions
|
||||||
# that should be further expanded at a later step before converting
|
# that should be further expanded at a later step before converting
|
||||||
# into lark code
|
# into lark code
|
||||||
productions_hi: Dict[str, Union[str, List[str]]] = dict()
|
productions_hi: Dict[str, Union[str, List[str]]] = dict()
|
||||||
|
|
||||||
# TODO: this should probably not be inlined here, but i'll move it
|
# TODO: this should probably not be inlined here, but i'll move it
|
||||||
# out once i get more info into the 'env'
|
# out once i get more info into the 'env'
|
||||||
def collect_required_thunks(env: List[Tuple[str, NodeRef]], expr: Expr) -> Dict[str, str]:
|
def collect_required_thunks(env: List[Tuple[str, NodeRef]], expr: Expr) -> Dict[str, str]:
|
||||||
names = dict(env)
|
names = dict(env)
|
||||||
print(f"collect_required_thunks({expr})", expr.__class__)
|
print(f"collect_required_thunks({expr})", expr.__class__)
|
||||||
if isinstance(expr, ExprDot):
|
if isinstance(expr, ExprDot):
|
||||||
return collect_required_thunks(env, expr.left)
|
return collect_required_thunks(env, expr.left)
|
||||||
elif isinstance(expr, ExprMul):
|
elif isinstance(expr, ExprMul):
|
||||||
a = collect_required_thunks(env, expr.left)
|
a = collect_required_thunks(env, expr.left)
|
||||||
b = collect_required_thunks(env, expr.right)
|
b = collect_required_thunks(env, expr.right)
|
||||||
a.update(b)
|
a.update(b)
|
||||||
return a
|
return a
|
||||||
elif isinstance(expr, ExprAdd):
|
elif isinstance(expr, ExprAdd):
|
||||||
a = collect_required_thunks(env, expr.left)
|
a = collect_required_thunks(env, expr.left)
|
||||||
b = collect_required_thunks(env, expr.right)
|
b = collect_required_thunks(env, expr.right)
|
||||||
a.update(b)
|
a.update(b)
|
||||||
return a
|
return a
|
||||||
elif isinstance(expr, ExprCall):
|
elif isinstance(expr, ExprCall):
|
||||||
return collect_required_thunks(env, expr.func)
|
return collect_required_thunks(env, expr.func)
|
||||||
elif isinstance(expr, ExprName):
|
elif isinstance(expr, ExprName):
|
||||||
if expr.name not in names and expr.name not in builtins:
|
if expr.name not in names and expr.name not in builtins:
|
||||||
raise Exception(f"unbound name '{expr.name}'")
|
raise Exception(f"unbound name '{expr.name}'")
|
||||||
return dict()
|
return dict()
|
||||||
raise Exception(f"unhandled {expr.__class__}")
|
raise Exception(f"unhandled {expr.__class__}")
|
||||||
|
|
||||||
for node in filter(lambda c: isinstance(c, Node), program):
|
for node in filter(lambda c: isinstance(c, Node), program):
|
||||||
node = cast(Node, node)
|
node = cast(Node, node)
|
||||||
n_class_name = gen(node.name)
|
n_class_name = gen(node.name)
|
||||||
class_decl = textwrap.dedent(f"""
|
class_decl = textwrap.dedent(f"""
|
||||||
class {v(n_class_name)}: pass
|
class {v(n_class_name)}: pass
|
||||||
""")
|
""")
|
||||||
res.extra += class_decl
|
res.extra += class_decl
|
||||||
|
|
||||||
print(node.name, node.ifaces)
|
print(node.name, node.ifaces)
|
||||||
|
|
||||||
for variant in node.variants:
|
for variant in node.variants:
|
||||||
v_class_name = gen(f"{n_class_name}_var")
|
v_class_name = gen(f"{n_class_name}_var")
|
||||||
class_decl = textwrap.dedent(f"""
|
class_decl = textwrap.dedent(f"""
|
||||||
class {v(v_class_name)}({v(n_class_name)}):
|
class {v(v_class_name)}({v(n_class_name)}):
|
||||||
''' '''
|
''' '''
|
||||||
pass
|
pass
|
||||||
""")
|
""")
|
||||||
res.extra += class_decl
|
res.extra += class_decl
|
||||||
|
|
||||||
prod_name = gen(node.name)
|
prod_name = gen(node.name)
|
||||||
print(prod_name)
|
print(prod_name)
|
||||||
|
|
||||||
# create an environment for checking the equations based on
|
# create an environment for checking the equations based on
|
||||||
# the production
|
# the production
|
||||||
env: List[Tuple[str, NodeRef]] = list()
|
env: List[Tuple[str, NodeRef]] = list()
|
||||||
for sym in variant.prod:
|
for sym in variant.prod:
|
||||||
if isinstance(sym, SymRename):
|
if isinstance(sym, SymRename):
|
||||||
env.append((sym.name, sym.ty))
|
env.append((sym.name, sym.ty))
|
||||||
print(env)
|
print(env)
|
||||||
|
|
||||||
# for each of the equations, find out what the equation is
|
# for each of the equations, find out what the equation is
|
||||||
# trying to compute, and generate a thunk corresponding to
|
# trying to compute, and generate a thunk corresponding to
|
||||||
# that value.
|
# that value.
|
||||||
for eq in variant.equations:
|
for eq in variant.equations:
|
||||||
eq_name = gen(f"eq_{node.name}")
|
eq_name = gen(f"eq_{node.name}")
|
||||||
thunk_name = gen(f"thunk_{node.name}")
|
thunk_name = gen(f"thunk_{node.name}")
|
||||||
|
|
||||||
print("RHS", eq.rhs, eq.rhs.id)
|
print("RHS", eq.rhs, eq.rhs.id)
|
||||||
collect_required_thunks(copy.deepcopy(env), eq.rhs)
|
collect_required_thunks(copy.deepcopy(env), eq.rhs)
|
||||||
|
|
||||||
func_impl = textwrap.dedent(f"""
|
func_impl = textwrap.dedent(f"""
|
||||||
def {eq_name}() -> None:
|
def {eq_name}() -> None:
|
||||||
''' {repr(eq)} '''
|
''' {repr(eq)} '''
|
||||||
pass
|
pass
|
||||||
def {thunk_name}() -> Thunk[None]:
|
def {thunk_name}() -> Thunk[None]:
|
||||||
return Thunk({eq_name})
|
return Thunk({eq_name})
|
||||||
""")
|
""")
|
||||||
print(f"```py\n{func_impl}\n```")
|
print(f"```py\n{func_impl}\n```")
|
||||||
res.extra += func_impl
|
res.extra += func_impl
|
||||||
|
|
||||||
# this is a "type alias" that connects it to one of the generated
|
# this is a "type alias" that connects it to one of the generated
|
||||||
# names above
|
# names above
|
||||||
res.extra += f"{node.name} = {v(n_class_name)}"
|
res.extra += f"{node.name} = {v(n_class_name)}"
|
||||||
|
|
||||||
return res
|
return res
|
78
agmain.py
78
agmain.py
|
@ -9,47 +9,47 @@ from aggen import *
|
||||||
p = Lark(open("grammar.lark").read(), start="program", parser="lalr")
|
p = Lark(open("grammar.lark").read(), start="program", parser="lalr")
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
with open("arith.ag") as f:
|
with open("arith.ag") as f:
|
||||||
data = f.read()
|
data = f.read()
|
||||||
|
|
||||||
cst = p.parse(data)
|
cst = p.parse(data)
|
||||||
|
|
||||||
trans = Parser()
|
trans = Parser()
|
||||||
ast = trans.transform(cst)
|
ast = trans.transform(cst)
|
||||||
print("ast", ast)
|
print("ast", ast)
|
||||||
|
|
||||||
res = gen(ast)
|
res = gen(ast)
|
||||||
|
|
||||||
if not os.path.exists("gen"):
|
if not os.path.exists("gen"):
|
||||||
os.makedirs("gen")
|
os.makedirs("gen")
|
||||||
with open("gen/arith.py", "w") as f:
|
with open("gen/arith.py", "w") as f:
|
||||||
fmt_str = textwrap.dedent("""
|
fmt_str = textwrap.dedent("""
|
||||||
__all__ = ["parse"]
|
__all__ = ["parse"]
|
||||||
from typing import Generic, TypeVar, Optional, Callable, Dict, Any
|
from typing import Generic, TypeVar, Optional, Callable, Dict, Any
|
||||||
from lark import Lark, Transformer
|
from lark import Lark, Transformer
|
||||||
T = TypeVar('T')
|
T = TypeVar('T')
|
||||||
builtins: Dict[str, Any] = {{
|
builtins: Dict[str, Any] = {{
|
||||||
"parseInt": lambda s: int(s)
|
"parseInt": lambda s: int(s)
|
||||||
}}
|
}}
|
||||||
class Thunk(Generic[T]):
|
class Thunk(Generic[T]):
|
||||||
''' A thunk represents a value that may be computed lazily. '''
|
''' A thunk represents a value that may be computed lazily. '''
|
||||||
value: Optional[T]
|
value: Optional[T]
|
||||||
def __init__(self, func: Callable[[], T]):
|
def __init__(self, func: Callable[[], T]):
|
||||||
self.func = func
|
self.func = func
|
||||||
self.value = None
|
self.value = None
|
||||||
def get(self) -> T:
|
def get(self) -> T:
|
||||||
if self.value is None:
|
if self.value is None:
|
||||||
self.value = self.func()
|
self.value = self.func()
|
||||||
return self.value
|
return self.value
|
||||||
parser = Lark('''start:
|
parser = Lark('''start:
|
||||||
{pd}''')
|
{pd}''')
|
||||||
class Trans(Transformer[None]):
|
class Trans(Transformer[None]):
|
||||||
pass
|
pass
|
||||||
{ex}
|
{ex}
|
||||||
def parse(input: str) -> None:
|
def parse(input: str) -> None:
|
||||||
print(input)
|
print(input)
|
||||||
""")
|
""")
|
||||||
f.write(fmt_str.format(pd=res.parser_data, ex=res.extra))
|
f.write(fmt_str.format(pd=res.parser_data, ex=res.extra))
|
||||||
|
|
||||||
mod = importlib.import_module("gen.arith")
|
mod = importlib.import_module("gen.arith")
|
||||||
mod.parse("1 + 2 * 3") # type: ignore
|
mod.parse("1 + 2 * 3") # type: ignore
|
||||||
|
|
16
arith.ag
16
arith.ag
|
@ -1,13 +1,13 @@
|
||||||
iface HasValue {
|
iface HasValue {
|
||||||
val: int,
|
val: int,
|
||||||
}
|
}
|
||||||
|
|
||||||
node Expr : HasValue {
|
node Expr : HasValue {
|
||||||
<l:Expr> "+" <r:Expr> => {
|
<l:Expr> "+" <r:Expr> => {
|
||||||
self.val = l.val + r.val * l.val;
|
self.val = l.val + r.val * l.val;
|
||||||
}
|
}
|
||||||
<l:Expr> "*" <r:Expr> => {
|
<l:Expr> "*" <r:Expr> => {
|
||||||
self.val = l.val * r.val;
|
self.val = l.val * r.val;
|
||||||
}
|
}
|
||||||
<n:r"[0-9]+"> => { self.val = parseInt(n); }
|
<n:r"[0-9]+"> => { self.val = parseInt(n); }
|
||||||
}
|
}
|
||||||
|
|
30
let.ag
30
let.ag
|
@ -1,25 +1,25 @@
|
||||||
iface HasEnv {
|
iface HasEnv {
|
||||||
env: Map<str, str>,
|
env: Map<str, str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
iface HasVal {
|
iface HasVal {
|
||||||
val: str,
|
val: str,
|
||||||
}
|
}
|
||||||
|
|
||||||
alias Ident = /([a-zA-Z][a-zA-Z0-9_]*)|(_[a-zA-Z0-9_]+)/
|
alias Ident = /([a-zA-Z][a-zA-Z0-9_]*)|(_[a-zA-Z0-9_]+)/
|
||||||
|
|
||||||
node Expr : HasEnv + HasVal {
|
node Expr : HasEnv + HasVal {
|
||||||
"let" <name:Ident> "=" <val:Expr> "in" <body:Expr> => {
|
"let" <name:Ident> "=" <val:Expr> "in" <body:Expr> => {
|
||||||
body.env = self.env.with(name, val);
|
body.env = self.env.with(name, val);
|
||||||
self.val = body.val;
|
self.val = body.val;
|
||||||
}
|
}
|
||||||
<name:Ident> => {
|
<name:Ident> => {
|
||||||
// TODO: does env need to be referenced here?
|
// TODO: does env need to be referenced here?
|
||||||
// TODO: how to check for unbound names ahead of time
|
// TODO: how to check for unbound names ahead of time
|
||||||
// (for self-implementation)
|
// (for self-implementation)
|
||||||
self.val = self.env.lookup(name);
|
self.val = self.env.lookup(name);
|
||||||
}
|
}
|
||||||
<string:StringLit> => {
|
<string:StringLit> => {
|
||||||
self.val = string;
|
self.val = string;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
36
old.py
36
old.py
|
@ -3,33 +3,33 @@ from typing import Generic, TypeVar, Optional, Callable
|
||||||
T = TypeVar("T")
|
T = TypeVar("T")
|
||||||
|
|
||||||
class Thunk(Generic[T]):
|
class Thunk(Generic[T]):
|
||||||
value: Optional[T]
|
value: Optional[T]
|
||||||
|
|
||||||
def __init__(self, func: Callable[[], T]):
|
def __init__(self, func: Callable[[], T]):
|
||||||
self.func = func
|
self.func = func
|
||||||
self.value = None
|
self.value = None
|
||||||
|
|
||||||
def get(self) -> T:
|
def get(self) -> T:
|
||||||
if self.value is None:
|
if self.value is None:
|
||||||
self.value = self.func()
|
self.value = self.func()
|
||||||
return self.value
|
return self.value
|
||||||
|
|
||||||
class Node:
|
class Node:
|
||||||
value: Thunk[int]
|
value: Thunk[int]
|
||||||
|
|
||||||
class Add(Node):
|
class Add(Node):
|
||||||
def __init__(self, left: Node, right: Node):
|
def __init__(self, left: Node, right: Node):
|
||||||
self.value = Thunk(lambda: left.value.get() + right.value.get())
|
self.value = Thunk(lambda: left.value.get() + right.value.get())
|
||||||
|
|
||||||
class Mul(Node):
|
class Mul(Node):
|
||||||
def __init__(self, left: Node, right: Node):
|
def __init__(self, left: Node, right: Node):
|
||||||
self.value = Thunk(lambda: left.value.get() * right.value.get())
|
self.value = Thunk(lambda: left.value.get() * right.value.get())
|
||||||
|
|
||||||
class Lit(Node):
|
class Lit(Node):
|
||||||
def __init__(self, num: int):
|
def __init__(self, num: int):
|
||||||
self.num = num
|
self.num = num
|
||||||
self.value = Thunk(lambda: num)
|
self.value = Thunk(lambda: num)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
tree = Add(Mul(Lit(3), Lit(4)), Lit(5))
|
tree = Add(Mul(Lit(3), Lit(4)), Lit(5))
|
||||||
print(tree.value.get())
|
print(tree.value.get())
|
||||||
|
|
Loading…
Add table
Reference in a new issue