From 3b776ac3843e925ee24f49e8df51ab6a1db6c085 Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Mon, 6 Nov 2017 01:12:42 -0800 Subject: 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. --- 020run.cc | 2 ++ 076continuation.cc | 11 ++++------- continuation5.mu | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 7 deletions(-) create mode 100644 continuation5.mu diff --git a/020run.cc b/020run.cc index 0da9fba7..b94d274a 100644 --- a/020run.cc +++ b/020run.cc @@ -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& 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)); } } diff --git a/076continuation.cc b/076continuation.cc index e3be246d..5311fd67 100644 --- a/076continuation.cc +++ b/076continuation.cc @@ -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. diff --git a/continuation5.mu b/continuation5.mu new file mode 100644 index 00000000..fb00a4f5 --- /dev/null +++ b/continuation5.mu @@ -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] +] -- cgit 1.4.1-2-gfad0