Add let statements
This commit is contained in:
parent
c27852daba
commit
a49b7b5baf
9
genir.py
9
genir.py
|
@ -3,7 +3,7 @@ from typing import *
|
||||||
|
|
||||||
from silly_thing import *
|
from silly_thing import *
|
||||||
from pattern import lex_and_parse_pattern
|
from pattern import lex_and_parse_pattern
|
||||||
from ir import Function, Application, Int, Variable
|
from ir import Function, Application, Int, Variable, LetBinding, Unit
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
@ -19,6 +19,11 @@ def json_to_ir(j: JsonType) -> Expression:
|
||||||
elif isinstance(j, str):
|
elif isinstance(j, str):
|
||||||
return Variable(j)
|
return Variable(j)
|
||||||
elif isinstance(j, Sequence):
|
elif isinstance(j, Sequence):
|
||||||
return Application([json_to_ir(e) for e in j])
|
match j:
|
||||||
|
case [first, *rest]:
|
||||||
|
return Application(json_to_ir(first), [json_to_ir(a) for a in rest])
|
||||||
|
case []:
|
||||||
|
return Unit()
|
||||||
|
raise Exception('Unreachable')
|
||||||
else:
|
else:
|
||||||
return Int(j)
|
return Int(j)
|
116
ir.py
116
ir.py
|
@ -3,7 +3,7 @@ from emis_funky_funktions import *
|
||||||
from typing import Mapping, Sequence, Tuple, TypeAlias
|
from typing import Mapping, Sequence, Tuple, TypeAlias
|
||||||
|
|
||||||
|
|
||||||
Expression: TypeAlias = 'Function | Application | Int | Variable | Builtin'
|
Expression: TypeAlias = 'Function | Application | Int | Variable | Builtin | LetBinding | Unit'
|
||||||
Pattern: TypeAlias = 'NamePattern | IntPattern | SPattern | IgnorePattern'
|
Pattern: TypeAlias = 'NamePattern | IntPattern | SPattern | IgnorePattern'
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
|
@ -118,6 +118,20 @@ class SPattern:
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return 'S ' + repr(self.pred)
|
return 'S ' + repr(self.pred)
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class Unit:
|
||||||
|
def subst(self, expression: Expression, variable: str) -> Expression:
|
||||||
|
return self
|
||||||
|
|
||||||
|
def is_value(self) -> bool:
|
||||||
|
return True
|
||||||
|
|
||||||
|
def step(self) -> Option[Expression]:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def __repr__(self) -> str:
|
||||||
|
return "[]"
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
class Builtin:
|
class Builtin:
|
||||||
name: str
|
name: str
|
||||||
|
@ -189,48 +203,92 @@ class Function:
|
||||||
return '{ ' + ', '.join('"' + repr(repr(p))[1:-1] + '" : ' + repr(e) for (p, e) in self.forms) + ' }'
|
return '{ ' + ', '.join('"' + repr(repr(p))[1:-1] + '" : ' + repr(e) for (p, e) in self.forms) + ' }'
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Application:
|
class LetBinding:
|
||||||
expressions: Sequence[Expression]
|
lhs: str
|
||||||
|
rhs: Expression
|
||||||
|
body: Expression
|
||||||
|
|
||||||
def subst(self, expression: Expression, variable: str) -> Expression:
|
def subst(self, expression: Expression, variable: str) -> Expression:
|
||||||
return Application([
|
if self.lhs == variable:
|
||||||
e.subst(expression, variable)
|
return self
|
||||||
for e in self.expressions
|
else:
|
||||||
])
|
return LetBinding(
|
||||||
|
self.lhs,
|
||||||
|
self.rhs.subst(expression, variable),
|
||||||
|
self.body.subst(expression, variable)
|
||||||
|
)
|
||||||
|
|
||||||
def is_value(self) -> bool:
|
def is_value(self) -> bool:
|
||||||
return not len(self.expressions)
|
return False
|
||||||
|
|
||||||
def step(self) -> Option[Expression]:
|
def step(self) -> Option[Expression]:
|
||||||
match self.expressions:
|
if self.rhs.is_value():
|
||||||
|
return Some(self.body.subst(
|
||||||
|
self.rhs.subst(
|
||||||
|
LetBinding(self.lhs, self.rhs, Variable(self.lhs)),
|
||||||
|
self.lhs
|
||||||
|
),
|
||||||
|
self.lhs
|
||||||
|
))
|
||||||
|
else:
|
||||||
|
return map_opt(lambda rhs_step:
|
||||||
|
LetBinding(self.lhs, rhs_step, self.body),
|
||||||
|
self.rhs.step()
|
||||||
|
)
|
||||||
|
|
||||||
|
def __repr__(self) -> str:
|
||||||
|
if isinstance(self.body, LetBinding) or isinstance(self.body, Application):
|
||||||
|
return f'L[ {repr(self.lhs)}, {repr(self.rhs)},{repr(self.body)[1:-1]}]'
|
||||||
|
else:
|
||||||
|
return f'L[ {repr(self.lhs)}, {repr(self.rhs)}, {repr(self.body)}]'
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Application:
|
||||||
|
first: Expression
|
||||||
|
args: Sequence[Expression]
|
||||||
|
|
||||||
|
def subst(self, expression: Expression, variable: str) -> Expression:
|
||||||
|
return Application(
|
||||||
|
self.first.subst(expression, variable),
|
||||||
|
[r.subst(expression, variable) for r in self.args]
|
||||||
|
)
|
||||||
|
|
||||||
|
def is_value(self) -> bool:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def step(self) -> Option[Expression]:
|
||||||
|
match self.args:
|
||||||
case []:
|
case []:
|
||||||
return None
|
return Some(self.first)
|
||||||
case [e]:
|
case [a, *rest]:
|
||||||
return Some(e)
|
match self.first.step():
|
||||||
case [f, a, *rest]:
|
case Some(first_stepped):
|
||||||
if f.is_value():
|
return Some(Application(first_stepped, self.args))
|
||||||
if a.is_value():
|
case None:
|
||||||
if isinstance(f, Function) or isinstance(f, Builtin):
|
match a.step():
|
||||||
|
case Some(a_stepped):
|
||||||
|
return Some(Application(self.first, [a_stepped, *rest]))
|
||||||
|
case None:
|
||||||
|
if isinstance(self.first, Function) or isinstance(self.first, Builtin):
|
||||||
return map_opt(
|
return map_opt(
|
||||||
lambda maybe_f_sub: Application([maybe_f_sub, *rest]),
|
lambda f_sub: Application(f_sub, rest),
|
||||||
f.try_apply(a)
|
self.first.try_apply(a)
|
||||||
)
|
)
|
||||||
|
elif isinstance(self.first, Variable):
|
||||||
|
lhs = self.first.name
|
||||||
|
rhs = a
|
||||||
|
body = rest
|
||||||
|
match body:
|
||||||
|
case []:
|
||||||
|
return Some(Unit())
|
||||||
|
case [body_first, *body_rest]:
|
||||||
|
return Some(LetBinding(lhs, rhs, Application(body_first, body_rest)))
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
else:
|
|
||||||
return map_opt(
|
|
||||||
lambda next_a: Application([f, next_a, *rest]),
|
|
||||||
a.step()
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
return map_opt(
|
|
||||||
lambda next_f: Application([next_f, a, *rest]),
|
|
||||||
f.step()
|
|
||||||
)
|
|
||||||
raise Exception('Unreachable')
|
raise Exception('Unreachable')
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return '[ ' + ', '.join(repr(e) for e in self.expressions) + ' ]'
|
return f'[ {repr(self.first)}, ' + ', '.join(repr(e) for e in self.args) + ' ]'
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Int:
|
class Int:
|
||||||
|
|
Loading…
Reference in a new issue