about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--cpp/.traces/new27
-rw-r--r--cpp/021call7
-rw-r--r--cpp/026new52
3 files changed, 84 insertions, 2 deletions
diff --git a/cpp/.traces/new b/cpp/.traces/new
new file mode 100644
index 00000000..c76e910b
--- /dev/null
+++ b/cpp/.traces/new
@@ -0,0 +1,27 @@
+parse/0: instruction: 24
+parse/0:   ingredient: {name: "integer", value: 0, type: 0, properties: [integer: type]}
+parse/0:   product: {name: "1", value: 0, type: 2-1, properties: [1: address:integer, raw: ]}
+parse/0: instruction: 24
+parse/0:   ingredient: {name: "integer", value: 0, type: 0, properties: [integer: type]}
+parse/0:   product: {name: "2", value: 0, type: 2-1, properties: [2: address:integer, raw: ]}
+parse/0: instruction: 13
+parse/0:   ingredient: {name: "1", value: 0, type: 2-1, properties: [1: address:integer, raw: ]}
+parse/0:   ingredient: {name: "2", value: 0, type: 2-1, properties: [2: address:integer, raw: ]}
+parse/0:   product: {name: "3", value: 0, type: 3, properties: [3: boolean, raw: ]}
+new/0: integer -> 1
+new/0: integer -> 1
+after-brace/0: recipe main
+after-brace/0: new ...
+after-brace/0: new ...
+after-brace/0: equal ...
+run/0: instruction main/0
+mem/0: storing 1000 in location 1
+run/0: instruction main/1
+mem/0: storing 1001 in location 2
+run/0: instruction main/2
+run/0: ingredient 0 is 1
+mem/0: location 1 is 1000
+run/0: ingredient 1 is 2
+mem/0: location 2 is 1001
+run/0: product 0 is 0
+mem/0: storing 0 in location 3
diff --git a/cpp/021call b/cpp/021call
index ad7c3ee3..79f86183 100644
--- a/cpp/021call
+++ b/cpp/021call
@@ -23,10 +23,13 @@ typedef stack<call> call_stack;
 :(replace{} "struct routine")
 struct routine {
   call_stack calls;
-  routine(recipe_number r) {
+  // End Routine Fields
+  routine(recipe_number r);
+};
+:(code)
+  routine::routine(recipe_number r) {
     calls.push(call(r));
   }
-};
 //: now update routine's helpers
 :(replace{} "inline size_t& running_at(routine& rr)")
 inline size_t& running_at(routine& rr) {
diff --git a/cpp/026new b/cpp/026new
new file mode 100644
index 00000000..edc17b17
--- /dev/null
+++ b/cpp/026new
@@ -0,0 +1,52 @@
+//: A simple memory allocator to create space for new variables at runtime.
+
+:(scenarios run)
+:(scenario "new")
+# call new two times with identical arguments; you should get back different results
+recipe main [
+  1:address:integer/raw <- new integer:type
+  2:address:integer/raw <- new integer:type
+  3:boolean/raw <- equal 1:address:integer/raw, 2:address:integer/raw
+]
++mem: storing 0 in location 3
+
+:(before "End Globals")
+const size_t Alloc_init = 1000;
+:(before "End Routine Fields")
+size_t alloc;
+:(replace{} "routine::routine(recipe_number r)")
+  routine::routine(recipe_number r) :alloc(Alloc_init) {
+    calls.push(call(r));
+  }
+
+//: first handle 'type' operands
+:(before "End Mu Types Initialization")
+Type_number["type"] = 0;
+:(after "Per-recipe Transforms")
+// replace type names with type_numbers
+if (inst.operation == Recipe_number["new"]) {
+  // first arg must be of type 'type'
+  assert(inst.ingredients.size() >= 1);
+  assert(isa_literal(inst.ingredients[0]));
+  assert(inst.ingredients[0].properties[0].second[0] == "type");
+  inst.ingredients[0].value = Type_number[inst.ingredients[0].name];
+  trace("new") << inst.ingredients[0].name << " -> " << inst.ingredients[0].value;
+}
+
+:(before "End Globals")
+// Operator to look at elements of arrays.
+const int NEW = 24;
+:(before "End Primitive Recipe Numbers")
+Recipe_number["new"] = NEW;
+assert(Next_recipe_number == NEW);
+Next_recipe_number++;
+:(before "End Primitive Recipe Implementations")
+case NEW: {
+  vector<int> result;
+  result.push_back(Current_routine.alloc);
+  write_memory(instructions[pc].products[0], result);
+  vector<int> types;
+  types.push_back(instructions[pc].ingredients[0].value);
+  Current_routine.alloc += size_of(types);
+  break;
+}