This commit is contained in:
Kartik K. Agaram 2015-10-01 17:30:14 -07:00
parent 16386f766e
commit 166e3c0d40
16 changed files with 482 additions and 176 deletions

View File

@ -44,6 +44,10 @@ case TRACE: {
STASH,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["stash"] = STASH;
:(before "End Primitive Recipe Checks")
case STASH: {
break;
}
:(before "End Primitive Recipe Implementations")
case STASH: {
ostringstream out;
@ -89,6 +93,10 @@ string print_mu(const reagent& r, const vector<double>& data) {
HIDE_WARNINGS,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["hide-warnings"] = HIDE_WARNINGS;
:(before "End Primitive Recipe Checks")
case HIDE_WARNINGS: {
break;
}
:(before "End Primitive Recipe Implementations")
case HIDE_WARNINGS: {
Hide_warnings = true;
@ -99,6 +107,10 @@ case HIDE_WARNINGS: {
SHOW_WARNINGS,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["show-warnings"] = SHOW_WARNINGS;
:(before "End Primitive Recipe Checks")
case SHOW_WARNINGS: {
break;
}
:(before "End Primitive Recipe Implementations")
case SHOW_WARNINGS: {
Hide_warnings = false;
@ -109,6 +121,10 @@ case SHOW_WARNINGS: {
_START_TRACING,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["$start-tracing"] = _START_TRACING;
:(before "End Primitive Recipe Checks")
case _START_TRACING: {
break;
}
:(before "End Primitive Recipe Implementations")
case _START_TRACING: {
if (current_instruction().ingredients.empty())
@ -122,6 +138,10 @@ case _START_TRACING: {
_STOP_TRACING,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["$stop-tracing"] = _STOP_TRACING;
:(before "End Primitive Recipe Checks")
case _STOP_TRACING: {
break;
}
:(before "End Primitive Recipe Implementations")
case _STOP_TRACING: {
Trace_stream->dump_layer = "";
@ -132,6 +152,10 @@ case _STOP_TRACING: {
_CLOSE_TRACE,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["$close-trace"] = _CLOSE_TRACE;
:(before "End Primitive Recipe Checks")
case _CLOSE_TRACE: {
break;
}
:(before "End Primitive Recipe Implementations")
case _CLOSE_TRACE: {
if (Trace_stream) {
@ -145,6 +169,10 @@ case _CLOSE_TRACE: {
_DUMP_TRACE,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["$dump-trace"] = _DUMP_TRACE;
:(before "End Primitive Recipe Checks")
case _DUMP_TRACE: {
break;
}
:(before "End Primitive Recipe Implementations")
case _DUMP_TRACE: {
if (ingredients.empty()) {
@ -160,6 +188,10 @@ case _DUMP_TRACE: {
_CLEAR_TRACE,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["$clear-trace"] = _CLEAR_TRACE;
:(before "End Primitive Recipe Checks")
case _CLEAR_TRACE: {
break;
}
:(before "End Primitive Recipe Implementations")
case _CLEAR_TRACE: {
CLEAR_TRACE;
@ -209,6 +241,10 @@ case ASSERT: {
_PRINT,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["$print"] = _PRINT;
:(before "End Primitive Recipe Checks")
case _PRINT: {
break;
}
:(before "End Primitive Recipe Implementations")
case _PRINT: {
for (long long int i = 0; i < SIZE(ingredients); ++i) {
@ -234,6 +270,10 @@ case _PRINT: {
_EXIT,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["$exit"] = _EXIT;
:(before "End Primitive Recipe Checks")
case _EXIT: {
break;
}
:(before "End Primitive Recipe Implementations")
case _EXIT: {
exit(0);
@ -266,6 +306,10 @@ case _SYSTEM: {
_DUMP_MEMORY,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["$dump-memory"] = _DUMP_MEMORY;
:(before "End Primitive Recipe Checks")
case _DUMP_MEMORY: {
break;
}
:(before "End Primitive Recipe Implementations")
case _DUMP_MEMORY: {
dump_memory();

View File

@ -35,12 +35,16 @@ for (long long int i = 0; i < SIZE(ingredients); ++i) {
NEXT_INGREDIENT,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["next-ingredient"] = NEXT_INGREDIENT;
:(before "End Primitive Recipe Implementations")
:(before "End Primitive Recipe Checks")
case NEXT_INGREDIENT: {
if (!ingredients.empty()) {
raise << maybe(current_recipe_name()) << "'next-ingredient' didn't expect any ingredients in '" << current_instruction().to_string() << "'\n" << end();
if (!inst.ingredients.empty()) {
raise << maybe(Recipe[r].name) << "'next-ingredient' didn't expect any ingredients in '" << inst.to_string() << "'\n" << end();
break;
}
break;
}
:(before "End Primitive Recipe Implementations")
case NEXT_INGREDIENT: {
assert(!Current_routine->calls.empty());
if (Current_routine->calls.front().next_ingredient_to_process < SIZE(Current_routine->calls.front().ingredient_atoms)) {
products.push_back(
@ -88,6 +92,10 @@ recipe f [
REWIND_INGREDIENTS,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["rewind-ingredients"] = REWIND_INGREDIENTS;
:(before "End Primitive Recipe Checks")
case REWIND_INGREDIENTS: {
break;
}
:(before "End Primitive Recipe Implementations")
case REWIND_INGREDIENTS: {
Current_routine->calls.front().next_ingredient_to_process = 0;
@ -109,17 +117,20 @@ recipe f [
INGREDIENT,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["ingredient"] = INGREDIENT;
:(before "End Primitive Recipe Checks")
case INGREDIENT: {
if (SIZE(inst.ingredients) != 1) {
raise << maybe(Recipe[r].name) << "'ingredient' expects exactly one ingredient, but got '" << inst.to_string() << "'\n" << end();
break;
}
if (!is_literal(inst.ingredients.at(0)) && !is_mu_scalar(inst.ingredients.at(0))) {
raise << maybe(Recipe[r].name) << "'ingredient' expects a literal ingredient, but got " << inst.ingredients.at(0).original_string << '\n' << end();
break;
}
break;
}
:(before "End Primitive Recipe Implementations")
case INGREDIENT: {
if (SIZE(ingredients) != 1) {
raise << maybe(current_recipe_name()) << "'ingredient' expects exactly one ingredient, but got '" << current_instruction().to_string() << "'\n" << end();
break;
}
if (!is_literal(current_instruction().ingredients.at(0))) {
raise << maybe(current_recipe_name()) << "'ingredient' expects a literal ingredient, but got " << current_instruction().ingredients.at(0).original_string << '\n' << end();
break;
}
assert(scalar(ingredients.at(0)));
if (static_cast<long long int>(ingredients.at(0).at(0)) < SIZE(Current_routine->calls.front().ingredient_atoms)) {
Current_routine->calls.front().next_ingredient_to_process = ingredients.at(0).at(0);
products.push_back(

View File

@ -16,6 +16,10 @@ recipe f [
REPLY,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["reply"] = REPLY;
:(before "End Primitive Recipe Checks")
case REPLY: {
break; // continue to process rest of *caller* instruction
}
:(before "End Primitive Recipe Implementations")
case REPLY: {
// Starting Reply

View File

@ -40,20 +40,21 @@ if (!r.properties.at(0).second.empty() && r.properties.at(0).second.at(0) == "re
CALL,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["call"] = CALL;
:(before "End Primitive Recipe Checks")
case CALL: {
if (inst.ingredients.empty()) {
raise << maybe(Recipe[r].name) << "'call' requires at least one ingredient (the recipe to call)\n" << end();
break;
}
if (!is_mu_scalar(inst.ingredients.at(0))) {
raise << maybe(Recipe[r].name) << "first ingredient of 'call' should be a recipe, but got " << inst.ingredients.at(0).original_string << '\n' << end();
break;
}
break;
}
:(before "End Primitive Recipe Implementations")
case CALL: {
if (ingredients.empty()) {
raise << maybe(current_recipe_name()) << "'call' requires at least one ingredient (the recipe to call)\n" << end();
break;
}
// Begin Call
if (!scalar(ingredients.at(0))) {
raise << maybe(current_recipe_name()) << "first ingredient of 'call' should be a recipe, but got " << current_instruction().ingredients.at(0).original_string << '\n' << end();
break;
}
// todo: when we start doing type checking this will be a prime point of
// attention, so we don't accidentally allow external data to a program to
// run as code.
Current_routine->calls.push_front(call(ingredients.at(0).at(0)));
ingredients.erase(ingredients.begin()); // drop the callee
goto call_housekeeping;

View File

@ -144,20 +144,20 @@ parent_index = -1;
START_RUNNING,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["start-running"] = START_RUNNING;
:(before "End Primitive Recipe Checks")
case START_RUNNING: {
if (inst.ingredients.empty()) {
raise << maybe(Recipe[r].name) << "'start-running' requires at least one ingredient: the recipe to start running\n" << end();
break;
}
if (!is_mu_scalar(inst.ingredients.at(0))) {
raise << maybe(Recipe[r].name) << "first ingredient of 'start-running' should be a recipe, but got " << inst.ingredients.at(0).original_string << '\n' << end();
break;
}
break;
}
:(before "End Primitive Recipe Implementations")
case START_RUNNING: {
if (ingredients.empty()) {
raise << "'start-running' requires at least one ingredient: the recipe to start running\n" << end();
break;
}
if (!scalar(ingredients.at(0))) {
raise << "first ingredient of 'start-running' should be a recipe, but got " << current_instruction().ingredients.at(0).original_string << '\n' << end();
break;
}
if (!ingredients.at(0).at(0)) {
raise << "'start-running' received non-existent recipe: '" << current_instruction().to_string() << "'\n" << end();
break;
}
routine* new_routine = new routine(ingredients.at(0).at(0));
new_routine->parent_index = Current_routine_index;
// populate ingredients
@ -330,16 +330,20 @@ recipe f2 [
ROUTINE_STATE,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["routine-state"] = ROUTINE_STATE;
:(before "End Primitive Recipe Checks")
case ROUTINE_STATE: {
if (SIZE(inst.ingredients) != 1) {
raise << maybe(Recipe[r].name) << "'routine-state' requires exactly one ingredient, but got " << inst.to_string() << '\n' << end();
break;
}
if (!is_mu_scalar(inst.ingredients.at(0))) {
raise << maybe(Recipe[r].name) << "first ingredient of 'routine-state' should be a routine id generated by 'start-running', but got " << inst.ingredients.at(0).original_string << '\n' << end();
break;
}
break;
}
:(before "End Primitive Recipe Implementations")
case ROUTINE_STATE: {
if (SIZE(ingredients) != 1) {
raise << maybe(current_recipe_name()) << "'routine-state' requires exactly one ingredient, but got " << current_instruction().to_string() << '\n' << end();
break;
}
if (!scalar(ingredients.at(0))) {
raise << maybe(current_recipe_name()) << "first ingredient of 'routine-state' should be a routine id generated by 'start-running', but got " << current_instruction().ingredients.at(0).original_string << '\n' << end();
break;
}
long long int id = ingredients.at(0).at(0);
long long int result = -1;
for (long long int i = 0; i < SIZE(Routines); ++i) {
@ -359,16 +363,20 @@ case ROUTINE_STATE: {
RESTART,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["restart"] = RESTART;
:(before "End Primitive Recipe Checks")
case RESTART: {
if (SIZE(inst.ingredients) != 1) {
raise << maybe(Recipe[r].name) << "'restart' requires exactly one ingredient, but got " << inst.to_string() << '\n' << end();
break;
}
if (!is_mu_scalar(inst.ingredients.at(0))) {
raise << maybe(Recipe[r].name) << "first ingredient of 'restart' should be a routine id generated by 'start-running', but got " << inst.ingredients.at(0).original_string << '\n' << end();
break;
}
break;
}
:(before "End Primitive Recipe Implementations")
case RESTART: {
if (SIZE(ingredients) != 1) {
raise << maybe(current_recipe_name()) << "'restart' requires exactly one ingredient, but got " << current_instruction().to_string() << '\n' << end();
break;
}
if (!scalar(ingredients.at(0))) {
raise << maybe(current_recipe_name()) << "first ingredient of 'restart' should be a routine id generated by 'start-running', but got " << current_instruction().ingredients.at(0).original_string << '\n' << end();
break;
}
long long int id = ingredients.at(0).at(0);
for (long long int i = 0; i < SIZE(Routines); ++i) {
if (Routines.at(i)->id == id) {
@ -383,16 +391,20 @@ case RESTART: {
STOP,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["stop"] = STOP;
:(before "End Primitive Recipe Checks")
case STOP: {
if (SIZE(inst.ingredients) != 1) {
raise << maybe(Recipe[r].name) << "'stop' requires exactly one ingredient, but got " << inst.to_string() << '\n' << end();
break;
}
if (!is_mu_scalar(inst.ingredients.at(0))) {
raise << maybe(Recipe[r].name) << "first ingredient of 'stop' should be a routine id generated by 'start-running', but got " << inst.ingredients.at(0).original_string << '\n' << end();
break;
}
break;
}
:(before "End Primitive Recipe Implementations")
case STOP: {
if (SIZE(ingredients) != 1) {
raise << maybe(current_recipe_name()) << "'stop' requires exactly one ingredient, but got " << current_instruction().to_string() << '\n' << end();
break;
}
if (!scalar(ingredients.at(0))) {
raise << maybe(current_recipe_name()) << "first ingredient of 'stop' should be a routine id generated by 'start-running', but got " << current_instruction().ingredients.at(0).original_string << '\n' << end();
break;
}
long long int id = ingredients.at(0).at(0);
for (long long int i = 0; i < SIZE(Routines); ++i) {
if (Routines.at(i)->id == id) {
@ -407,6 +419,10 @@ case STOP: {
_DUMP_ROUTINES,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["$dump-routines"] = _DUMP_ROUTINES;
:(before "End Primitive Recipe Checks")
case _DUMP_ROUTINES: {
break;
}
:(before "End Primitive Recipe Implementations")
case _DUMP_ROUTINES: {
for (long long int i = 0; i < SIZE(Routines); ++i) {
@ -457,20 +473,24 @@ limit = -1; /* no limit */
LIMIT_TIME,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["limit-time"] = LIMIT_TIME;
:(before "End Primitive Recipe Checks")
case LIMIT_TIME: {
if (SIZE(inst.ingredients) != 2) {
raise << maybe(Recipe[r].name) << "'limit-time' requires exactly two ingredient, but got " << inst.to_string() << '\n' << end();
break;
}
if (!is_mu_scalar(inst.ingredients.at(0))) {
raise << maybe(Recipe[r].name) << "first ingredient of 'limit-time' should be a routine id generated by 'start-running', but got " << inst.ingredients.at(0).original_string << '\n' << end();
break;
}
if (!is_mu_scalar(inst.ingredients.at(1))) {
raise << maybe(Recipe[r].name) << "second ingredient of 'limit-time' should be a number (of instructions to run for), but got " << inst.ingredients.at(1).original_string << '\n' << end();
break;
}
break;
}
:(before "End Primitive Recipe Implementations")
case LIMIT_TIME: {
if (SIZE(ingredients) != 2) {
raise << maybe(current_recipe_name()) << "'limit-time' requires exactly two ingredient, but got " << current_instruction().to_string() << '\n' << end();
break;
}
if (!scalar(ingredients.at(0))) {
raise << maybe(current_recipe_name()) << "first ingredient of 'limit-time' should be a routine id generated by 'start-running', but got " << current_instruction().ingredients.at(0).original_string << '\n' << end();
break;
}
if (!scalar(ingredients.at(1))) {
raise << maybe(current_recipe_name()) << "second ingredient of 'limit-time' should be a number (of instructions to run for), but got " << current_instruction().ingredients.at(1).original_string << '\n' << end();
break;
}
long long int id = ingredients.at(0).at(0);
for (long long int i = 0; i < SIZE(Routines); ++i) {
if (Routines.at(i)->id == id) {

View File

@ -34,6 +34,10 @@ waiting_on_location = old_value_of_waiting_location = 0;
WAIT_FOR_LOCATION,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["wait-for-location"] = WAIT_FOR_LOCATION;
:(before "End Primitive Recipe Checks")
case WAIT_FOR_LOCATION: {
break;
}
:(before "End Primitive Recipe Implementations")
case WAIT_FOR_LOCATION: {
reagent loc = canonize(current_instruction().ingredients.at(0));
@ -88,16 +92,20 @@ waiting_on_routine = 0;
WAIT_FOR_ROUTINE,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["wait-for-routine"] = WAIT_FOR_ROUTINE;
:(before "End Primitive Recipe Checks")
case WAIT_FOR_ROUTINE: {
if (SIZE(inst.ingredients) != 1) {
raise << maybe(Recipe[r].name) << "'wait-for-routine' requires exactly one ingredient, but got " << inst.to_string() << '\n' << end();
break;
}
if (!is_mu_scalar(inst.ingredients.at(0))) {
raise << maybe(Recipe[r].name) << "first ingredient of 'wait-for-routine' should be a routine id generated by 'start-running', but got " << inst.ingredients.at(0).original_string << '\n' << end();
break;
}
break;
}
:(before "End Primitive Recipe Implementations")
case WAIT_FOR_ROUTINE: {
if (SIZE(ingredients) != 1) {
raise << maybe(current_recipe_name()) << "'wait-for-routine' requires exactly one ingredient, but got " << current_instruction().to_string() << '\n' << end();
break;
}
if (!scalar(ingredients.at(0))) {
raise << maybe(current_recipe_name()) << "first ingredient of 'wait-for-routine' should be a routine id generated by 'start-running', but got " << current_instruction().ingredients.at(0).original_string << '\n' << end();
break;
}
if (ingredients.at(0).at(0) == Current_routine->id) {
raise << maybe(current_recipe_name()) << "routine can't wait for itself! " << current_instruction().to_string() << '\n' << end();
break;
@ -130,6 +138,10 @@ for (long long int i = 0; i < SIZE(Routines); ++i) {
SWITCH,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["switch"] = SWITCH;
:(before "End Primitive Recipe Checks")
case SWITCH: {
break;
}
:(before "End Primitive Recipe Implementations")
case SWITCH: {
long long int id = some_other_running_routine();

View File

@ -53,16 +53,21 @@ if (inst.operation == Recipe_ordinal["new"]) {
NEW,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["new"] = NEW;
:(before "End Primitive Recipe Checks")
case NEW: {
if (inst.ingredients.empty() || SIZE(inst.ingredients) > 2) {
raise << maybe(Recipe[r].name) << "'new' requires one or two ingredients, but got " << inst.to_string() << '\n' << end();
break;
}
reagent type = inst.ingredients.at(0);
if (!is_mu_scalar(type) && !is_literal(type)) {
raise << maybe(Recipe[r].name) << "first ingredient of 'new' should be a type, but got " << type.original_string << '\n' << end();
break;
}
break;
}
:(before "End Primitive Recipe Implementations")
case NEW: {
if (ingredients.empty() || SIZE(ingredients) > 2) {
raise << maybe(current_recipe_name()) << "'new' requires one or two ingredients, but got " << current_instruction().to_string() << '\n' << end();
break;
}
if (!scalar(ingredients.at(0))) {
raise << maybe(current_recipe_name()) << "first ingredient of 'new' should be a type, but got " << current_instruction().ingredients.at(0).original_string << '\n' << end();
break;
}
// compute the space we need
long long int size = 0;
long long int array_length = 0;
@ -213,22 +218,24 @@ Free_list.clear();
ABANDON,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["abandon"] = ABANDON;
:(before "End Primitive Recipe Checks")
case ABANDON: {
if (SIZE(inst.ingredients) != 1) {
raise << maybe(Recipe[r].name) << "'abandon' requires one ingredient, but got '" << inst.to_string() << "'\n" << end();
break;
}
reagent types = inst.ingredients.at(0);
canonize_type(types);
if (types.types.empty() || types.types.at(0) != Type_ordinal["address"]) {
raise << maybe(Recipe[r].name) << "first ingredient of 'abandon' should be an address, but got " << inst.ingredients.at(0).original_string << '\n' << end();
break;
}
break;
}
:(before "End Primitive Recipe Implementations")
case ABANDON: {
if (SIZE(ingredients) != 1) {
raise << maybe(current_recipe_name()) << "'abandon' requires one ingredient, but got '" << current_instruction().to_string() << "'\n" << end();
break;
}
if (!scalar(ingredients.at(0))) {
raise << maybe(current_recipe_name()) << "first ingredient of 'abandon' should be an address, but got " << current_instruction().ingredients.at(0).original_string << '\n' << end();
break;
}
long long int address = ingredients.at(0).at(0);
reagent types = canonize(current_instruction().ingredients.at(0));
if (types.types.empty() || types.types.at(0) != Type_ordinal["address"]) {
raise << maybe(current_recipe_name()) << "first ingredient of 'abandon' should be an address, but got " << current_instruction().ingredients.at(0).original_string << '\n' << end();
break;
}
reagent target_type = lookup_memory(types);
abandon(address, size_of(target_type));
break;
@ -317,12 +324,12 @@ recipe main [
}
:(after "case NEW" following "Primitive Recipe Implementations")
if (is_literal(current_instruction().ingredients.at(0))
&& current_instruction().ingredients.at(0).properties.at(0).second.at(0) == "literal-string") {
products.resize(1);
products.at(0).push_back(new_mu_string(current_instruction().ingredients.at(0).name));
break;
}
if (is_literal(current_instruction().ingredients.at(0))
&& current_instruction().ingredients.at(0).properties.at(0).second.at(0) == "literal-string") {
products.resize(1);
products.at(0).push_back(new_mu_string(current_instruction().ingredients.at(0).name));
break;
}
:(code)
long long int new_mu_string(const string& contents) {

View File

@ -189,6 +189,10 @@ recipe main [
RUN,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["run"] = RUN;
:(before "End Primitive Recipe Checks")
case RUN: {
break;
}
:(before "End Primitive Recipe Implementations")
case RUN: {
ostringstream tmp;
@ -243,6 +247,10 @@ recipe main [
MEMORY_SHOULD_CONTAIN,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["memory-should-contain"] = MEMORY_SHOULD_CONTAIN;
:(before "End Primitive Recipe Checks")
case MEMORY_SHOULD_CONTAIN: {
break;
}
:(before "End Primitive Recipe Implementations")
case MEMORY_SHOULD_CONTAIN: {
if (!Passed) break;
@ -404,6 +412,10 @@ recipe main [
TRACE_SHOULD_CONTAIN,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["trace-should-contain"] = TRACE_SHOULD_CONTAIN;
:(before "End Primitive Recipe Checks")
case TRACE_SHOULD_CONTAIN: {
break;
}
:(before "End Primitive Recipe Implementations")
case TRACE_SHOULD_CONTAIN: {
if (!Passed) break;
@ -496,6 +508,10 @@ recipe main [
TRACE_SHOULD_NOT_CONTAIN,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["trace-should-not-contain"] = TRACE_SHOULD_NOT_CONTAIN;
:(before "End Primitive Recipe Checks")
case TRACE_SHOULD_NOT_CONTAIN: {
break;
}
:(before "End Primitive Recipe Implementations")
case TRACE_SHOULD_NOT_CONTAIN: {
if (!Passed) break;
@ -556,22 +572,26 @@ recipe main [
CHECK_TRACE_COUNT_FOR_LABEL,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["check-trace-count-for-label"] = CHECK_TRACE_COUNT_FOR_LABEL;
:(before "End Primitive Recipe Checks")
case CHECK_TRACE_COUNT_FOR_LABEL: {
if (SIZE(inst.ingredients) != 2) {
raise << maybe(Recipe[r].name) << "'check-trace-for-label' requires exactly two ingredients, but got '" << inst.to_string() << "'\n" << end();
break;
}
if (!is_mu_scalar(inst.ingredients.at(0))) {
raise << maybe(Recipe[r].name) << "first ingredient of 'check-trace-for-label' should be a number (count), but got " << inst.ingredients.at(0).original_string << '\n' << end();
break;
}
if (!is_literal_string(inst.ingredients.at(1))) {
raise << maybe(Recipe[r].name) << "second ingredient of 'check-trace-for-label' should be a literal string (label), but got " << inst.ingredients.at(1).original_string << '\n' << end();
break;
}
break;
}
:(before "End Primitive Recipe Implementations")
case CHECK_TRACE_COUNT_FOR_LABEL: {
if (!Passed) break;
if (SIZE(current_instruction().ingredients) != 2) {
raise << maybe(current_recipe_name()) << "'check-trace-for-label' requires exactly two ingredients, but got '" << current_instruction().to_string() << "'\n" << end();
break;
}
if (!scalar(ingredients.at(0))) {
raise << maybe(current_recipe_name()) << "first ingredient of 'check-trace-for-label' should be a number (count), but got " << current_instruction().ingredients.at(0).original_string << '\n' << end();
break;
}
long long int expected_count = ingredients.at(0).at(0);
if (!is_literal_string(current_instruction().ingredients.at(1))) {
raise << maybe(current_recipe_name()) << "second ingredient of 'check-trace-for-label' should be a literal string (label), but got " << current_instruction().ingredients.at(1).original_string << '\n' << end();
break;
}
string label = current_instruction().ingredients.at(1).name;
long long int count = trace_count(label);
if (count != expected_count) {

View File

@ -21,6 +21,10 @@ Type[continuation].name = "continuation";
CURRENT_CONTINUATION,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["current-continuation"] = CURRENT_CONTINUATION;
:(before "End Primitive Recipe Checks")
case CURRENT_CONTINUATION: {
break;
}
:(before "End Primitive Recipe Implementations")
case CURRENT_CONTINUATION: {
// copy the current call stack
@ -38,12 +42,16 @@ case CURRENT_CONTINUATION: {
CONTINUE_FROM,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["continue-from"] = CONTINUE_FROM;
:(before "End Primitive Recipe Implementations")
:(before "End Primitive Recipe Checks")
case CONTINUE_FROM: {
if (!scalar(ingredients.at(0))) {
raise << maybe(current_recipe_name()) << "first ingredient of 'continue-from' should be a continuation id generated by 'current-continuation', but got " << current_instruction().ingredients.at(0).original_string << '\n' << end();
if (!is_mu_scalar(inst.ingredients.at(0))) {
raise << maybe(Recipe[r].name) << "first ingredient of 'continue-from' should be a continuation id generated by 'current-continuation', but got " << inst.ingredients.at(0).original_string << '\n' << end();
break;
}
break;
}
:(before "End Primitive Recipe Implementations")
case CONTINUE_FROM: {
long long int c = ingredients.at(0).at(0);
Current_routine->calls = Continuation[c]; // deep copy; calls have no pointers
continue; // skip rest of this instruction
@ -166,6 +174,10 @@ is_reset = false;
CREATE_DELIMITED_CONTINUATION,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["create-delimited-continuation"] = CREATE_DELIMITED_CONTINUATION;
:(before "End Primitive Recipe Checks")
case CREATE_DELIMITED_CONTINUATION: {
break;
}
:(before "End Primitive Recipe Implementations")
case CREATE_DELIMITED_CONTINUATION: {
Current_routine->calls.front().is_reset = true;
@ -188,6 +200,10 @@ Next_delimited_continuation_id = 0;
REPLY_DELIMITED_CONTINUATION,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["reply-delimited-continuation"] = REPLY_DELIMITED_CONTINUATION;
:(before "End Primitive Recipe Checks")
case REPLY_DELIMITED_CONTINUATION: {
break;
}
:(before "End Primitive Recipe Implementations")
case REPLY_DELIMITED_CONTINUATION: {
// first clear any existing ingredients, to isolate the creation of the

View File

@ -2,6 +2,10 @@
RANDOM,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["random"] = RANDOM;
:(before "End Primitive Recipe Checks")
case RANDOM: {
break;
}
:(before "End Primitive Recipe Implementations")
case RANDOM: {
// todo: limited range of numbers, might be imperfectly random
@ -15,6 +19,10 @@ case RANDOM: {
MAKE_RANDOM_NONDETERMINISTIC,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["make-random-nondeterministic"] = MAKE_RANDOM_NONDETERMINISTIC;
:(before "End Primitive Recipe Checks")
case MAKE_RANDOM_NONDETERMINISTIC: {
break;
}
:(before "End Primitive Recipe Implementations")
case MAKE_RANDOM_NONDETERMINISTIC: {
srand(time(NULL));
@ -25,16 +33,20 @@ case MAKE_RANDOM_NONDETERMINISTIC: {
ROUND,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["round"] = ROUND;
:(before "End Primitive Recipe Checks")
case ROUND: {
if (SIZE(inst.ingredients) != 1) {
raise << maybe(Recipe[r].name) << "'round' requires exactly one ingredient, but got " << inst.to_string() << '\n' << end();
break;
}
if (!is_mu_scalar(inst.ingredients.at(0))) {
raise << maybe(Recipe[r].name) << "first ingredient of 'round' should be a number, but got " << inst.ingredients.at(0).original_string << '\n' << end();
break;
}
break;
}
:(before "End Primitive Recipe Implementations")
case ROUND: {
if (SIZE(ingredients) != 1) {
raise << maybe(current_recipe_name()) << "'round' requires exactly one ingredient, but got " << current_instruction().to_string() << '\n' << end();
break;
}
if (!scalar(ingredients.at(0))) {
raise << maybe(current_recipe_name()) << "first ingredient of 'round' should be a number, but got " << current_instruction().ingredients.at(0).original_string << '\n' << end();
break;
}
products.resize(1);
products.at(0).push_back(rint(ingredients.at(0).at(0)));
break;

View File

@ -10,6 +10,10 @@ bool Autodisplay = true;
OPEN_CONSOLE,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["open-console"] = OPEN_CONSOLE;
:(before "End Primitive Recipe Checks")
case OPEN_CONSOLE: {
break;
}
:(before "End Primitive Recipe Implementations")
case OPEN_CONSOLE: {
tb_init();
@ -28,6 +32,10 @@ case OPEN_CONSOLE: {
CLOSE_CONSOLE,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["close-console"] = CLOSE_CONSOLE;
:(before "End Primitive Recipe Checks")
case CLOSE_CONSOLE: {
break;
}
:(before "End Primitive Recipe Implementations")
case CLOSE_CONSOLE: {
tb_shutdown();
@ -41,6 +49,10 @@ tb_shutdown();
CLEAR_DISPLAY,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["clear-display"] = CLEAR_DISPLAY;
:(before "End Primitive Recipe Checks")
case CLEAR_DISPLAY: {
break;
}
:(before "End Primitive Recipe Implementations")
case CLEAR_DISPLAY: {
tb_clear();
@ -52,6 +64,10 @@ case CLEAR_DISPLAY: {
SYNC_DISPLAY,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["sync-display"] = SYNC_DISPLAY;
:(before "End Primitive Recipe Checks")
case SYNC_DISPLAY: {
break;
}
:(before "End Primitive Recipe Implementations")
case SYNC_DISPLAY: {
tb_sync();
@ -62,6 +78,10 @@ case SYNC_DISPLAY: {
CLEAR_LINE_ON_DISPLAY,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["clear-line-on-display"] = CLEAR_LINE_ON_DISPLAY;
:(before "End Primitive Recipe Checks")
case CLEAR_LINE_ON_DISPLAY: {
break;
}
:(before "End Primitive Recipe Implementations")
case CLEAR_LINE_ON_DISPLAY: {
long long int width = tb_width();
@ -77,6 +97,10 @@ case CLEAR_LINE_ON_DISPLAY: {
PRINT_CHARACTER_TO_DISPLAY,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["print-character-to-display"] = PRINT_CHARACTER_TO_DISPLAY;
:(before "End Primitive Recipe Checks")
case PRINT_CHARACTER_TO_DISPLAY: {
break;
}
:(before "End Primitive Recipe Implementations")
case PRINT_CHARACTER_TO_DISPLAY: {
int h=tb_height(), w=tb_width();
@ -139,6 +163,10 @@ case PRINT_CHARACTER_TO_DISPLAY: {
CURSOR_POSITION_ON_DISPLAY,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["cursor-position-on-display"] = CURSOR_POSITION_ON_DISPLAY;
:(before "End Primitive Recipe Checks")
case CURSOR_POSITION_ON_DISPLAY: {
break;
}
:(before "End Primitive Recipe Implementations")
case CURSOR_POSITION_ON_DISPLAY: {
products.resize(2);
@ -151,21 +179,25 @@ case CURSOR_POSITION_ON_DISPLAY: {
MOVE_CURSOR_ON_DISPLAY,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["move-cursor-on-display"] = MOVE_CURSOR_ON_DISPLAY;
:(before "End Primitive Recipe Checks")
case MOVE_CURSOR_ON_DISPLAY: {
if (SIZE(inst.ingredients) != 2) {
raise << maybe(Recipe[r].name) << "'move-cursor-on-display' requires two ingredients, but got " << inst.to_string() << '\n' << end();
break;
}
if (!is_mu_scalar(inst.ingredients.at(0))) {
raise << maybe(Recipe[r].name) << "first ingredient of 'move-cursor-on-display' should be a row number, but got " << inst.ingredients.at(0).original_string << '\n' << end();
break;
}
if (!is_mu_scalar(inst.ingredients.at(1))) {
raise << maybe(Recipe[r].name) << "second ingredient of 'move-cursor-on-display' should be a column number, but got " << inst.ingredients.at(1).original_string << '\n' << end();
break;
}
break;
}
:(before "End Primitive Recipe Implementations")
case MOVE_CURSOR_ON_DISPLAY: {
if (SIZE(ingredients) != 2) {
raise << maybe(current_recipe_name()) << "'move-cursor-on-display' requires two ingredients, but got " << current_instruction().to_string() << '\n' << end();
break;
}
if (!scalar(ingredients.at(0))) {
raise << maybe(current_recipe_name()) << "first ingredient of 'move-cursor-on-display' should be a row number, but got " << current_instruction().ingredients.at(0).original_string << '\n' << end();
break;
}
Display_row = ingredients.at(0).at(0);
if (!scalar(ingredients.at(1))) {
raise << maybe(current_recipe_name()) << "second ingredient of 'move-cursor-on-display' should be a column number, but got " << current_instruction().ingredients.at(1).original_string << '\n' << end();
break;
}
Display_column = ingredients.at(1).at(0);
tb_set_cursor(Display_column, Display_row);
if (Autodisplay) tb_present();
@ -176,6 +208,10 @@ case MOVE_CURSOR_ON_DISPLAY: {
MOVE_CURSOR_DOWN_ON_DISPLAY,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["move-cursor-down-on-display"] = MOVE_CURSOR_DOWN_ON_DISPLAY;
:(before "End Primitive Recipe Checks")
case MOVE_CURSOR_DOWN_ON_DISPLAY: {
break;
}
:(before "End Primitive Recipe Implementations")
case MOVE_CURSOR_DOWN_ON_DISPLAY: {
int h=tb_height();
@ -192,6 +228,10 @@ case MOVE_CURSOR_DOWN_ON_DISPLAY: {
MOVE_CURSOR_UP_ON_DISPLAY,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["move-cursor-up-on-display"] = MOVE_CURSOR_UP_ON_DISPLAY;
:(before "End Primitive Recipe Checks")
case MOVE_CURSOR_UP_ON_DISPLAY: {
break;
}
:(before "End Primitive Recipe Implementations")
case MOVE_CURSOR_UP_ON_DISPLAY: {
if (Display_row > 0) {
@ -206,6 +246,10 @@ case MOVE_CURSOR_UP_ON_DISPLAY: {
MOVE_CURSOR_RIGHT_ON_DISPLAY,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["move-cursor-right-on-display"] = MOVE_CURSOR_RIGHT_ON_DISPLAY;
:(before "End Primitive Recipe Checks")
case MOVE_CURSOR_RIGHT_ON_DISPLAY: {
break;
}
:(before "End Primitive Recipe Implementations")
case MOVE_CURSOR_RIGHT_ON_DISPLAY: {
int w=tb_width();
@ -222,6 +266,10 @@ case MOVE_CURSOR_RIGHT_ON_DISPLAY: {
MOVE_CURSOR_LEFT_ON_DISPLAY,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["move-cursor-left-on-display"] = MOVE_CURSOR_LEFT_ON_DISPLAY;
:(before "End Primitive Recipe Checks")
case MOVE_CURSOR_LEFT_ON_DISPLAY: {
break;
}
:(before "End Primitive Recipe Implementations")
case MOVE_CURSOR_LEFT_ON_DISPLAY: {
if (Display_column > 0) {
@ -236,6 +284,10 @@ case MOVE_CURSOR_LEFT_ON_DISPLAY: {
DISPLAY_WIDTH,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["display-width"] = DISPLAY_WIDTH;
:(before "End Primitive Recipe Checks")
case DISPLAY_WIDTH: {
break;
}
:(before "End Primitive Recipe Implementations")
case DISPLAY_WIDTH: {
products.resize(1);
@ -247,6 +299,10 @@ case DISPLAY_WIDTH: {
DISPLAY_HEIGHT,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["display-height"] = DISPLAY_HEIGHT;
:(before "End Primitive Recipe Checks")
case DISPLAY_HEIGHT: {
break;
}
:(before "End Primitive Recipe Implementations")
case DISPLAY_HEIGHT: {
products.resize(1);
@ -258,6 +314,10 @@ case DISPLAY_HEIGHT: {
HIDE_CURSOR_ON_DISPLAY,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["hide-cursor-on-display"] = HIDE_CURSOR_ON_DISPLAY;
:(before "End Primitive Recipe Checks")
case HIDE_CURSOR_ON_DISPLAY: {
break;
}
:(before "End Primitive Recipe Implementations")
case HIDE_CURSOR_ON_DISPLAY: {
tb_set_cursor(TB_HIDE_CURSOR, TB_HIDE_CURSOR);
@ -268,6 +328,10 @@ case HIDE_CURSOR_ON_DISPLAY: {
SHOW_CURSOR_ON_DISPLAY,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["show-cursor-on-display"] = SHOW_CURSOR_ON_DISPLAY;
:(before "End Primitive Recipe Checks")
case SHOW_CURSOR_ON_DISPLAY: {
break;
}
:(before "End Primitive Recipe Implementations")
case SHOW_CURSOR_ON_DISPLAY: {
tb_set_cursor(Display_row, Display_column);
@ -278,6 +342,10 @@ case SHOW_CURSOR_ON_DISPLAY: {
HIDE_DISPLAY,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["hide-display"] = HIDE_DISPLAY;
:(before "End Primitive Recipe Checks")
case HIDE_DISPLAY: {
break;
}
:(before "End Primitive Recipe Implementations")
case HIDE_DISPLAY: {
Autodisplay = false;
@ -288,6 +356,10 @@ case HIDE_DISPLAY: {
SHOW_DISPLAY,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["show-display"] = SHOW_DISPLAY;
:(before "End Primitive Recipe Checks")
case SHOW_DISPLAY: {
break;
}
:(before "End Primitive Recipe Implementations")
case SHOW_DISPLAY: {
Autodisplay = true;
@ -301,6 +373,10 @@ case SHOW_DISPLAY: {
WAIT_FOR_SOME_INTERACTION,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["wait-for-some-interaction"] = WAIT_FOR_SOME_INTERACTION;
:(before "End Primitive Recipe Checks")
case WAIT_FOR_SOME_INTERACTION: {
break;
}
:(before "End Primitive Recipe Implementations")
case WAIT_FOR_SOME_INTERACTION: {
tb_event event;
@ -312,6 +388,10 @@ case WAIT_FOR_SOME_INTERACTION: {
CHECK_FOR_INTERACTION,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["check-for-interaction"] = CHECK_FOR_INTERACTION;
:(before "End Primitive Recipe Checks")
case CHECK_FOR_INTERACTION: {
break;
}
:(before "End Primitive Recipe Implementations")
case CHECK_FOR_INTERACTION: {
products.resize(2); // result and status
@ -375,6 +455,10 @@ case CHECK_FOR_INTERACTION: {
INTERACTIONS_LEFT,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["interactions-left?"] = INTERACTIONS_LEFT;
:(before "End Primitive Recipe Checks")
case INTERACTIONS_LEFT: {
break;
}
:(before "End Primitive Recipe Implementations")
case INTERACTIONS_LEFT: {
products.resize(1);
@ -388,6 +472,10 @@ case INTERACTIONS_LEFT: {
CLEAR_DISPLAY_FROM,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["clear-display-from"] = CLEAR_DISPLAY_FROM;
:(before "End Primitive Recipe Checks")
case CLEAR_DISPLAY_FROM: {
break;
}
:(before "End Primitive Recipe Implementations")
case CLEAR_DISPLAY_FROM: {
// todo: error checking

View File

@ -154,6 +154,10 @@ if (curr.name == "assume-screen") {
SCREEN_SHOULD_CONTAIN,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["screen-should-contain"] = SCREEN_SHOULD_CONTAIN;
:(before "End Primitive Recipe Checks")
case SCREEN_SHOULD_CONTAIN: {
break;
}
:(before "End Primitive Recipe Implementations")
case SCREEN_SHOULD_CONTAIN: {
if (!Passed) break;
@ -165,6 +169,10 @@ case SCREEN_SHOULD_CONTAIN: {
SCREEN_SHOULD_CONTAIN_IN_COLOR,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["screen-should-contain-in-color"] = SCREEN_SHOULD_CONTAIN_IN_COLOR;
:(before "End Primitive Recipe Checks")
case SCREEN_SHOULD_CONTAIN_IN_COLOR: {
break;
}
:(before "End Primitive Recipe Implementations")
case SCREEN_SHOULD_CONTAIN_IN_COLOR: {
if (!Passed) break;
@ -312,6 +320,10 @@ void raw_string_stream::skip_whitespace_and_comments() {
_DUMP_SCREEN,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["$dump-screen"] = _DUMP_SCREEN;
:(before "End Primitive Recipe Checks")
case _DUMP_SCREEN: {
break;
}
:(before "End Primitive Recipe Implementations")
case _DUMP_SCREEN: {
dump_screen();

View File

@ -38,12 +38,14 @@ Name[r]["console"] = CONSOLE;
:(before "End is_special_name Cases")
if (s == "console") return true;
//: Unlike assume-keyboard, assume-console is easiest to implement as just a
//: primitive recipe.
:(before "End Primitive Recipe Declarations")
ASSUME_CONSOLE,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["assume-console"] = ASSUME_CONSOLE;
:(before "End Primitive Recipe Checks")
case ASSUME_CONSOLE: {
break;
}
:(before "End Primitive Recipe Implementations")
case ASSUME_CONSOLE: {
// create a temporary recipe just for parsing; it won't contain valid instructions
@ -225,6 +227,10 @@ scenario events-in-scenario [
REPLACE_IN_CONSOLE,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["replace-in-console"] = REPLACE_IN_CONSOLE;
:(before "End Primitive Recipe Checks")
case REPLACE_IN_CONSOLE: {
break;
}
:(before "End Primitive Recipe Implementations")
case REPLACE_IN_CONSOLE: {
assert(scalar(ingredients.at(0)));

View File

@ -2,6 +2,10 @@
_BROWSE_TRACE,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["$browse-trace"] = _BROWSE_TRACE;
:(before "End Primitive Recipe Checks")
case _BROWSE_TRACE: {
break;
}
:(before "End Primitive Recipe Implementations")
case _BROWSE_TRACE: {
start_trace_browser();

View File

@ -26,16 +26,20 @@ recipe main [
RUN_INTERACTIVE,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["run-interactive"] = RUN_INTERACTIVE;
:(before "End Primitive Recipe Checks")
case RUN_INTERACTIVE: {
if (SIZE(inst.ingredients) != 1) {
raise << maybe(Recipe[r].name) << "'run-interactive' requires exactly one ingredient, but got " << inst.to_string() << '\n' << end();
break;
}
if (!is_mu_scalar(inst.ingredients.at(0))) {
raise << maybe(Recipe[r].name) << "first ingredient of 'run-interactive' should be a string, but got " << inst.ingredients.at(0).to_string() << '\n' << end();
break;
}
break;
}
:(before "End Primitive Recipe Implementations")
case RUN_INTERACTIVE: {
if (SIZE(ingredients) != 1) {
raise << maybe(current_recipe_name()) << "'run-interactive' requires exactly one ingredient, but got " << current_instruction().to_string() << '\n' << end();
break;
}
if (!scalar(ingredients.at(0))) {
raise << maybe(current_recipe_name()) << "first ingredient of 'run-interactive' should be a string, but got " << current_instruction().ingredients.at(0).to_string() << '\n' << end();
break;
}
bool new_code_pushed_to_stack = run_interactive(ingredients.at(0).at(0));
if (!new_code_pushed_to_stack) {
products.resize(5);
@ -166,6 +170,10 @@ recipe main [
_START_TRACKING_PRODUCTS,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["$start-tracking-products"] = _START_TRACKING_PRODUCTS;
:(before "End Primitive Recipe Checks")
case _START_TRACKING_PRODUCTS: {
break;
}
:(before "End Primitive Recipe Implementations")
case _START_TRACKING_PRODUCTS: {
Track_most_recent_products = true;
@ -176,6 +184,10 @@ case _START_TRACKING_PRODUCTS: {
_STOP_TRACKING_PRODUCTS,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["$stop-tracking-products"] = _STOP_TRACKING_PRODUCTS;
:(before "End Primitive Recipe Checks")
case _STOP_TRACKING_PRODUCTS: {
break;
}
:(before "End Primitive Recipe Implementations")
case _STOP_TRACKING_PRODUCTS: {
Track_most_recent_products = false;
@ -186,6 +198,10 @@ case _STOP_TRACKING_PRODUCTS: {
_MOST_RECENT_PRODUCTS,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["$most-recent-products"] = _MOST_RECENT_PRODUCTS;
:(before "End Primitive Recipe Checks")
case _MOST_RECENT_PRODUCTS: {
break;
}
:(before "End Primitive Recipe Implementations")
case _MOST_RECENT_PRODUCTS: {
products.resize(1);
@ -197,6 +213,10 @@ case _MOST_RECENT_PRODUCTS: {
SAVE_TRACE,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["save-trace"] = SAVE_TRACE;
:(before "End Primitive Recipe Checks")
case SAVE_TRACE: {
break;
}
:(before "End Primitive Recipe Implementations")
case SAVE_TRACE: {
products.resize(1);
@ -208,6 +228,10 @@ case SAVE_TRACE: {
_CLEANUP_RUN_INTERACTIVE,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["$cleanup-run-interactive"] = _CLEANUP_RUN_INTERACTIVE;
:(before "End Primitive Recipe Checks")
case _CLEANUP_RUN_INTERACTIVE: {
break;
}
:(before "End Primitive Recipe Implementations")
case _CLEANUP_RUN_INTERACTIVE: {
run_code_end();
@ -343,16 +367,20 @@ void truncate(string& x) {
RELOAD,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["reload"] = RELOAD;
:(before "End Primitive Recipe Checks")
case RELOAD: {
if (SIZE(inst.ingredients) != 1) {
raise << maybe(Recipe[r].name) << "'reload' requires exactly one ingredient, but got " << inst.to_string() << '\n' << end();
break;
}
if (!is_mu_scalar(inst.ingredients.at(0))) {
raise << maybe(Recipe[r].name) << "first ingredient of 'reload' should be a literal string, but got " << inst.ingredients.at(0).original_string << '\n' << end();
break;
}
break;
}
:(before "End Primitive Recipe Implementations")
case RELOAD: {
if (SIZE(ingredients) != 1) {
raise << maybe(current_recipe_name()) << "'reload' requires exactly one ingredient, but got " << current_instruction().to_string() << '\n' << end();
break;
}
if (!scalar(ingredients.at(0))) {
raise << maybe(current_recipe_name()) << "first ingredient of 'reload' should be a literal string, but got " << current_instruction().ingredients.at(0).original_string << '\n' << end();
break;
}
// clear any containers in advance
for (long long int i = 0; i < SIZE(recently_added_types); ++i) {
Type_ordinal.erase(Type[recently_added_types.at(i)].name);

View File

@ -6,12 +6,27 @@
RESTORE,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["restore"] = RESTORE;
:(before "End Primitive Recipe Implementations")
:(before "End Primitive Recipe Checks")
case RESTORE: {
if (SIZE(ingredients) != 1) {
raise << maybe(current_recipe_name()) << "'restore' requires exactly one ingredient, but got " << current_instruction().to_string() << '\n' << end();
if (SIZE(inst.ingredients) != 1) {
raise << maybe(Recipe[r].name) << "'restore' requires exactly one ingredient, but got " << inst.to_string() << '\n' << end();
break;
}
string filename;
if (is_literal_string(inst.ingredients.at(0))) {
;
}
else if (is_mu_string(inst.ingredients.at(0))) {
;
}
else {
raise << maybe(Recipe[r].name) << "first ingredient of 'restore' should be a string, but got " << inst.ingredients.at(0).to_string() << '\n' << end();
break;
}
break;
}
:(before "End Primitive Recipe Implementations")
case RESTORE: {
string filename;
if (is_literal_string(current_instruction().ingredients.at(0))) {
filename = current_instruction().ingredients.at(0).name;
@ -19,10 +34,6 @@ case RESTORE: {
else if (is_mu_string(current_instruction().ingredients.at(0))) {
filename = read_mu_string(ingredients.at(0).at(0));
}
else {
raise << maybe(current_recipe_name()) << "first ingredient of 'restore' should be a string, but got " << current_instruction().ingredients.at(0).to_string() << '\n' << end();
break;
}
if (Current_scenario) {
// do nothing in tests
products.resize(1);
@ -59,12 +70,30 @@ string slurp(const string& filename) {
SAVE,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["save"] = SAVE;
:(before "End Primitive Recipe Implementations")
:(before "End Primitive Recipe Checks")
case SAVE: {
if (SIZE(ingredients) != 2) {
raise << maybe(current_recipe_name()) << "'save' requires exactly two ingredients, but got " << current_instruction().to_string() << '\n' << end();
if (SIZE(inst.ingredients) != 2) {
raise << maybe(Recipe[r].name) << "'save' requires exactly two ingredients, but got " << inst.to_string() << '\n' << end();
break;
}
if (is_literal_string(inst.ingredients.at(0))) {
;
}
else if (is_mu_string(inst.ingredients.at(0))) {
;
}
else {
raise << maybe(Recipe[r].name) << "first ingredient of 'save' should be a string, but got " << inst.ingredients.at(0).to_string() << '\n' << end();
break;
}
if (!is_mu_scalar(inst.ingredients.at(1))) {
raise << maybe(Recipe[r].name) << "second ingredient of 'save' should be an address:array:character, but got " << inst.ingredients.at(1).to_string() << '\n' << end();
break;
}
break;
}
:(before "End Primitive Recipe Implementations")
case SAVE: {
if (Current_scenario) break; // do nothing in tests
string filename;
if (is_literal_string(current_instruction().ingredients.at(0))) {
@ -73,14 +102,6 @@ case SAVE: {
else if (is_mu_string(current_instruction().ingredients.at(0))) {
filename = read_mu_string(ingredients.at(0).at(0));
}
else {
raise << maybe(current_recipe_name()) << "first ingredient of 'save' should be a string, but got " << current_instruction().ingredients.at(0).to_string() << '\n' << end();
break;
}
if (!scalar(ingredients.at(1))) {
raise << maybe(current_recipe_name()) << "second ingredient of 'save' should be an address:array:character, but got " << current_instruction().ingredients.at(1).to_string() << '\n' << end();
break;
}
ofstream fout(("lesson/"+filename).c_str());
string contents = read_mu_string(ingredients.at(1).at(0));
fout << contents;