diff options
Diffstat (limited to 'cpp/020run')
-rw-r--r-- | cpp/020run | 187 |
1 files changed, 187 insertions, 0 deletions
diff --git a/cpp/020run b/cpp/020run new file mode 100644 index 00000000..91e242a7 --- /dev/null +++ b/cpp/020run @@ -0,0 +1,187 @@ +:(scenarios run) +:(scenario copy_literal) +recipe main [ + 1:integer <- copy 23:literal +] ++run: instruction main/0 ++run: ingredient 0 is 23 ++mem: storing 23 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 23 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) {} +}; + +:(before "End Globals") +routine* Current_routine = NULL; + +:(code) +void run(recipe_number r) { + run(routine(r)); +} + +void run(routine rr) { + Current_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; } +//? cout << "AAA " << Trace_stream << " ^" << Trace_stream->dump_layer << "$\n"; //? 1 + trace("run") << "instruction " << recipe_name(rr) << '/' << pc; +//? cout << "operation " << instructions[pc].operation << '\n'; //? 3 +//? if (!instructions[pc].products.empty()) trace("foo") << "AAA product 0 is " << instructions[pc].products[0].to_string(); //? 1 + 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; + } + Current_routine = NULL; +} + +//: 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) { + load(argv[i]); + } + + Trace_stream = new trace_stream; +//? Trace_stream->dump_layer = "all"; //? 2 + transform_all(); + recipe_number r = Recipe_number[string("main")]; + if (r) run(r); + dump_memory(); +} + +:(code) +void load(string filename) { + ifstream fin(filename.c_str()); + if (!fin) { + raise << "no such file " << filename << '\n'; + return; + } + fin >> std::noskipws; + add_recipes(fin); + transform_all(); + fin.close(); +} + +//: On startup, load everything in core.mu +:(before "End Load Recipes") +load("core.mu"); +recently_added_recipes.clear(); // freeze everything so it doesn't get cleared by tests + +//: helper for tests + +:(code) +void run(string form) { + vector<recipe_number> tmp = add_recipes(form); + transform_all(); + run(tmp.front()); +} + +:(code) +vector<int> read_memory(reagent x) { +//? cout << "read_memory: " << x.to_string() << '\n'; //? 1 + vector<int> result; + if (isa_literal(x)) { + result.push_back(x.value); + return result; + } + int base = x.value; + size_t size = size_of(x); + for (size_t offset = 0; offset < 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) { + if (is_dummy(x)) return; + int base = x.value; + if (size_of(x) != data.size()) + raise << "size mismatch in storing to " << x.to_string() << '\n'; + for (size_t offset = 0; offset < data.size(); ++offset) { + trace("mem") << "storing " << data[offset] << " in location " << base+offset; + Memory[base+offset] = data[offset]; + } +} + +:(code) +size_t size_of(const reagent& r) { + return size_of(r.types); +} +size_t size_of(const vector<type_number>& types) { + // End size_of(types) Cases + return 1; +} + +bool is_dummy(const reagent& x) { + return x.name == "_"; +} + +bool isa_literal(const reagent& r) { + return r.types.size() == 1 && r.types[0] == 0; +} + +:(scenario run_label) +recipe main [ + +foo + 1:integer <- copy 23:literal + 2:integer <- copy 1:integer +] ++run: instruction main/1 ++run: instruction main/2 +-run: instruction main/0 + +:(scenario run_dummy) +recipe main [ + _ <- copy 0:literal +] ++run: instruction main/0 |