:(scenario "calling_recipe") recipe main [ f ] recipe f [ 3:integer <- add 2:literal, 2:literal ] +mem: storing in location 3 :(before "End Call Fields") vector > 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) {} :(replace{} "End Primitive Recipe Implementations." then "default:") default: { // not a primitive; try to look for a matching recipe if (Recipe.find(instructions[pc].operation) == Recipe.end()) { raise << "undefined operation " << instructions[pc].operation << '\n'; break; } call callee(instructions[pc].operation); for (vector::iterator p = instructions[pc].ingredients.begin(); p != instructions[pc].ingredients.end(); ++p) { callee.ingredient_atoms.push_back(read_memory(*p)); } rr.calls.push(callee); 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; } :(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 > callee_results; for (size_t i = 0; i < instructions[pc].ingredients.size(); ++i) { callee_results.push_back(read_memory(instructions[pc].ingredients[i])); } 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; }