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:
Kartik K. Agaram 2017-11-06 01:12:42 -08:00
parent c34a067564
commit 3b776ac384
3 changed files with 45 additions and 7 deletions

View File

@ -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));
}
}

View File

@ -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
View 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]
]