2015-07-07 19:32:31 +00:00
|
|
|
//: 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
|
2015-06-01 06:44:52 +00:00
|
|
|
|
|
|
|
:(before "End Primitive Recipe Declarations")
|
|
|
|
RUN_INTERACTIVE,
|
|
|
|
:(before "End Primitive Recipe Numbers")
|
2015-07-04 16:40:50 +00:00
|
|
|
Recipe_ordinal["run-interactive"] = RUN_INTERACTIVE;
|
2015-06-01 06:44:52 +00:00
|
|
|
//? cerr << "run-interactive: " << RUN_INTERACTIVE << '\n'; //? 1
|
|
|
|
:(before "End Primitive Recipe Implementations")
|
|
|
|
case RUN_INTERACTIVE: {
|
|
|
|
assert(scalar(ingredients.at(0)));
|
2015-07-07 19:32:31 +00:00
|
|
|
products.resize(1);
|
2015-07-08 19:54:06 +00:00
|
|
|
bool new_code_pushed_to_stack = run_interactive(ingredients.at(0).at(0));
|
2015-07-07 19:32:31 +00:00
|
|
|
if (!new_code_pushed_to_stack) {
|
2015-07-08 19:54:06 +00:00
|
|
|
products.at(0).push_back(0);
|
|
|
|
break; // done with this instruction
|
2015-07-07 19:32:31 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
continue; // not done with caller; don't increment current_step_index()
|
|
|
|
}
|
2015-06-01 06:44:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
:(code)
|
2015-07-08 20:26:02 +00:00
|
|
|
// reads a string, tries to call it as code, saving all warnings.
|
2015-07-08 19:54:06 +00:00
|
|
|
// returns true if successfully called (no errors found during load and transform)
|
|
|
|
bool run_interactive(long long int address) {
|
2015-06-01 06:44:52 +00:00
|
|
|
long long int size = Memory[address];
|
2015-07-08 20:26:02 +00:00
|
|
|
if (size == 0) return false;
|
2015-06-01 06:44:52 +00:00
|
|
|
ostringstream tmp;
|
2015-07-07 22:55:57 +00:00
|
|
|
for (long long int curr = address+1; curr <= address+size; ++curr) {
|
2015-06-01 06:44:52 +00:00
|
|
|
// todo: unicode
|
|
|
|
tmp << (char)(int)Memory[curr];
|
|
|
|
}
|
2015-07-04 16:40:50 +00:00
|
|
|
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()));
|
2015-07-07 19:32:31 +00:00
|
|
|
if (command.empty()) return false;
|
2015-07-04 16:40:50 +00:00
|
|
|
Recipe.erase(Recipe_ordinal["interactive"]);
|
2015-07-08 18:43:59 +00:00
|
|
|
Hide_warnings = true;
|
2015-06-01 06:44:52 +00:00
|
|
|
// call run(string) but without the scheduling
|
2015-06-06 18:10:46 +00:00
|
|
|
load("recipe interactive [\n"+command+"\n]\n");
|
2015-06-01 06:44:52 +00:00
|
|
|
transform_all();
|
2015-07-08 18:43:59 +00:00
|
|
|
if (trace_count("warn") > 0) {
|
|
|
|
Hide_warnings = false;
|
|
|
|
return false;
|
|
|
|
}
|
2015-07-04 16:40:50 +00:00
|
|
|
Current_routine->calls.push_front(call(Recipe_ordinal["interactive"]));
|
2015-07-07 19:32:31 +00:00
|
|
|
return true;
|
2015-06-01 06:44:52 +00:00
|
|
|
}
|
2015-06-02 07:48:32 +00:00
|
|
|
|
2015-07-08 20:26:02 +00:00
|
|
|
:(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();
|
|
|
|
}
|
|
|
|
|
2015-07-07 19:32:31 +00:00
|
|
|
long long int stringified_value_of_location(long long int address) {
|
2015-06-06 17:38:51 +00:00
|
|
|
// convert to string
|
|
|
|
ostringstream out;
|
2015-07-07 22:55:57 +00:00
|
|
|
//? trace(1, "foo") << "a: " << address; //? 1
|
2015-07-07 19:32:31 +00:00
|
|
|
out << Memory[address];
|
2015-07-07 22:55:57 +00:00
|
|
|
//? trace(1, "foo") << "b: " << Memory[address]; //? 1
|
2015-07-07 19:32:31 +00:00
|
|
|
return new_string(out.str());
|
2015-06-06 17:38:51 +00:00
|
|
|
}
|
|
|
|
|
2015-06-02 07:48:32 +00:00
|
|
|
//:: debugging tool
|
|
|
|
|
|
|
|
:(before "End Primitive Recipe Declarations")
|
|
|
|
_RUN_DEPTH,
|
|
|
|
:(before "End Primitive Recipe Numbers")
|
2015-07-04 16:40:50 +00:00
|
|
|
Recipe_ordinal["$run-depth"] = _RUN_DEPTH;
|
2015-06-02 07:48:32 +00:00
|
|
|
:(before "End Primitive Recipe Implementations")
|
|
|
|
case _RUN_DEPTH: {
|
|
|
|
cerr << Current_routine->calls.size();
|
|
|
|
break;
|
|
|
|
}
|