diff options
Diffstat (limited to 'cpp/013run')
-rw-r--r-- | cpp/013run | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/cpp/013run b/cpp/013run new file mode 100644 index 00000000..cd0a08a6 --- /dev/null +++ b/cpp/013run @@ -0,0 +1,153 @@ +:(scenarios run) +:(scenario copy_literal) +recipe main [ + 1:integer <- copy 23:literal +] ++run: instruction main/0 ++run: ingredient 0 is 23 ++mem: storing in location 1 + +:(scenario copy) +recipe main [ + 1:integer <- copy 23:literal + 2:integer <- copy 1:integer +] ++run: instruction main/1 ++run: ingredient 0 is 1 ++mem: location 1 is 23 ++mem: storing in location 2 + +:(before "End Types") +// Book-keeping while running a recipe. +//: Later layers will change this. +struct routine { + recipe_number running_recipe; + size_t running_at; + routine(recipe_number r) :running_recipe(r), running_at(0) {} +}; + +:(code) +void run(recipe_number r) { + run(routine(r)); +} + +void run(routine rr) { + while (!done(rr)) { + vector<instruction>& instructions = steps(rr); + size_t& pc = running_at(rr); + // Running one instruction. + if (instructions[pc].is_label) { ++pc; continue; } + trace("run") << "instruction " << recipe_name(rr) << '/' << pc; + switch (instructions[pc].operation) { + // Primitive Recipe Implementations. + case COPY: { + trace("run") << "ingredient 0 is " << instructions[pc].ingredients[0].name; + vector<int> data = read_memory(instructions[pc].ingredients[0]); + write_memory(instructions[pc].products[0], data); + break; + } + // End Primitive Recipe Implementations. + default: { + cout << "not a primitive op: " << instructions[pc].operation << '\n'; + } + } + ++pc; + } +} + +//: Some helpers. +//: We'll need to override these later as we change the definition of routine. +//: Important that they return referrences into the routine. +inline size_t& running_at(routine& rr) { + return rr.running_at; +} + +inline string recipe_name(routine& rr) { + return Recipe[rr.running_recipe].name; +} + +inline vector<instruction>& steps(routine& rr) { + return Recipe[rr.running_recipe].steps; +} + +inline bool done(routine& rr) { + return running_at(rr) >= steps(rr).size(); +} + +:(before "End Main") +if (argc > 1) { + setup(); + for (int i = 1; i < argc; ++i) { + ifstream fin(argv[i]); + while (!fin.eof()) add_recipe(fin); + fin.close(); + } + + recipe_number r = Recipe_number[string("main")]; + if (r) run(r); + dump_memory(); +} + +//: helper for tests + +:(before "End Globals") +// track recipes added so that we can cleanup after each test +vector<recipe_number> recipes_added_by_test; + +:(code) +void run(string form) { + vector<recipe_number> tmp = add_recipes(form); + recipes_added_by_test.insert(recipes_added_by_test.end(), tmp.begin(), tmp.end()); + transform_all(); + run(recipes_added_by_test.front()); +} + +:(before "End Setup") +for (size_t i = 0; i < recipes_added_by_test.size(); ++i) { + Recipe_number.erase(Recipe[recipes_added_by_test[i]].name); + Recipe.erase(recipes_added_by_test[i]); +} +recipes_added_by_test.clear(); + +:(code) +vector<int> read_memory(reagent x) { +//? cout << "read_memory: " << x.to_string() << '\n'; //? 1 + vector<int> result; + if (x.types[0] == 0) { // literal + result.push_back(x.value); + return result; + } + int base = x.value; + for (size_t offset = 0; offset < Type[x.types[0]].size; ++offset) { + int val = Memory[base+offset]; + trace("mem") << "location " << base+offset << " is " << val; + result.push_back(val); + } + return result; +} + +void write_memory(reagent x, vector<int> data) { + int base = to_int(x.name); + size_t size = size_of(x); + if (size != data.size()) raise << "size mismatch in storing to " << x.to_string(); + for (size_t offset = 0; offset < size; ++offset) { + trace("mem") << "storing in location " << base+offset; + Memory[base+offset] = data[offset]; + } +} + +:(code) +size_t size_of(reagent r) { + type_info t = Type[r.types[0]]; + if (!t.is_record && !t.is_array) return t.size; + return t.size; // TODO +} + +:(scenario run_label) +recipe main [ + +foo + 1:integer <- copy 23:literal + 2:integer <- copy 1:integer +] ++run: instruction main/1 ++run: instruction main/2 |