Continue brain-dumping psudocode and notes. I think I've got most everything critical now
This commit is contained in:
114
psudocode.txt
114
psudocode.txt
@@ -135,13 +135,53 @@ fun partial_eval_helper(x, only_head, env, env_stack, memostuff, force):
|
|||||||
x is MarkedComb -> if !env.is_real && !x.se.is_real // both aren't real, re-evaluation of closure creation site
|
x is MarkedComb -> if !env.is_real && !x.se.is_real // both aren't real, re-evaluation of closure creation site
|
||||||
|| env.is_real && !x.se.is_real // new env real, but se isn't - the creation of the closure!
|
|| env.is_real && !x.se.is_real // new env real, but se isn't - the creation of the closure!
|
||||||
then let inner_env = make_tmp_inner_env(x.params, x.de?, env, x.env_id)
|
then let inner_env = make_tmp_inner_env(x.params, x.de?, env, x.env_id)
|
||||||
in MarkedComb(se=env, body=partial_eval_helper(body, false, inner_env, add inner_env to env_stack, memostuff, false))
|
in MarkedComb(se=env, body=partial_eval_helper(body, false, inner_env, <add inner_env to env_stack>, memostuff, false))
|
||||||
x is MarkedPrimComb -> x
|
x is MarkedPrimComb -> x
|
||||||
x is MarkedSymbol -> if x.is_val then x
|
x is MarkedSymbol -> if x.is_val then x
|
||||||
else env_lookup_helper(x, env)
|
else env_lookup_helper(x, env)
|
||||||
x is MarkedArray -> if x.is_val then x
|
x is MarkedArray -> if x.is_val then x
|
||||||
else ...TODO...
|
else let
|
||||||
|
comb = partial_eval_helper(x.values[0], only_head=true, env, env_stack, memostuff, false)
|
||||||
|
params = x.values[1:]
|
||||||
|
if later_head?(comb) return MarkedArray(values=[comb]+params)
|
||||||
|
if comb.needed_for_progress == true:
|
||||||
|
comb = partial_eval_helper(comb, only_head=false, ...)
|
||||||
|
|
||||||
|
// If not -1, we always partial eval, if >0 we also unval/partial eval to do one full round of eval
|
||||||
|
wrap_level = comb.wrap_level
|
||||||
|
while wrap_level >= 0:
|
||||||
|
if wrap_level >= 1:
|
||||||
|
params = map(unval, map(\x. partial_eval_helper(x, ...), params))
|
||||||
|
params = map(\x. partial_eval_helper(x, ...), params)
|
||||||
|
wrap_level -= 1
|
||||||
|
if <any of the above error, or couldn't be unvaled yet>:
|
||||||
|
return MarkedArray(values=[comb.with_wrap_level(wrap_level)] + <params at whatever level they were sucessfully evaluated to>)
|
||||||
|
|
||||||
|
if comb is MarkedPrimComb:
|
||||||
|
result = comb.impl(params)
|
||||||
|
if result == 'LATER:
|
||||||
|
return MarkedArray(values=[comb.with_wrap_level(wrap_level)] + params)
|
||||||
|
else:
|
||||||
|
return result
|
||||||
|
|
||||||
|
if comb.is_varadic:
|
||||||
|
params = params[:comb.params.len-1] + [ params[comb.params.len-1:] ]
|
||||||
|
|
||||||
|
inner_env = MarkedEnv(id=comb.env_id, possible_de_symbol=comb.de?, possible_de=env, symbols=comb.params, values=params, upper=comb.se)
|
||||||
|
|
||||||
|
rec_stop_hash = combine_hash(inner_env.hash, comb.body.hash)
|
||||||
|
if rec_stop_hash in memostuff:
|
||||||
|
return MarkedArray(values=[comb] + params, transient_needed_env_id=true, rec_stopping_hash=rec_stop_hash)
|
||||||
|
|
||||||
|
memostuff.add(rec_stop_hash)
|
||||||
|
result = partial_eval_helper(body, false, inner_env, <add inner_env to env_stack>, memostuff, false)
|
||||||
|
memostuff.remove(rec_stop_hash)
|
||||||
|
|
||||||
|
if !combiner_return_ok(result, comb.env_id):
|
||||||
|
transiently_needed = if comb.de? != nil then env.id else nil
|
||||||
|
return MarkedArray(values=[comb] + params, transient_needed_env_id=transiently_needed, rec_stopping_hash=rec_stop_hash)
|
||||||
|
|
||||||
|
return drop_redundent_veval(result, env, env_stack, memostuff)
|
||||||
|
|
||||||
And then we define a root_env with PrimComb versions of all of the standard functions.
|
And then we define a root_env with PrimComb versions of all of the standard functions.
|
||||||
The ones that are most interesting and interact the most with partial evaluation are
|
The ones that are most interesting and interact the most with partial evaluation are
|
||||||
@@ -153,16 +193,61 @@ fun needs_params_prim(...):
|
|||||||
...
|
...
|
||||||
fun give_up_params_prim(...):
|
fun give_up_params_prim(...):
|
||||||
...
|
...
|
||||||
fun veval_inner(...):
|
|
||||||
...
|
fun veval_inner(only_head, de, env_stack, memostuff, params):
|
||||||
|
body = params[0]
|
||||||
|
implicent_env = len(params) != 2
|
||||||
|
eval_env = if implicit_env { de } else { partial_eval_helper(params[1], only_head, de, env_stack, memostuff, false) }
|
||||||
|
evaled_body = partial_eval_helper(body, only_head, eval_env, env_stack, memostuff, false)
|
||||||
|
if implicit_env or combiner_return_ok(evaled_body, eval_env.idx):
|
||||||
|
return drop_redundent_veval(evaled_body, de, env_stack, memostuff)
|
||||||
|
else:
|
||||||
|
return drop_redundent_veval(MarkedArray(values=[MarkedPrimComb('veval, wrap_level=-1, val_head_ok=true, handler=veval_inner), evaled_body, eval_env], de, env_stack, memostuff)
|
||||||
|
|
||||||
root_env = {
|
root_env = {
|
||||||
eval: ...
|
eval: MarkedPrimComb('eval, wrap_level=1, val_head_ok=true, handler=lambda(only_head, de, env_stack, memostuff, params):
|
||||||
vapply: ...
|
let
|
||||||
lapply: ...
|
body = params[0]
|
||||||
vau: ....
|
implicit_env = len(params) != 2
|
||||||
wrap: ...
|
return veval_inner(only_head, de, env_stack, memostuff, if implicit_env { [try_unval(body)] } else { [try_unval(body), params[1]] })
|
||||||
unwrap: ...
|
)
|
||||||
|
vapply: MarkedPrimComb('vapply, wrap_level=1, val_head_ok=true, handler=lambda(only_head, de, env_stack, memostuff, [func params env]):
|
||||||
|
return veval_inner(only_head, de, env_stack, memostuff, [MarkedArray(values=[func]+params), env)
|
||||||
|
)
|
||||||
|
lapply: MarkedPrimComb('lapply, wrap_level=1, val_head_ok=true, handler=lambda(only_head, de, env_stack, memostuff, [func params env]):
|
||||||
|
return veval_inner(only_head, de, env_stack, memostuff, [MarkedArray(values=[func.offset_wrap_level(-1)]+params), env)
|
||||||
|
)
|
||||||
|
vau: MarkedPrimComb('vau, wrap_level=0, val_head_ok=true, handler=lambda(only_head, de, env_stack, memostuff, params):
|
||||||
|
let
|
||||||
|
de? = if len(params) == 3 { params[0].symbol_value } else { nil }
|
||||||
|
params = map(lambda(x): s.symbol_value, if de? { params[1] } else { params[0] })
|
||||||
|
varadic = '& in params
|
||||||
|
params.remove('&)
|
||||||
|
implicit_env = len(params) != 2
|
||||||
|
body = try_unval(if de? { params[2] } else { params[1] })
|
||||||
|
env_id = <new_id>
|
||||||
|
if !only_head:
|
||||||
|
inner_env = make_tmp_inner_env(params, de?, upper=de, id=env_id)
|
||||||
|
body = partial_eval_helper(body, false, inner_env, <add inner_env to env_stack>, memostuff, false)
|
||||||
|
return MarkedComb(wrap_level=0, id=new_id, de?=de?, static_env=de, variadic=varadic, params=params, body=body)
|
||||||
|
)
|
||||||
|
wrap: ...<returns new MarkedPrimComb/MarkedComb with incremented wrap_level>...
|
||||||
|
unwrap: ...<returns new MarkedPrimComb/MarkedComb with decremented wrap_level>...
|
||||||
cond: ...
|
cond: ...
|
||||||
|
...Oddly tricky - is wrap_level 0, but...
|
||||||
|
... 1. unvals & partially evaluates starting from the first condition
|
||||||
|
... 2. if this condition is true, return the unvald & partially evaluated corresponding arm
|
||||||
|
... 3. if this condition is false, drop the arm and return to 1
|
||||||
|
... 4. In this case, we have an unknown between true & false
|
||||||
|
... 5. check to see if combine_hash(x.hash, env.hash) is in memostuff (prevent infinite recursion blocked on a cond guard!)
|
||||||
|
... 6. if the hash was in memostuff, return MarkedArray(later_hash=the_hash,
|
||||||
|
... values=[MarkedPrimComb('vcond,wraplevel=-1,...)] + map(unval, <remaining preds/arms>))
|
||||||
|
... 7. else new_preds_arms = map(partial_eval..., map(unval, <remaining preds/arms>))
|
||||||
|
... <TODO: 8. remove arms/preds now guarenteed to be false, remove all arms/preds after first true>
|
||||||
|
... 9. return MarkedArray(values=[MarkedPrimComb('vcond,wraplevel=-1,...)] + new_preds)
|
||||||
|
...
|
||||||
|
...The vcond is like cond but doesn't do any unvaling (as it's already been done) (and wrap_level is set to -1 so the function call machinery doesn't touch the params either)
|
||||||
|
...
|
||||||
symbol?: needs_params_prim(symbol?)
|
symbol?: needs_params_prim(symbol?)
|
||||||
int?: needs_params_prim(int?)
|
int?: needs_params_prim(int?)
|
||||||
string?: needs_params_prim(string?)
|
string?: needs_params_prim(string?)
|
||||||
@@ -203,6 +288,10 @@ root_env = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun compile(...):
|
fun compile(...):
|
||||||
|
...
|
||||||
|
... tagged words, etc
|
||||||
|
... eval
|
||||||
|
... vau / vau helper closure
|
||||||
...
|
...
|
||||||
Note that when it's compiling a call, it compiles an if/else chain on the wrap level of the combiner being called.
|
Note that when it's compiling a call, it compiles an if/else chain on the wrap level of the combiner being called.
|
||||||
in the 0 branch, it emits the parameters as constant data
|
in the 0 branch, it emits the parameters as constant data
|
||||||
@@ -210,3 +299,8 @@ fun compile(...):
|
|||||||
- note that this must be robust to partial-eval errors, as this branch might not ever happen at runtime and be nonsense code!
|
- note that this must be robust to partial-eval errors, as this branch might not ever happen at runtime and be nonsense code!
|
||||||
- if the partial evaluation errors, it emits a value that will cause an error at runtime into the compiled code
|
- if the partial evaluation errors, it emits a value that will cause an error at runtime into the compiled code
|
||||||
in the > 1 branch, it errors
|
in the > 1 branch, it errors
|
||||||
|
...
|
||||||
|
...
|
||||||
|
Must be careful about infiniate recursion, including tricky cases that infinitly ping back and forth between
|
||||||
|
partial eval and compile even though both have individual internal recursion checks
|
||||||
|
...
|
||||||
|
|||||||
Reference in New Issue
Block a user