about summary refs log tree commit diff stats
path: root/035call_ingredient.cc
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-07-03 18:07:38 -0700
committerKartik K. Agaram <vc@akkartik.com>2015-07-03 18:11:25 -0700
commit608d5c9aa148801081d7dca80b6f3bfb5b285f08 (patch)
tree8f24ec8efb2c2b5081c068b90537913cef86973d /035call_ingredient.cc
parent7e867a045e29a37d66eedce03c95a2feb979411a (diff)
downloadmu-608d5c9aa148801081d7dca80b6f3bfb5b285f08.tar.gz
1698
Diffstat (limited to '035call_ingredient.cc')
-rw-r--r--035call_ingredient.cc116
1 files changed, 116 insertions, 0 deletions
diff --git a/035call_ingredient.cc b/035call_ingredient.cc
new file mode 100644
index 00000000..9e355eb1
--- /dev/null
+++ b/035call_ingredient.cc
@@ -0,0 +1,116 @@
+//: Calls can take ingredients just like primitives. To access a recipe's
+//: ingredients, use 'next-ingredient'.
+
+:(scenario next_ingredient)
+recipe main [
+  f 2:literal
+]
+recipe f [
+  12:number <- next-ingredient
+  13:number <- add 1:literal, 12:number
+]
++mem: storing 3 in location 13
+
+:(scenario next_ingredient_missing)
+recipe main [
+  f
+]
+recipe f [
+  _, 12:number <- next-ingredient
+]
++mem: storing 0 in location 12
+
+:(before "End call Fields")
+vector<vector<double> > ingredient_atoms;
+long long int next_ingredient_to_process;
+:(before "End call Constructor")
+next_ingredient_to_process = 0;
+
+:(after "complete_call:")
+for (long long int i = 0; i < SIZE(ingredients); ++i) {
+  Current_routine->calls.front().ingredient_atoms.push_back(ingredients.at(i));
+}
+
+:(before "End Primitive Recipe Declarations")
+NEXT_INGREDIENT,
+:(before "End Primitive Recipe Numbers")
+Recipe_number["next-ingredient"] = NEXT_INGREDIENT;
+:(before "End Primitive Recipe Implementations")
+case NEXT_INGREDIENT: {
+  assert(!Current_routine->calls.empty());
+  if (Current_routine->calls.front().next_ingredient_to_process < SIZE(Current_routine->calls.front().ingredient_atoms)) {
+    products.push_back(
+        Current_routine->calls.front().ingredient_atoms.at(Current_routine->calls.front().next_ingredient_to_process));
+    assert(SIZE(products) == 1);  products.resize(2);  // push a new vector
+    products.at(1).push_back(1);
+    ++Current_routine->calls.front().next_ingredient_to_process;
+  }
+  else {
+    products.resize(2);
+    products.at(0).push_back(0);  // todo: will fail noisily if we try to read a compound value
+    products.at(1).push_back(0);
+  }
+  break;
+}
+
+:(scenario rewind_ingredients)
+recipe main [
+  f 2:literal
+]
+recipe f [
+  12:number <- next-ingredient  # consume ingredient
+  _, 1:boolean <- next-ingredient  # will not find any ingredients
+  rewind-ingredients
+  13:number, 2:boolean <- next-ingredient  # will find ingredient again
+]
++mem: storing 2 in location 12
++mem: storing 0 in location 1
++mem: storing 2 in location 13
++mem: storing 1 in location 2
+
+:(before "End Primitive Recipe Declarations")
+REWIND_INGREDIENTS,
+:(before "End Primitive Recipe Numbers")
+Recipe_number["rewind-ingredients"] = REWIND_INGREDIENTS;
+:(before "End Primitive Recipe Implementations")
+case REWIND_INGREDIENTS: {
+  Current_routine->calls.front().next_ingredient_to_process = 0;
+  break;
+}
+
+:(scenario ingredient)
+recipe main [
+  f 1:literal, 2:literal
+]
+recipe f [
+  12:number <- ingredient 1:literal  # consume second ingredient first
+  13:number, 1:boolean <- next-ingredient  # next-ingredient tries to scan past that
+]
++mem: storing 2 in location 12
++mem: storing 0 in location 1
+
+:(before "End Primitive Recipe Declarations")
+INGREDIENT,
+:(before "End Primitive Recipe Numbers")
+Recipe_number["ingredient"] = INGREDIENT;
+:(before "End Primitive Recipe Implementations")
+case INGREDIENT: {
+  assert(is_literal(current_instruction().ingredients.at(0)));
+  assert(scalar(ingredients.at(0)));
+  if (static_cast<long long int>(ingredients.at(0).at(0)) < SIZE(Current_routine->calls.front().ingredient_atoms)) {
+    Current_routine->calls.front().next_ingredient_to_process = ingredients.at(0).at(0);
+    products.push_back(
+        Current_routine->calls.front().ingredient_atoms.at(Current_routine->calls.front().next_ingredient_to_process));
+    assert(SIZE(products) == 1);  products.resize(2);  // push a new vector
+    products.at(1).push_back(1);
+    ++Current_routine->calls.front().next_ingredient_to_process;
+  }
+  else {
+    if (SIZE(current_instruction().products) > 1) {
+      products.resize(2);
+      products.at(0).push_back(0);  // todo: will fail noisily if we try to read a compound value
+      products.at(1).push_back(0);
+    }
+  }
+  break;
+}