diff options
author | Kartik K. Agaram <vc@akkartik.com> | 2015-03-15 09:43:05 -0700 |
---|---|---|
committer | Kartik K. Agaram <vc@akkartik.com> | 2015-03-15 09:43:05 -0700 |
commit | ec92602746894c81990a37d7a5e5d7f14a518f0e (patch) | |
tree | 5783f2eaadfae829ea4c1524cff52ee8f3d3904c | |
parent | fa0c006672437f4e89f86d0f53e9e4b3da767a74 (diff) | |
download | mu-ec92602746894c81990a37d7a5e5d7f14a518f0e.tar.gz |
928 - 'call' layer is now more cohesive
It does less though. Args temporarily not supported.
-rw-r--r-- | cpp/.traces/calling_recipe | 2 | ||||
-rw-r--r-- | cpp/002trace | 3 | ||||
-rw-r--r-- | cpp/012run | 61 | ||||
-rw-r--r-- | cpp/020call | 117 |
4 files changed, 76 insertions, 107 deletions
diff --git a/cpp/.traces/calling_recipe b/cpp/.traces/calling_recipe index 3c220e09..c0538ca8 100644 --- a/cpp/.traces/calling_recipe +++ b/cpp/.traces/calling_recipe @@ -1,4 +1,4 @@ -parse/0: instruction: 25 +parse/0: instruction: 23 parse/0: instruction: 2 parse/0: ingredient: {name: "2", type: 0} parse/0: ingredient: {name: "2", type: 0} diff --git a/cpp/002trace b/cpp/002trace index 796ad7f1..b4d0cfca 100644 --- a/cpp/002trace +++ b/cpp/002trace @@ -113,7 +113,7 @@ struct trace_stream { void newline() { if (!curr_stream) return; past_lines.push_back(pair<string, pair<int, string> >(curr_layer, pair<int, string>(frame[curr_layer], curr_stream->str()))); - if (curr_layer == dump_layer || curr_layer == "dump" || + if (curr_layer == dump_layer || curr_layer == "dump" || dump_layer == "all" || (!Hide_warnings && curr_layer == "warn")) cerr << frame[curr_layer] << ": " << with_newline(curr_stream->str()); delete curr_stream; @@ -204,6 +204,7 @@ struct lease_tracer { #define START_TRACING_UNTIL_END_OF_SCOPE lease_tracer leased_tracer; :(before "End Test Setup") START_TRACING_UNTIL_END_OF_SCOPE +//? Trace_stream->dump_layer = "all"; //? 1 :(before "End Tracing") void trace_all(const string& label, const list<string>& in) { diff --git a/cpp/012run b/cpp/012run index 3f02c7b9..558a264d 100644 --- a/cpp/012run +++ b/cpp/012run @@ -18,24 +18,12 @@ recipe main [ +mem: storing in location 2 :(before "End Types") -// Each recipe can be 'called' many many times in a program. Each call needs a -// little extra information. TODO: move this into the call layer somehow -struct call { - recipe_number running_recipe; - size_t pc; - // End Call Fields - call(recipe_number r) :running_recipe(r), pc(0) {} -}; -typedef stack<call> call_stack; - -// TODO: move this into the scheduler layer somehow +// Book-keeping while running a recipe. +// Later layers will change this. struct routine { - size_t alloc; - size_t alloc_max; - call_stack calls; - size_t limit; - size_t running_since; - // todo: sleep conditions + recipe_number running_recipe; + size_t running_at; + routine(recipe_number r) :running_recipe(r), running_at(0) {} }; :(code) @@ -44,23 +32,15 @@ void run(string form) { } void run(recipe_number r) { - routine rr; - rr.calls.push(call(r)); - run(rr); + run(routine(r)); } void run(routine rr) { - while (!rr.calls.empty()) { - vector<instruction>& instructions = Recipe[rr.calls.top().running_recipe].steps; - // TODO: move this into the call layer somehow - while (rr.calls.top().pc >= instructions.size()) { - rr.calls.pop(); - if (rr.calls.empty()) return; - // todo: no results returned warning - ++rr.calls.top().pc; - } - size_t& pc = rr.calls.top().pc; - trace("run") << "instruction " << Recipe[rr.calls.top().running_recipe].name << '/' << pc; + while (!done(rr)) { + vector<instruction>& instructions = steps(rr); + size_t& pc = running_at(rr); + // Running one instruction. + trace("run") << "instruction " << recipe_name(rr) << '/' << pc; switch (instructions[pc].operation) { // Primitive Recipe Implementations. case COPY: { @@ -78,6 +58,25 @@ void run(routine rr) { } } +// 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(); diff --git a/cpp/020call b/cpp/020call index ef15ee94..f926a100 100644 --- a/cpp/020call +++ b/cpp/020call @@ -1,3 +1,4 @@ +// So far the recipes we define can't run each other. Let's change that. :(scenario "calling_recipe") recipe main [ f @@ -7,11 +8,37 @@ recipe f [ ] +mem: storing in location 3 -:(before "End Call Fields") -vector<vector<int> > ingredient_atoms; -size_t next_ingredient_to_process; -:(replace{} "call(recipe_number r)") -call(recipe_number r) :running_recipe(r), pc(0), next_ingredient_to_process(0) {} +:(before "struct routine {") +// Everytime a recipe runs another, we interrupt it and start running the new +// recipe. When that finishes, we continue this one where we left off. +// This requires maintaining a 'stack' of interrupted recipes or 'calls'. +struct call { + recipe_number running_recipe; + size_t pc; + // End Call Fields + call(recipe_number r) :running_recipe(r), pc(0) {} +}; +typedef stack<call> call_stack; + +:(replace{} "struct routine") +struct routine { + call_stack calls; + routine(recipe_number r) { + calls.push(call(r)); + } +}; +:(replace{} "inline size_t& running_at(routine& rr)") +inline size_t& running_at(routine& rr) { + return rr.calls.top().pc; +} +:(replace{} "inline string recipe_name(routine& rr)") +inline string recipe_name(routine& rr) { + return Recipe[rr.calls.top().running_recipe].name; +} +:(replace{} "inline vector<instruction>& steps(routine& rr)") +inline vector<instruction>& steps(routine& rr) { + return Recipe[rr.calls.top().running_recipe].steps; +} :(replace{} "default:" following "End Primitive Recipe Implementations.") default: { @@ -20,79 +47,21 @@ default: { raise << "undefined operation " << instructions[pc].operation << '\n'; break; } - call callee(instructions[pc].operation); - for (vector<reagent>::iterator p = instructions[pc].ingredients.begin(); p != instructions[pc].ingredients.end(); ++p) { - callee.ingredient_atoms.push_back(read_memory(*p)); - } - rr.calls.push(callee); + rr.calls.push(call(instructions[pc].operation)); continue; // not done with caller; don't increment pc } -:(scenario "next_ingredient") -recipe main [ - f 2:literal -] -recipe f [ - 12:integer <- next_ingredient - 13:integer <- add 1:literal, 12:integer -] -+run: instruction f/1 -+mem: location 12 is 2 -+mem: storing in location 13 - -:(before "End Globals") -const int NEXT_INGREDIENT = 22; -:(before "End Primitive Recipe Numbers") -Recipe_number["next_ingredient"] = NEXT_INGREDIENT; -assert(Next_recipe_number == NEXT_INGREDIENT); -Next_recipe_number++; -:(before "End Primitive Recipe Implementations") -case NEXT_INGREDIENT: { - if (rr.calls.top().next_ingredient_to_process < rr.calls.top().ingredient_atoms.size()) { - trace("run") << "product 0 is " - << rr.calls.top().ingredient_atoms[rr.calls.top().next_ingredient_to_process][0]; - write_memory(instructions[pc].products[0], - rr.calls.top().ingredient_atoms[rr.calls.top().next_ingredient_to_process]); - ++rr.calls.top().next_ingredient_to_process; - } - break; +:(replace{} "inline bool done(routine& rr)") +inline bool done(routine& rr) { + return rr.calls.empty(); } -:(scenario "reply") -recipe main [ - 3:integer, 4:integer <- f 2:literal -] -recipe f [ - 12:integer <- next_ingredient - 13:integer <- add 1:literal, 12:integer - reply 12:integer, 13:integer -] -+run: instruction main/0 -+run: result 0 is 1[2...] -+mem: storing in location 3 -+run: result 1 is 1[3...] -+mem: storing in location 4 - -:(before "End Globals") -const int REPLY = 23; -:(before "End Primitive Recipe Numbers") -Recipe_number["reply"] = REPLY; -assert(Next_recipe_number == REPLY); -Next_recipe_number++; -:(before "End Primitive Recipe Implementations") -case REPLY: { - vector<vector<int> > callee_results; - for (size_t i = 0; i < instructions[pc].ingredients.size(); ++i) { - callee_results.push_back(read_memory(instructions[pc].ingredients[i])); - } +:(before "Running one instruction.") +// when we reach the end of one call, we may reach the end of the one below +// it, and the one below that, and so on +while (running_at(rr) >= steps(rr).size()) { rr.calls.pop(); - size_t& caller_pc = rr.calls.top().pc; - instruction& caller_instruction = Recipe[rr.calls.top().running_recipe].steps[caller_pc]; - assert(caller_instruction.products.size() <= callee_results.size()); - for (size_t i = 0; i < caller_instruction.products.size(); ++i) { - trace("run") << "result " << i << " is " << callee_results[i].size() << "[" << callee_results[i][0] << "...]"; - write_memory(caller_instruction.products[i], callee_results[i]); - } - ++caller_pc; - break; + if (rr.calls.empty()) return; + // todo: no results returned warning + ++running_at(rr); } |