4116 - support calling continuations with arguments
Surprisingly small change, considering how long it took me and how mind-bending it was. 'return-continuation-until-mark' now behaves like both call and return instructions, which made it hard to reason about.
This commit is contained in:
parent
c34a067564
commit
3b776ac384
|
@ -64,6 +64,7 @@ void run_current_routine() {
|
|||
// Running One Instruction
|
||||
if (current_instruction().is_label) { ++current_step_index(); continue; }
|
||||
trace(Initial_callstack_depth + Trace_stream->callstack_depth, "run") << to_string(current_instruction()) << end();
|
||||
//? if (Foo) cerr << "run: " << to_string(current_instruction()) << '\n';
|
||||
if (get_or_insert(Memory, 0) != 0) {
|
||||
raise << "something wrote to location 0; this should never happen\n" << end();
|
||||
put(Memory, 0, 0);
|
||||
|
@ -323,6 +324,7 @@ void write_memory(reagent/*copy*/ x, const vector<double>& data) {
|
|||
for (int offset = 0; offset < SIZE(data); ++offset) {
|
||||
assert(x.value+offset > 0);
|
||||
trace("mem") << "storing " << no_scientific(data.at(offset)) << " in location " << x.value+offset << end();
|
||||
//? if (Foo) cerr << "mem: storing " << no_scientific(data.at(offset)) << " in location " << x.value+offset << '\n';
|
||||
put(Memory, x.value+offset, data.at(offset));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ recipe main [
|
|||
1:continuation <- call-with-continuation-mark f, 77 # 77 is an argument to f
|
||||
2:number <- copy 5
|
||||
{
|
||||
2:number <- call 1:continuation, 2:number # 2 is an argument to g, the 'top' of the continuation
|
||||
2:number <- call 1:continuation, 2:number # jump to 'return-continuation-until-mark' below
|
||||
3:boolean <- greater-or-equal 2:number, 8
|
||||
break-if 3:boolean
|
||||
loop
|
||||
|
@ -73,10 +73,7 @@ recipe f [
|
|||
]
|
||||
recipe g [
|
||||
21:number <- next-ingredient
|
||||
rewind-ingredients
|
||||
return-continuation-until-mark
|
||||
# calls of the continuation start from here
|
||||
22:number <- next-ingredient
|
||||
22:number <- return-continuation-until-mark
|
||||
23:number <- add 22:number, 1
|
||||
return 23:number
|
||||
]
|
||||
|
@ -218,10 +215,10 @@ if (current_instruction().ingredients.at(0).type->atom
|
|||
trace("trace") << "calling delimited continuation; growing callstack depth to " << Trace_stream->callstack_depth << end();
|
||||
assert(Trace_stream->callstack_depth < 9000); // 9998-101 plus cushion
|
||||
}
|
||||
++current_step_index(); // skip past the return-continuation-until-mark
|
||||
ingredients.erase(ingredients.begin()); // drop the callee
|
||||
finish_call_housekeeping(to_instruction(caller), ingredients);
|
||||
continue;
|
||||
copy(ingredients.begin(), ingredients.end(), inserter(products, products.begin()));
|
||||
break; // record results of resuming 'return-continuation-until-mark' instruction
|
||||
}
|
||||
|
||||
//: Ensure that the presence of a continuation keeps its stack frames from being reclaimed.
|
||||
|
|
39
continuation5.mu
Normal file
39
continuation5.mu
Normal file
|
@ -0,0 +1,39 @@
|
|||
# Example program showing that a 'paused' continuation can be 'resumed' with
|
||||
# ingredients.
|
||||
#
|
||||
# Print out a list of numbers, first adding 0 to the first, 1 to the second, 2
|
||||
# to the third, and so on.
|
||||
|
||||
def main [
|
||||
local-scope
|
||||
l:&:list:num <- copy 0
|
||||
l <- push 3, l
|
||||
l <- push 2, l
|
||||
l <- push 1, l
|
||||
k:continuation, x:num, done?:bool <- call-with-continuation-mark create-yielder, l
|
||||
a:num <- copy 1
|
||||
{
|
||||
break-if done?
|
||||
$print x 10/newline
|
||||
k, x:num, done?:bool <- call k, a # resume; x = a + next l value
|
||||
a <- add a, 1
|
||||
loop
|
||||
}
|
||||
]
|
||||
|
||||
def create-yielder l:&:list:num -> n:num, done?:bool [
|
||||
local-scope
|
||||
load-ingredients
|
||||
a:num <- copy 0
|
||||
{
|
||||
done? <- equal l, 0
|
||||
break-if done?
|
||||
n <- first l
|
||||
l <- rest l
|
||||
n <- add n, a
|
||||
a <- return-continuation-until-mark n, done? # pause/resume
|
||||
loop
|
||||
}
|
||||
return-continuation-until-mark -1, done?
|
||||
assert 0/false, [called too many times, ran out of continuations to return]
|
||||
]
|
Loading…
Reference in New Issue
Block a user