about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-10-28 05:50:39 -0700
committerKartik K. Agaram <vc@akkartik.com>2015-10-28 05:51:15 -0700
commit3b795875bc7ab25e5cfa02f74b1a4428af4c0ec4 (patch)
tree3b5ac4de7382ee1ff682fd9e94a813484bb3d6d9
parent3eeea0a22d16e0fcd43bd33725c0b54639d0ad14 (diff)
downloadmu-3b795875bc7ab25e5cfa02f74b1a4428af4c0ec4.tar.gz
2295 - drop first-class recipes and continuations
Making life too complex at this time.
-rw-r--r--034call.cc7
-rw-r--r--035call_ingredient.cc4
-rw-r--r--037recipe.cc52
-rw-r--r--053continuation.cc292
-rw-r--r--callcc.mu17
-rw-r--r--counters.mu16
-rw-r--r--mu.vim1
7 files changed, 9 insertions, 380 deletions
diff --git a/034call.cc b/034call.cc
index b799b594..ee554ab6 100644
--- a/034call.cc
+++ b/034call.cc
@@ -90,7 +90,6 @@ if (Recipe.find(inst.operation) == Recipe.end()) {
 }
 :(replace{} "default:" following "End Primitive Recipe Implementations")
 default: {
-  const instruction& call_instruction = current_instruction();
   if (Recipe.find(current_instruction().operation) == Recipe.end()) {  // duplicate from Checks
     // stop running this instruction immediately
     ++current_step_index();
@@ -103,12 +102,8 @@ default: {
     assert(Trace_stream->callstack_depth < 9000);  // 9998-101 plus cushion
   }
   Current_routine->calls.push_front(call(current_instruction().operation));
-  finish_call_housekeeping(call_instruction, ingredients);
-  continue;  // not done with caller; don't increment current_step_index()
-}
-:(code)
-void finish_call_housekeeping(const instruction& call_instruction, const vector<vector<double> >& ingredients) {
   // End Call Housekeeping
+  continue;  // not done with caller; don't increment current_step_index()
 }
 
 :(scenario calling_undefined_recipe_fails)
diff --git a/035call_ingredient.cc b/035call_ingredient.cc
index c8f6d75a..1291e567 100644
--- a/035call_ingredient.cc
+++ b/035call_ingredient.cc
@@ -22,7 +22,6 @@ recipe f [
 
 :(before "End call Fields")
 vector<vector<double> > ingredient_atoms;
-vector<type_tree*> ingredient_types;
 long long int next_ingredient_to_process;
 :(before "End call Constructor")
 next_ingredient_to_process = 0;
@@ -30,9 +29,6 @@ next_ingredient_to_process = 0;
 :(before "End Call Housekeeping")
 for (long long int i = 0; i < SIZE(ingredients); ++i) {
   Current_routine->calls.front().ingredient_atoms.push_back(ingredients.at(i));
-  if (SIZE(Current_routine->calls) > 1)
-    Current_routine->calls.front().ingredient_types.push_back(call_instruction.ingredients.at(i).type);
-  // todo: else function is main and ingredient_type is string
 }
 
 :(before "End Primitive Recipe Declarations")
diff --git a/037recipe.cc b/037recipe.cc
index 51ad79af..a2a95a39 100644
--- a/037recipe.cc
+++ b/037recipe.cc
@@ -2,27 +2,6 @@
 //: also like to make the recipe a variable, pass recipes to "higher-order"
 //: recipes, return recipes from recipes and so on.
 
-:(scenario call_literal_recipe)
-recipe main [
-  1:number <- call f:recipe, 34
-]
-recipe f [
-  2:number <- next-ingredient
-  reply 2:number
-]
-+mem: storing 34 in location 1
-
-:(scenario call_variable)
-recipe main [
-  1:recipe-ordinal <- copy f:recipe
-  2:number <- call 1:recipe-ordinal, 34
-]
-recipe f [
-  3:number <- next-ingredient
-  reply 3:number
-]
-+mem: storing 34 in location 2
-
 :(before "End Mu Types Initialization")
 // 'recipe' is a literal
 Type_ordinal["recipe"] = 0;
@@ -36,37 +15,6 @@ if (r.properties.at(0).second && r.properties.at(0).second->value == "recipe") {
   return;
 }
 
-:(before "End Primitive Recipe Declarations")
-CALL,
-:(before "End Primitive Recipe Numbers")
-Recipe_ordinal["call"] = CALL;
-:(before "End Primitive Recipe Checks")
-case CALL: {
-  if (inst.ingredients.empty()) {
-    raise_error << maybe(Recipe[r].name) << "'call' requires at least one ingredient (the recipe to call)\n" << end();
-    break;
-  }
-  if (!is_mu_recipe(inst.ingredients.at(0))) {
-    raise_error << maybe(Recipe[r].name) << "first ingredient of 'call' should be a recipe, but got " << inst.ingredients.at(0).original_string << '\n' << end();
-    break;
-  }
-  break;
-}
-:(before "End Primitive Recipe Implementations")
-case CALL: {
-  // Begin Call
-  if (Trace_stream) {
-    ++Trace_stream->callstack_depth;
-    trace("trace") << "indirect 'call': incrementing callstack depth to " << Trace_stream->callstack_depth << end();
-    assert(Trace_stream->callstack_depth < 9000);  // 9998-101 plus cushion
-  }
-  const instruction& caller_instruction = current_instruction();
-  Current_routine->calls.push_front(call(ingredients.at(0).at(0)));
-  ingredients.erase(ingredients.begin());  // drop the callee
-  finish_call_housekeeping(caller_instruction, ingredients);
-  continue;
-}
-
 :(code)
 bool is_mu_recipe(reagent r) {
   if (!r.type) return false;
diff --git a/053continuation.cc b/053continuation.cc
deleted file mode 100644
index b92217d6..00000000
--- a/053continuation.cc
+++ /dev/null
@@ -1,292 +0,0 @@
-//: Continuations are a powerful primitive for constructing advanced kinds of
-//: control *policies* like back-tracking. They're usually provided using a
-//: primitive called 'call-cc': http://en.wikipedia.org/wiki/Call-with-current-continuation)
-//: But in mu 'call-cc' is constructed out of a combination of two primitives:
-//:   'current-continuation', which returns a continuation, and
-//:   'continue-from', which takes a continuation to switch to.
-
-//: todo: implement continuations in mu's memory
-:(before "End Globals")
-map<long long int, call_stack> Continuation;
-long long int Next_continuation_id = 0;
-:(before "End Setup")
-Continuation.clear();
-Next_continuation_id = 0;
-
-:(before "End Mu Types Initialization")
-type_ordinal continuation = Type_ordinal["continuation"] = Next_type_ordinal++;
-Type[continuation].name = "continuation";
-
-:(before "End Primitive Recipe Declarations")
-CURRENT_CONTINUATION,
-:(before "End Primitive Recipe Numbers")
-Recipe_ordinal["current-continuation"] = CURRENT_CONTINUATION;
-:(before "End Primitive Recipe Checks")
-case CURRENT_CONTINUATION: {
-  break;
-}
-:(before "End Primitive Recipe Implementations")
-case CURRENT_CONTINUATION: {
-  // copy the current call stack
-  Continuation[Next_continuation_id] = Current_routine->calls;  // deep copy because calls have no pointers
-  // make sure calling the copy doesn't spawn the same continuation again
-  ++Continuation[Next_continuation_id].front().running_step_index;
-  products.resize(1);
-  products.at(0).push_back(Next_continuation_id);
-  ++Next_continuation_id;
-  trace("current-continuation") << "new continuation " << Next_continuation_id << end();
-  break;
-}
-
-:(before "End Primitive Recipe Declarations")
-CONTINUE_FROM,
-:(before "End Primitive Recipe Numbers")
-Recipe_ordinal["continue-from"] = CONTINUE_FROM;
-:(before "End Primitive Recipe Checks")
-case CONTINUE_FROM: {
-  if (!is_mu_continuation(inst.ingredients.at(0))) {
-    raise_error << maybe(Recipe[r].name) << "first ingredient of 'continue-from' should be a continuation generated by 'current-continuation', but got " << inst.ingredients.at(0).original_string << '\n' << end();
-    break;
-  }
-  break;
-}
-:(before "End Primitive Recipe Implementations")
-case CONTINUE_FROM: {
-  long long int c = ingredients.at(0).at(0);
-  if (Trace_stream) {
-    Trace_stream->callstack_depth += SIZE(Continuation[c]);
-    trace("trace") << "continuation; growing callstack depth to " << Trace_stream->callstack_depth << end();
-    assert(Trace_stream->callstack_depth < 9000);  // 9998-101 plus cushion
-  }
-  Current_routine->calls = Continuation[c];  // deep copy; calls have no pointers
-  continue;  // skip rest of this instruction
-}
-
-:(code)
-bool is_mu_continuation(const reagent& x) {
-  if (!x.type) return false;
-  return x.type->value == Type_ordinal["continuation"];
-}
-
-:(scenario continuation)
-# simulate a loop using continuations
-recipe main [
-  1:number <- copy 0
-  2:continuation <- current-continuation
-  {
-    3:boolean <- greater-or-equal 1:number, 3
-    break-if 3:boolean
-    1:number <- add 1:number, 1
-    continue-from 2:continuation  # loop
-  }
-]
-+mem: storing 1 in location 1
-+mem: storing 2 in location 1
-+mem: storing 3 in location 1
--mem: storing 4 in location 1
-# ensure every iteration doesn't copy the stack over and over
-$current-continuation: 1
-
-:(scenario continuation_inside_caller)
-recipe main [
-  1:number <- copy 0
-  2:continuation <- loop-body
-  {
-    3:boolean <- greater-or-equal 1:number, 3
-    break-if 3:boolean
-    continue-from 2:continuation  # loop
-  }
-]
-
-recipe loop-body [
-  4:continuation <- current-continuation
-  1:number <- add 1:number, 1
-]
-+mem: storing 1 in location 1
-+mem: storing 2 in location 1
-+mem: storing 3 in location 1
--mem: storing 4 in location 1
-
-//:: A variant of continuations is the 'delimited' continuation that can be called like any other recipe.
-//:
-//: In mu, this is constructed out of two primitives:
-//:
-//:  * 'create-delimited-continuation' lays down a mark on the call
-//:    stack and calls the provided function (it is sometimes called 'prompt')
-//:  * 'reply-current-continuation' copies the top of the stack until the
-//:    mark, and returns it as the response of create-delimited-continuation
-//:    (which might be a distant ancestor on the call stack; intervening calls
-//:    don't return)
-//:
-//: The resulting slice of the stack can now be called just like a regular
-//: function.
-
-:(scenario delimited_continuation)
-recipe main [
-  1:continuation <- create-delimited-continuation f:recipe 12  # 12 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
-    3:boolean <- greater-or-equal 2:number, 8
-    break-if 3:boolean
-    loop
-  }
-]
-
-recipe f [
-  11:number <- next-ingredient
-  12:number <- g 11:number
-  reply 12:number
-]
-
-recipe g [
-  21:number <- next-ingredient
-  rewind-ingredients
-  reply-delimited-continuation
-  # calls of the continuation start from here
-  22:number <- next-ingredient
-  23:number <- add 22:number, 1
-  reply 23:number
-]
-# first call of 'g' executes the part before reply-delimited-continuation
-+mem: storing 12 in location 21
-+run: 2:number <- copy 5
-+mem: storing 5 in location 2
-# calls of the continuation execute the part after reply-delimited-continuation
-+run: 2:number <- call 1:continuation, 2:number
-+mem: storing 5 in location 22
-+mem: storing 6 in location 2
-+run: 2:number <- call 1:continuation, 2:number
-+mem: storing 6 in location 22
-+mem: storing 7 in location 2
-+run: 2:number <- call 1:continuation, 2:number
-+mem: storing 7 in location 22
-+mem: storing 8 in location 2
-# first call of 'g' does not execute the part after reply-delimited-continuation
--mem: storing 12 in location 22
-# calls of the continuation don't execute the part before reply-delimited-continuation
--mem: storing 5 in location 21
--mem: storing 6 in location 21
--mem: storing 7 in location 21
-# termination
--mem: storing 9 in location 2
-
-//: 'create-delimited-continuation' is like 'call' except it adds a 'reset' mark to
-//: the call stack
-
-:(before "End call Fields")
-bool is_reset;
-:(before "End call Constructor")
-is_reset = false;
-
-//: like call, but mark the current call as a 'reset' call before pushing the next one on it
-
-:(before "End Primitive Recipe Declarations")
-CREATE_DELIMITED_CONTINUATION,
-:(before "End Primitive Recipe Numbers")
-Recipe_ordinal["create-delimited-continuation"] = CREATE_DELIMITED_CONTINUATION;
-:(before "End Primitive Recipe Checks")
-case CREATE_DELIMITED_CONTINUATION: {
-  break;
-}
-:(before "End Primitive Recipe Implementations")
-case CREATE_DELIMITED_CONTINUATION: {
-  if (Trace_stream) {
-    ++Trace_stream->callstack_depth;
-    trace("trace") << "delimited continuation; incrementing callstack depth to " << Trace_stream->callstack_depth << end();
-    assert(Trace_stream->callstack_depth < 9000);  // 9998-101 plus cushion
-  }
-  const instruction& caller_instruction = current_instruction();
-  Current_routine->calls.front().is_reset = true;
-  Current_routine->calls.push_front(call(Recipe_ordinal[current_instruction().ingredients.at(0).name]));
-  ingredients.erase(ingredients.begin());  // drop the callee
-  finish_call_housekeeping(caller_instruction, ingredients);
-  continue;
-}
-
-//: save the slice of current call stack until the 'create-delimited-continuation'
-//: call, and return it as the result.
-//: todo: implement delimited continuations in mu's memory
-:(before "End Globals")
-map<long long int, call_stack> Delimited_continuation;
-long long int Next_delimited_continuation_id = 0;
-:(before "End Setup")
-Delimited_continuation.clear();
-Next_delimited_continuation_id = 0;
-
-:(before "End Primitive Recipe Declarations")
-REPLY_DELIMITED_CONTINUATION,
-:(before "End Primitive Recipe Numbers")
-Recipe_ordinal["reply-delimited-continuation"] = REPLY_DELIMITED_CONTINUATION;
-:(before "End Primitive Recipe Checks")
-case REPLY_DELIMITED_CONTINUATION: {
-  break;
-}
-:(before "End Primitive Recipe Implementations")
-case REPLY_DELIMITED_CONTINUATION: {
-  // first clear any existing ingredients, to isolate the creation of the
-  // continuation from its calls
-  Current_routine->calls.front().ingredient_atoms.clear();
-  Current_routine->calls.front().next_ingredient_to_process = 0;
-  // copy the current call stack until the most recent 'reset' call
-  call_stack::iterator find_reset(call_stack& c);  // manual prototype containing '::'
-  call_stack::iterator reset = find_reset(Current_routine->calls);
-  if (reset == Current_routine->calls.end()) {
-    raise_error << maybe(current_recipe_name()) << "couldn't find a 'reset' call to jump out to\n" << end();
-    break;
-  }
-  Delimited_continuation[Next_delimited_continuation_id] = call_stack(Current_routine->calls.begin(), reset);
-  while (Current_routine->calls.begin() != reset) {
-    if (Trace_stream) {
-      --Trace_stream->callstack_depth;
-      assert(Trace_stream->callstack_depth >= 0);
-    }
-    Current_routine->calls.pop_front();
-  }
-  // return it as the result of the 'reset' call
-  products.resize(1);
-  products.at(0).push_back(Next_delimited_continuation_id);
-  ++Next_delimited_continuation_id;
-  break;  // continue to process rest of 'reset' call
-}
-
-:(code)
-call_stack::iterator find_reset(call_stack& c) {
-  for (call_stack::iterator p = c.begin(); p != c.end(); ++p)
-    if (p->is_reset) return p;
-  return c.end();
-}
-
-//: overload 'call' for continuations
-:(after "Begin Call")
-  if (!current_instruction().ingredients.at(0).properties.empty()
-      && current_instruction().ingredients.at(0).properties.at(0).second
-      && current_instruction().ingredients.at(0).properties.at(0).second->value == "continuation") {
-    // copy multiple calls on to current call stack
-    assert(scalar(ingredients.at(0)));
-    if (Delimited_continuation.find(ingredients.at(0).at(0)) == Delimited_continuation.end()) {
-      raise_error << maybe(current_recipe_name()) << "no such delimited continuation " << current_instruction().ingredients.at(0).original_string << '\n' << end();
-    }
-    const call_stack& new_calls = Delimited_continuation[ingredients.at(0).at(0)];
-    const call& caller = (SIZE(new_calls) > 1) ? *++new_calls.rbegin() : Current_routine->calls.front();
-    for (call_stack::const_reverse_iterator p = new_calls.rbegin(); p != new_calls.rend(); ++p)
-      Current_routine->calls.push_front(*p);
-    if (Trace_stream) {
-      Trace_stream->callstack_depth += SIZE(new_calls);
-      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 reply-delimited-continuation
-    ingredients.erase(ingredients.begin());  // drop the callee
-    finish_call_housekeeping(to_instruction(caller), ingredients);
-    continue;
-  }
-
-:(code)
-const instruction& to_instruction(const call& c) {
-  assert(Recipe.find(c.running_recipe) != Recipe.end());
-  return Recipe[c.running_recipe].steps.at(c.running_step_index);
-}
-
-:(before "End is_mu_recipe Cases")
-if (r.type && r.type->value == Type_ordinal["continuation"]) return true;
diff --git a/callcc.mu b/callcc.mu
deleted file mode 100644
index 1bf32973..00000000
--- a/callcc.mu
+++ /dev/null
@@ -1,17 +0,0 @@
-# example program: saving and reusing call-stacks or continuations
-
-recipe main [
-  c:continuation <- f
-  continue-from c                         # <-- ..when you hit this
-]
-
-recipe f [
-  c:continuation <- g
-  reply c
-]
-
-recipe g [
-  c:continuation <- current-continuation  # <-- loop back to here
-  $print 1
-  reply c  # threaded through unmodified after first iteration
-]
diff --git a/counters.mu b/counters.mu
index 8a4da073..be1f098a 100644
--- a/counters.mu
+++ b/counters.mu
@@ -1,18 +1,18 @@
 # example program: maintain multiple counters with isolated lexical scopes
 # (spaces)
 
-recipe new-counter n:number -> default-space:address:array:location [
-  default-space <- new location:type, 30
-  load-ingredients
-  reply
+recipe new-counter [
+  default-space:address:array:location <- new location:type, 30
+  n:number <- next-ingredient
+  reply default-space
 ]
 
-recipe increment-counter outer:address:array:location/names:new-counter, x:number -> n:number/space:1 [
+recipe increment-counter [
   local-scope
-  load-ingredients
-  0:address:array:location/names:new-counter <- copy outer  # setup outer space; it *must* come from 'new-counter'
+  0:address:array:location/names:new-counter <- next-ingredient  # setup outer space; it *must* come from 'new-counter'
+  x:number <- next-ingredient
   n:number/space:1 <- add n:number/space:1, x
-  reply n/space:1
+  reply n:number/space:1
 ]
 
 recipe main [
diff --git a/mu.vim b/mu.vim
index bb77b50d..72255940 100644
--- a/mu.vim
+++ b/mu.vim
@@ -62,7 +62,6 @@ syntax match muGlobal %[^ ]\+:global/\?[^ ,]*% | highlight link muGlobal Special
 syntax keyword muControl reply reply-if reply-unless jump jump-if jump-unless loop loop-if loop-unless break break-if break-unless current-continuation continue-from create-delimited-continuation reply-delimited-continuation | highlight muControl ctermfg=3
 " common keywords
 syntax keyword muRecipe recipe recipe! before after | highlight muRecipe ctermfg=208
-syntax match muRecipe " -> "
 syntax keyword muScenario scenario | highlight muScenario ctermfg=34
 syntax keyword muData container exclusive-container | highlight muData ctermfg=226