Add a repl

This commit is contained in:
Emi Simpson 2023-03-08 11:50:03 -05:00
parent 0383bc5b82
commit 224ec0bc98
Signed by: Emi
GPG Key ID: A12F2C2FFDC3D847
4 changed files with 45 additions and 10 deletions

View File

@ -1,9 +1,8 @@
from emis_funky_funktions import *
from typing import *
from silly_thing import *
from pattern import lex_and_parse_pattern
from ir import Function, Application, Int, Variable, LetBinding, Unit
from ir import Expression, Function, Application, Int, Variable, LetBinding, ReplHole
import json
@ -23,7 +22,7 @@ def json_to_ir(j: JsonType) -> Expression:
case [first, *rest]:
return Application(json_to_ir(first), [json_to_ir(a) for a in rest])
case []:
return Unit()
return ReplHole()
raise Exception('Unreachable')
else:
return Int(j)

10
ir.py
View File

@ -3,7 +3,7 @@ from emis_funky_funktions import *
from typing import Mapping, Sequence, Tuple, TypeAlias
Expression: TypeAlias = 'Function | Application | Int | Variable | Builtin | LetBinding | Unit'
Expression: TypeAlias = 'Function | Application | Int | Variable | Builtin | LetBinding | ReplHole'
Pattern: TypeAlias = 'NamePattern | IntPattern | SPattern | IgnorePattern'
@dataclass(frozen=True)
@ -119,9 +119,11 @@ class SPattern:
return 'S ' + repr(self.pred)
@dataclass(frozen=True)
class Unit:
class ReplHole:
bindings: Sequence[Tuple[str, Expression]] = tuple()
def subst(self, expression: Expression, variable: str) -> Expression:
return self
return ReplHole((*self.bindings, (variable, expression)))
def is_value(self) -> bool:
return True
@ -280,7 +282,7 @@ class Application:
body = rest
match body:
case []:
return Some(Unit())
return Some(ReplHole())
case [body_first, *body_rest]:
return Some(LetBinding(lhs, rhs, Application(body_first, body_rest)))
else:

12
main.py
View File

@ -1,8 +1,16 @@
from emis_funky_funktions import *
from genir import json_to_ir
from silly_thing import evaluate
from silly_thing import repl, repl_expr
import json, sys
print(evaluate(json_to_ir(json.loads(open(sys.argv[1]).read()))))
def main():
match sys.argv:
case [_, file]:
repl_expr(json_to_ir(json.loads(open(sys.argv[1]).read())))
case _:
repl()
if __name__ == '__main__':
main()

View File

@ -1,8 +1,10 @@
from emis_funky_funktions import *
from typing import Collection, Sequence, TypeAlias
from ir import Expression
from ir import Expression, ReplHole, subst_all
from genir import json_to_ir
import json
from dataclasses import dataclass
from operator import add
@ -35,6 +37,30 @@ def evaluate(expr: Expression) -> Expression:
raise AssertionError('Evaluate called on a value which cannot step:', expr)
raise Exception('Unreachable')
def repl_expr(expr: Expression, bindings: Sequence[Tuple[str, Expression]] = tuple()):
expr_subst = subst_all(bindings, expr)
result = evaluate(expr_subst)
if isinstance(result, ReplHole):
print('Environment updated\n')
repl(result.bindings)
else:
print(result, end='\n\n')
repl(bindings)
def repl(bindings: Sequence[Tuple[str, Expression]] = tuple()):
print('Enter a JSON expression:')
try:
expr = input('-> ')
except EOFError:
print('<exit>')
return
try:
ast = json.loads(expr)
except json.decoder.JSONDecodeError as e:
print(f'Bad json: ', e.args[0], end='\n\n')
return repl(bindings)
repl_expr(json_to_ir(ast), bindings)
if __name__ == '__main__':
import doctest
doctest.testmod()