Compare commits
6 Commits
482547fea9
...
23ef1f1228
Author | SHA1 | Date |
---|---|---|
Emi Simpson | 23ef1f1228 | |
Emi Simpson | 6a598e3856 | |
Emi Simpson | 2479dbd9a6 | |
Emi Simpson | 67a7bbc821 | |
Emi Simpson | a673db77ca | |
Emi Simpson | 656b44e18f |
|
@ -135,14 +135,6 @@ aka a let binding without an "in" clause
|
||||||
["addTwo", {"x": ["S", ["S", "x"]]}]
|
["addTwo", {"x": ["S", ["S", "x"]]}]
|
||||||
```
|
```
|
||||||
|
|
||||||
### Execute REPL within context
|
|
||||||
|
|
||||||
(this is still a bit buggy, and may create an invalid REPL)
|
|
||||||
|
|
||||||
```json
|
|
||||||
[{"x": []}, 12]
|
|
||||||
```
|
|
||||||
|
|
||||||
### Multi-argument functions
|
### Multi-argument functions
|
||||||
|
|
||||||
```json
|
```json
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
[
|
[
|
||||||
"fibb",
|
"slow_fibb",
|
||||||
|
{
|
||||||
|
"0": 0,
|
||||||
|
"1": 1,
|
||||||
|
"n": ["+", ["slow_fibb", ["+", "n", -2]], ["slow_fibb", ["+", "n", -1]]]
|
||||||
|
},
|
||||||
|
|
||||||
|
"fast_fibb",
|
||||||
[
|
[
|
||||||
"fibb_helper",
|
"fibb_helper",
|
||||||
{
|
{
|
||||||
|
|
18
ir.py
18
ir.py
|
@ -11,6 +11,12 @@ import types_
|
||||||
Expression: TypeAlias = 'MonoFunc | Application | Int | Variable | Builtin | LetBinding | ReplHole | Switch'
|
Expression: TypeAlias = 'MonoFunc | Application | Int | Variable | Builtin | LetBinding | ReplHole | Switch'
|
||||||
Value: TypeAlias = 'MonoFunc | Int | Builtin | ReplHole'
|
Value: TypeAlias = 'MonoFunc | Int | Builtin | ReplHole'
|
||||||
|
|
||||||
|
dollar_count: int = 0
|
||||||
|
def mk_dollar() -> str:
|
||||||
|
global dollar_count
|
||||||
|
dollar_count += 1
|
||||||
|
return f'${dollar_count-1}'
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
class ReplHole:
|
class ReplHole:
|
||||||
typ_bindings: types_.Context
|
typ_bindings: types_.Context
|
||||||
|
@ -34,7 +40,7 @@ class ReplHole:
|
||||||
def render(self) -> str:
|
def render(self) -> str:
|
||||||
return '\n'.join(
|
return '\n'.join(
|
||||||
f'const {var_name} = ({var_expr.codegen()});'
|
f'const {var_name} = ({var_expr.codegen()});'
|
||||||
for (var_name, var_expr) in self.val_bindings
|
for (var_name, var_expr) in self.val_bindings[::-1]
|
||||||
if var_name not in types_.BUILTINS_CONTEXT
|
if var_name not in types_.BUILTINS_CONTEXT
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -120,18 +126,20 @@ class MonoFunc:
|
||||||
case [(var, [])]: # Binds a single variable to the entire input
|
case [(var, [])]: # Binds a single variable to the entire input
|
||||||
return Ok(MonoFunc(var, body))
|
return Ok(MonoFunc(var, body))
|
||||||
|
|
||||||
|
local_variable = mk_dollar()
|
||||||
|
|
||||||
# If those special cases fail, we eliminate the pattern matching to produce a
|
# If those special cases fail, we eliminate the pattern matching to produce a
|
||||||
# single body:
|
# single body:
|
||||||
match_trees = tuple( # Construct a match tree for each possible branch
|
match_trees = tuple( # Construct a match tree for each possible branch
|
||||||
pattern.match_tree(
|
pattern.match_tree(
|
||||||
EMPTY_STRUCT_PATH,
|
EMPTY_STRUCT_PATH,
|
||||||
LeafNode.from_value(bindings_to_lets(pattern.bindings(), Variable('$'), body))
|
LeafNode.from_value(bindings_to_lets(pattern.bindings(), Variable(local_variable), body))
|
||||||
)
|
)
|
||||||
for (pattern, body) in forms
|
for (pattern, body) in forms
|
||||||
)
|
)
|
||||||
unified_match_tree = merge_all_trees(match_trees) # Unify all the trees
|
unified_match_tree = merge_all_trees(match_trees) # Unify all the trees
|
||||||
compiled_tree = compile_tree(unified_match_tree, Variable('$')) # Turn each tree into IR
|
compiled_tree = compile_tree(unified_match_tree, Variable(local_variable)) # Turn each tree into IR
|
||||||
return compiled_tree <= p(MonoFunc, '$')
|
return compiled_tree <= p(MonoFunc, local_variable)
|
||||||
|
|
||||||
def try_apply(self, v: Expression) -> Option[Expression]:
|
def try_apply(self, v: Expression) -> Option[Expression]:
|
||||||
return Some(self.body.subst(v, self.arg))
|
return Some(self.body.subst(v, self.arg))
|
||||||
|
@ -222,7 +230,7 @@ class Application:
|
||||||
return unwrap_opt(self.first.try_apply(self.arg)).codegen()
|
return unwrap_opt(self.first.try_apply(self.arg)).codegen()
|
||||||
else:
|
else:
|
||||||
match self.first:
|
match self.first:
|
||||||
case Application(Builtin(Builtin.BB_PLUS), addend1):
|
case Application(Builtin(Builtin.BB_PLUS()), addend1):
|
||||||
return f'({addend1.codegen()} + {self.arg.codegen()})'
|
return f'({addend1.codegen()} + {self.arg.codegen()})'
|
||||||
case Builtin(Builtin.BB_PLUS_CONST(n)):
|
case Builtin(Builtin.BB_PLUS_CONST(n)):
|
||||||
return f'({self.arg.codegen()}{n:+})'
|
return f'({self.arg.codegen()}{n:+})'
|
||||||
|
|
5
opt.py
5
opt.py
|
@ -10,8 +10,9 @@ Optimization: TypeAlias = Callable[[Expression], Option[Expression]]
|
||||||
def eliminate_single_let(expr: Expression) -> Option[Expression]:
|
def eliminate_single_let(expr: Expression) -> Option[Expression]:
|
||||||
match expr:
|
match expr:
|
||||||
case LetBinding(lhs, rhs, body):
|
case LetBinding(lhs, rhs, body):
|
||||||
if count_uses(lhs, body) <= 1:
|
rhs_is_simple = isinstance(rhs, Int | Variable | Builtin)
|
||||||
# RHS is used at most once i nthe body
|
if count_uses(lhs, body) <= 1 or rhs_is_simple:
|
||||||
|
# RHS is used at most once i nthe body or replication wouldnt be costly
|
||||||
if count_uses(lhs, rhs) > 0:
|
if count_uses(lhs, rhs) > 0:
|
||||||
# RHS is recursive
|
# RHS is recursive
|
||||||
if not isinstance(body, Variable):
|
if not isinstance(body, Variable):
|
||||||
|
|
Loading…
Reference in New Issue