mu/081run_interactive.cc

110 lines
3.2 KiB
C++
Raw Normal View History

//: Helper for various programming environments: run arbitrary mu code and
//: return some result in string form.
:(scenario run_interactive_code)
recipe main [
2:address:array:character <- new [1:number <- copy 34:literal
]
run-interactive 2:address:array:character # code won't return a result
]
+mem: storing 34 in location 1
:(scenario run_interactive_empty)
recipe main [
1:address:array:character <- run-interactive 0:literal
]
# result is null
+mem: storing 0 in location 1
:(before "End Primitive Recipe Declarations")
RUN_INTERACTIVE,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["run-interactive"] = RUN_INTERACTIVE;
//? cerr << "run-interactive: " << RUN_INTERACTIVE << '\n'; //? 1
:(before "End Primitive Recipe Implementations")
case RUN_INTERACTIVE: {
assert(scalar(ingredients.at(0)));
products.resize(1);
bool new_code_pushed_to_stack = run_interactive(ingredients.at(0).at(0));
if (!new_code_pushed_to_stack) {
products.at(0).push_back(0);
break; // done with this instruction
}
else {
continue; // not done with caller; don't increment current_step_index()
}
}
:(code)
// reads a string, tries to call it as code, saving all warnings.
// returns true if successfully called (no errors found during load and transform)
bool run_interactive(long long int address) {
long long int size = Memory[address];
if (size == 0) return false;
ostringstream tmp;
2015-07-07 22:55:57 +00:00
for (long long int curr = address+1; curr <= address+size; ++curr) {
// todo: unicode
tmp << (char)(int)Memory[curr];
}
if (Recipe_ordinal.find("interactive") == Recipe_ordinal.end())
Recipe_ordinal["interactive"] = Next_recipe_ordinal++;
2015-06-06 18:10:46 +00:00
string command = trim(strip_comments(tmp.str()));
if (command.empty()) return false;
Recipe.erase(Recipe_ordinal["interactive"]);
Hide_warnings = true;
// call run(string) but without the scheduling
2015-06-06 18:10:46 +00:00
load("recipe interactive [\n"+command+"\n]\n");
transform_all();
if (trace_count("warn") > 0) {
Hide_warnings = false;
return false;
}
Current_routine->calls.push_front(call(Recipe_ordinal["interactive"]));
return true;
}
:(after "Starting Reply")
if (current_recipe_name() == "interactive") clean_up_interactive();
:(after "Falling Through End Of Recipe")
if (current_recipe_name() == "interactive") clean_up_interactive();
:(code)
void clean_up_interactive() {
Hide_warnings = false;
}
2015-06-06 18:10:46 +00:00
string strip_comments(string in) {
ostringstream result;
for (long long int i = 0; i < SIZE(in); ++i) {
if (in.at(i) != '#') {
result << in.at(i);
}
else {
while (i < SIZE(in) && in.at(i) != '\n')
++i;
if (i < SIZE(in) && in.at(i) == '\n') ++i;
}
}
return result.str();
}
long long int stringified_value_of_location(long long int address) {
// convert to string
ostringstream out;
2015-07-07 22:55:57 +00:00
//? trace(1, "foo") << "a: " << address; //? 1
out << Memory[address];
2015-07-07 22:55:57 +00:00
//? trace(1, "foo") << "b: " << Memory[address]; //? 1
return new_string(out.str());
}
//:: debugging tool
:(before "End Primitive Recipe Declarations")
_RUN_DEPTH,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["$run-depth"] = _RUN_DEPTH;
:(before "End Primitive Recipe Implementations")
case _RUN_DEPTH: {
cerr << Current_routine->calls.size();
break;
}