From 28763a3d6a84c03836b1b85eaeee547a3a97b8e4 Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Thu, 11 Jun 2015 22:10:01 -0700 Subject: 1553 --- 077mouse.cc | 33 +++++++++ 077trace_browser.cc | 200 -------------------------------------------------- 078run_interactive.cc | 122 ------------------------------ 079input.cc | 33 --------- 080trace_browser.cc | 200 ++++++++++++++++++++++++++++++++++++++++++++++++++ 081run_interactive.cc | 122 ++++++++++++++++++++++++++++++ 6 files changed, 355 insertions(+), 355 deletions(-) create mode 100644 077mouse.cc delete mode 100644 077trace_browser.cc delete mode 100644 078run_interactive.cc delete mode 100644 079input.cc create mode 100644 080trace_browser.cc create mode 100644 081run_interactive.cc diff --git a/077mouse.cc b/077mouse.cc new file mode 100644 index 00000000..e458574a --- /dev/null +++ b/077mouse.cc @@ -0,0 +1,33 @@ +:(before "End Primitive Recipe Declarations") +READ_KEYBOARD_OR_MOUSE_EVENT, +:(before "End Primitive Recipe Numbers") +Recipe_number["read-keyboard-or-mouse-event"] = READ_KEYBOARD_OR_MOUSE_EVENT; +:(before "End Primitive Recipe Implementations") +case READ_KEYBOARD_OR_MOUSE_EVENT: { + products.resize(2); // result and status + tb_event event; + int event_type = tb_peek_event(&event, 5/*ms*/); + if (event_type == TB_EVENT_KEY) { + products.at(0).push_back(/*keyboard event*/0); + long long key = event.key ? event.key : event.ch; + if (key == TB_KEY_CTRL_C) tb_shutdown(), exit(1); + if (key == TB_KEY_BACKSPACE2) key = TB_KEY_BACKSPACE; + if (key == TB_KEY_CARRIAGE_RETURN) key = TB_KEY_NEWLINE; + products.at(0).push_back(key); + products.at(1).push_back(/*found*/true); + break; + } + if (event_type == TB_EVENT_MOUSE) { + products.at(0).push_back(/*mouse event*/1); +//? tb_shutdown(); //? 1 +//? cerr << event_type << ' ' << event.key << ' ' << event.y << ' ' << event.x << '\n'; //? 1 +//? exit(0); //? 1 + products.at(0).push_back(event.key); // which button, etc. + products.at(0).push_back(event.y); // row + products.at(0).push_back(event.x); // column + products.at(1).push_back(/*found*/true); + break; + } + products.at(1).push_back(/*found*/false); + break; +} diff --git a/077trace_browser.cc b/077trace_browser.cc deleted file mode 100644 index 69d68792..00000000 --- a/077trace_browser.cc +++ /dev/null @@ -1,200 +0,0 @@ -:(before "End Primitive Recipe Declarations") -_BROWSE_TRACE, -:(before "End Primitive Recipe Numbers") -Recipe_number["$browse-trace"] = _BROWSE_TRACE; -:(before "End Primitive Recipe Implementations") -case _BROWSE_TRACE: { - start_trace_browser(); - break; -} - -:(before "End Globals") -set Visible; -long long int Top_of_screen = 0; -long long int Last_printed_row = 0; -map Trace_index; // screen row -> trace index - -:(code) -void start_trace_browser() { - if (!Trace_stream) return; - cerr << "computing depth to display\n"; - long long int min_depth = 9999; - for (long long int i = 0; i < SIZE(Trace_stream->past_lines); ++i) { - trace_line& curr_line = Trace_stream->past_lines.at(i); - if (curr_line.depth == 0) continue; - if (curr_line.depth < min_depth) min_depth = curr_line.depth; - } - cerr << "depth is " << min_depth << '\n'; - cerr << "computing lines to display\n"; - for (long long int i = 0; i < SIZE(Trace_stream->past_lines); ++i) { - if (Trace_stream->past_lines.at(i).depth == min_depth) - Visible.insert(i); - } - tb_init(); - Display_row = Display_column = 0; - tb_event event; - Top_of_screen = 0; - refresh_screen_rows(); - while (true) { - render(); - do { - tb_poll_event(&event); - } while (event.type != TB_EVENT_KEY); - long long int key = event.key ? event.key : event.ch; - if (key == 'q' || key == 'Q') break; - if (key == 'j' || key == TB_KEY_ARROW_DOWN) { - // move cursor one line down - if (Display_row < Last_printed_row) ++Display_row; - } - if (key == 'k' || key == TB_KEY_ARROW_UP) { - // move cursor one line up - if (Display_row > 0) --Display_row; - } - if (key == 'H') { - // move cursor to top of screen - Display_row = 0; - } - if (key == 'M') { - // move cursor to center of screen - Display_row = tb_height()/2; - } - if (key == 'L') { - // move cursor to bottom of screen - Display_row = tb_height()-1; - } - if (key == 'J' || key == TB_KEY_PGDN) { - // page-down - if (Trace_index.find(tb_height()-1) != Trace_index.end()) { - Top_of_screen = Trace_index[tb_height()-1]+1; - refresh_screen_rows(); - } - } - if (key == 'K' || key == TB_KEY_PGUP) { - // page-up is more convoluted -//? tb_shutdown(); //? 1 -//? cerr << "page-up: Top_of_screen is currently " << Top_of_screen << '\n'; //? 1 - for (int screen_row = tb_height(); screen_row > 0 && Top_of_screen > 0; --screen_row) { - --Top_of_screen; - if (Top_of_screen <= 0) break; - while (Top_of_screen > 0 && Visible.find(Top_of_screen) == Visible.end()) - --Top_of_screen; -//? cerr << "now " << Top_of_screen << '\n'; //? 1 - } -//? exit(0); //? 1 - if (Top_of_screen > 0) - refresh_screen_rows(); - } - if (key == 'G') { - // go to bottom of screen; largely like page-up, interestingly - Top_of_screen = SIZE(Trace_stream->past_lines)-1; - for (int screen_row = tb_height(); screen_row > 0 && Top_of_screen > 0; --screen_row) { - --Top_of_screen; - if (Top_of_screen <= 0) break; - while (Top_of_screen > 0 && Visible.find(Top_of_screen) == Visible.end()) - --Top_of_screen; - } - refresh_screen_rows(); - // move cursor to bottom - Display_row = Last_printed_row; - refresh_screen_rows(); - } - if (key == TB_KEY_CARRIAGE_RETURN) { - // expand lines under current by one level -//? tb_shutdown(); - assert(Trace_index.find(Display_row) != Trace_index.end()); - long long int start_index = Trace_index[Display_row]; -//? cerr << "start_index is " << start_index << '\n'; - long long int index = 0; - // simultaneously compute end_index and min_depth - int min_depth = 9999; - for (index = start_index+1; index < SIZE(Trace_stream->past_lines); ++index) { - if (Visible.find(index) != Visible.end()) break; - trace_line& curr_line = Trace_stream->past_lines.at(index); - if (curr_line.depth == 0) continue; - assert(curr_line.depth > Trace_stream->past_lines.at(start_index).depth); - if (curr_line.depth < min_depth) min_depth = curr_line.depth; - } -//? cerr << "min_depth is " << min_depth << '\n'; - long long int end_index = index; -//? cerr << "end_index is " << end_index << '\n'; - // mark as visible all intervening indices at min_depth - for (index = start_index; index < end_index; ++index) { - trace_line& curr_line = Trace_stream->past_lines.at(index); - if (curr_line.depth == min_depth) { -//? cerr << "adding " << index << '\n'; - Visible.insert(index); - } - } -//? exit(0); - refresh_screen_rows(); - } - if (key == TB_KEY_BACKSPACE || key == TB_KEY_BACKSPACE2) { - // collapse all lines under current - assert(Trace_index.find(Display_row) != Trace_index.end()); - long long int start_index = Trace_index[Display_row]; - long long int index = 0; - // end_index is the next line at a depth same as or lower than start_index - int initial_depth = Trace_stream->past_lines.at(start_index).depth; - for (index = start_index+1; index < SIZE(Trace_stream->past_lines); ++index) { - if (Visible.find(index) == Visible.end()) continue; - trace_line& curr_line = Trace_stream->past_lines.at(index); - if (curr_line.depth == 0) continue; - if (curr_line.depth <= initial_depth) break; - } - long long int end_index = index; - // mark as visible all intervening indices at min_depth - for (index = start_index+1; index < end_index; ++index) { - Visible.erase(index); - } - refresh_screen_rows(); - } - } - tb_shutdown(); -} - -// update Trace_indices for each screen_row on the basis of Top_of_screen and Visible -void refresh_screen_rows() { - long long int screen_row = 0, index = 0; - Trace_index.clear(); - for (screen_row = 0, index = Top_of_screen; screen_row < tb_height() && index < SIZE(Trace_stream->past_lines); ++screen_row, ++index) { - // skip lines without depth for now - while (Visible.find(index) == Visible.end()) { - ++index; - if (index >= SIZE(Trace_stream->past_lines)) goto done; - } - assert(index < SIZE(Trace_stream->past_lines)); - Trace_index[screen_row] = index; - } -done:; -} - -void render() { - long long int screen_row = 0; - for (screen_row = 0; screen_row < tb_height(); ++screen_row) { - if (Trace_index.find(screen_row) == Trace_index.end()) break; - trace_line& curr_line = Trace_stream->past_lines.at(Trace_index[screen_row]); - ostringstream out; - out << std::setw(4) << curr_line.depth << ' ' << curr_line.label << ": " << curr_line.contents; - render_line(screen_row, out.str()); - } - // clear rest of screen - Last_printed_row = screen_row-1; - for (; screen_row < tb_height(); ++screen_row) { - render_line(screen_row, "~"); - } - // move cursor back to display row at the end - tb_set_cursor(0, Display_row); - tb_present(); -} - -void render_line(int screen_row, const string& s) { - long long int col = 0; - for (col = 0; col < tb_width() && col < SIZE(s); ++col) { - char c = s.at(col); - if (c == '\n') c = ';'; // replace newlines with semi-colons - tb_change_cell(col, screen_row, c, TB_WHITE, TB_BLACK); - } - for (; col < tb_width(); ++col) { - tb_change_cell(col, screen_row, ' ', TB_WHITE, TB_BLACK); - } -} diff --git a/078run_interactive.cc b/078run_interactive.cc deleted file mode 100644 index 95a40533..00000000 --- a/078run_interactive.cc +++ /dev/null @@ -1,122 +0,0 @@ -//: Helper for the repl. - -:(before "End Primitive Recipe Declarations") -RUN_INTERACTIVE, -:(before "End Primitive Recipe Numbers") -Recipe_number["run-interactive"] = RUN_INTERACTIVE; -//? cerr << "run-interactive: " << RUN_INTERACTIVE << '\n'; //? 1 -:(before "End Primitive Recipe Implementations") -case RUN_INTERACTIVE: { - assert(scalar(ingredients.at(0))); -//? cerr << "AAA 0\n"; //? 1 - run_interactive(ingredients.at(0).at(0)); -//? cerr << "ZZZ\n"; //? 1 - continue; // not done with caller; don't increment current_step_index() -} - -:(code) -// manual tests: -// empty string (excluding whitespace and comments) does nothing -// ctrl-d -// just an integer (excluding whitespace and comments) prints value of that location in memory -// instruction executes -// backspace at start begins new attempt -void run_interactive(long long int address) { -//? tb_shutdown(); //? 1 - long long int size = Memory[address]; - if (size == 0) { - ++current_step_index(); - return; - } - ostringstream tmp; - for (long long int curr = address+1; curr < address+size; ++curr) { - // todo: unicode - tmp << (char)(int)Memory[curr]; - } -//? cerr << size << ' ' << Memory[address+size] << '\n'; //? 1 - assert(Memory[address+size] == 10); // skip the newline - if (Recipe_number.find("interactive") == Recipe_number.end()) - Recipe_number["interactive"] = Next_recipe_number++; - string command = trim(strip_comments(tmp.str())); - if (command.empty()) { - ++current_step_index(); - return; - } - if (is_integer(command)) { - print_value_of_location_as_response(to_integer(command)); - ++current_step_index(); - return; - } -//? exit(0); //? 1 - if (Name[Recipe_number["interactive"]].find(command) != Name[Recipe_number["interactive"]].end()) { - print_value_of_location_as_response(Name[Recipe_number["interactive"]][command]); - ++current_step_index(); - return; - } -//? tb_shutdown(); //? 1 -//? cerr << command; //? 1 -//? exit(0); //? 1 -//? cerr << "AAA 1\n"; //? 1 - Recipe.erase(Recipe_number["interactive"]); - // call run(string) but without the scheduling -//? cerr << ("recipe interactive [\n"+command+"\n]\n"); //? 1 - load("recipe interactive [\n"+command+"\n]\n"); - transform_all(); -//? cerr << "names: " << Name[Recipe_number["interactive"]].size() << "; "; //? 1 -//? cerr << "steps: " << Recipe[Recipe_number["interactive"]].steps.size() << "; "; //? 1 -//? cerr << "interactive transformed_until: " << Recipe[Recipe_number["interactive"]].transformed_until << '\n'; //? 1 - Current_routine->calls.push_front(call(Recipe_number["interactive"])); -} - -string strip_comments(string in) { - ostringstream result; -//? cerr << in; //? 1 - 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; - } - } -//? cerr << "ZZZ"; //? 1 - return result.str(); -} - -void print_value_of_location_as_response(long long int address) { - // convert to string - ostringstream out; - out << "=> " << Memory[address]; - string result = out.str(); - // handle regular I/O - if (!tb_is_active()) { - cerr << result << '\n'; - return; - } - // raw I/O; use termbox to print - long long int bound = SIZE(result); - if (bound > tb_width()) bound = tb_width(); - for (long long int i = 0; i < bound; ++i) { - tb_change_cell(i, Display_row, result.at(i), /*computer's color*/245, TB_BLACK); - } - // newline - if (Display_row < tb_height()-1) - ++Display_row; - Display_column = 0; - tb_set_cursor(Display_column, Display_row); - tb_present(); -} - -//:: debugging tool - -:(before "End Primitive Recipe Declarations") -_RUN_DEPTH, -:(before "End Primitive Recipe Numbers") -Recipe_number["$run-depth"] = _RUN_DEPTH; -:(before "End Primitive Recipe Implementations") -case _RUN_DEPTH: { - cerr << Current_routine->calls.size(); - break; -} diff --git a/079input.cc b/079input.cc deleted file mode 100644 index e458574a..00000000 --- a/079input.cc +++ /dev/null @@ -1,33 +0,0 @@ -:(before "End Primitive Recipe Declarations") -READ_KEYBOARD_OR_MOUSE_EVENT, -:(before "End Primitive Recipe Numbers") -Recipe_number["read-keyboard-or-mouse-event"] = READ_KEYBOARD_OR_MOUSE_EVENT; -:(before "End Primitive Recipe Implementations") -case READ_KEYBOARD_OR_MOUSE_EVENT: { - products.resize(2); // result and status - tb_event event; - int event_type = tb_peek_event(&event, 5/*ms*/); - if (event_type == TB_EVENT_KEY) { - products.at(0).push_back(/*keyboard event*/0); - long long key = event.key ? event.key : event.ch; - if (key == TB_KEY_CTRL_C) tb_shutdown(), exit(1); - if (key == TB_KEY_BACKSPACE2) key = TB_KEY_BACKSPACE; - if (key == TB_KEY_CARRIAGE_RETURN) key = TB_KEY_NEWLINE; - products.at(0).push_back(key); - products.at(1).push_back(/*found*/true); - break; - } - if (event_type == TB_EVENT_MOUSE) { - products.at(0).push_back(/*mouse event*/1); -//? tb_shutdown(); //? 1 -//? cerr << event_type << ' ' << event.key << ' ' << event.y << ' ' << event.x << '\n'; //? 1 -//? exit(0); //? 1 - products.at(0).push_back(event.key); // which button, etc. - products.at(0).push_back(event.y); // row - products.at(0).push_back(event.x); // column - products.at(1).push_back(/*found*/true); - break; - } - products.at(1).push_back(/*found*/false); - break; -} diff --git a/080trace_browser.cc b/080trace_browser.cc new file mode 100644 index 00000000..69d68792 --- /dev/null +++ b/080trace_browser.cc @@ -0,0 +1,200 @@ +:(before "End Primitive Recipe Declarations") +_BROWSE_TRACE, +:(before "End Primitive Recipe Numbers") +Recipe_number["$browse-trace"] = _BROWSE_TRACE; +:(before "End Primitive Recipe Implementations") +case _BROWSE_TRACE: { + start_trace_browser(); + break; +} + +:(before "End Globals") +set Visible; +long long int Top_of_screen = 0; +long long int Last_printed_row = 0; +map Trace_index; // screen row -> trace index + +:(code) +void start_trace_browser() { + if (!Trace_stream) return; + cerr << "computing depth to display\n"; + long long int min_depth = 9999; + for (long long int i = 0; i < SIZE(Trace_stream->past_lines); ++i) { + trace_line& curr_line = Trace_stream->past_lines.at(i); + if (curr_line.depth == 0) continue; + if (curr_line.depth < min_depth) min_depth = curr_line.depth; + } + cerr << "depth is " << min_depth << '\n'; + cerr << "computing lines to display\n"; + for (long long int i = 0; i < SIZE(Trace_stream->past_lines); ++i) { + if (Trace_stream->past_lines.at(i).depth == min_depth) + Visible.insert(i); + } + tb_init(); + Display_row = Display_column = 0; + tb_event event; + Top_of_screen = 0; + refresh_screen_rows(); + while (true) { + render(); + do { + tb_poll_event(&event); + } while (event.type != TB_EVENT_KEY); + long long int key = event.key ? event.key : event.ch; + if (key == 'q' || key == 'Q') break; + if (key == 'j' || key == TB_KEY_ARROW_DOWN) { + // move cursor one line down + if (Display_row < Last_printed_row) ++Display_row; + } + if (key == 'k' || key == TB_KEY_ARROW_UP) { + // move cursor one line up + if (Display_row > 0) --Display_row; + } + if (key == 'H') { + // move cursor to top of screen + Display_row = 0; + } + if (key == 'M') { + // move cursor to center of screen + Display_row = tb_height()/2; + } + if (key == 'L') { + // move cursor to bottom of screen + Display_row = tb_height()-1; + } + if (key == 'J' || key == TB_KEY_PGDN) { + // page-down + if (Trace_index.find(tb_height()-1) != Trace_index.end()) { + Top_of_screen = Trace_index[tb_height()-1]+1; + refresh_screen_rows(); + } + } + if (key == 'K' || key == TB_KEY_PGUP) { + // page-up is more convoluted +//? tb_shutdown(); //? 1 +//? cerr << "page-up: Top_of_screen is currently " << Top_of_screen << '\n'; //? 1 + for (int screen_row = tb_height(); screen_row > 0 && Top_of_screen > 0; --screen_row) { + --Top_of_screen; + if (Top_of_screen <= 0) break; + while (Top_of_screen > 0 && Visible.find(Top_of_screen) == Visible.end()) + --Top_of_screen; +//? cerr << "now " << Top_of_screen << '\n'; //? 1 + } +//? exit(0); //? 1 + if (Top_of_screen > 0) + refresh_screen_rows(); + } + if (key == 'G') { + // go to bottom of screen; largely like page-up, interestingly + Top_of_screen = SIZE(Trace_stream->past_lines)-1; + for (int screen_row = tb_height(); screen_row > 0 && Top_of_screen > 0; --screen_row) { + --Top_of_screen; + if (Top_of_screen <= 0) break; + while (Top_of_screen > 0 && Visible.find(Top_of_screen) == Visible.end()) + --Top_of_screen; + } + refresh_screen_rows(); + // move cursor to bottom + Display_row = Last_printed_row; + refresh_screen_rows(); + } + if (key == TB_KEY_CARRIAGE_RETURN) { + // expand lines under current by one level +//? tb_shutdown(); + assert(Trace_index.find(Display_row) != Trace_index.end()); + long long int start_index = Trace_index[Display_row]; +//? cerr << "start_index is " << start_index << '\n'; + long long int index = 0; + // simultaneously compute end_index and min_depth + int min_depth = 9999; + for (index = start_index+1; index < SIZE(Trace_stream->past_lines); ++index) { + if (Visible.find(index) != Visible.end()) break; + trace_line& curr_line = Trace_stream->past_lines.at(index); + if (curr_line.depth == 0) continue; + assert(curr_line.depth > Trace_stream->past_lines.at(start_index).depth); + if (curr_line.depth < min_depth) min_depth = curr_line.depth; + } +//? cerr << "min_depth is " << min_depth << '\n'; + long long int end_index = index; +//? cerr << "end_index is " << end_index << '\n'; + // mark as visible all intervening indices at min_depth + for (index = start_index; index < end_index; ++index) { + trace_line& curr_line = Trace_stream->past_lines.at(index); + if (curr_line.depth == min_depth) { +//? cerr << "adding " << index << '\n'; + Visible.insert(index); + } + } +//? exit(0); + refresh_screen_rows(); + } + if (key == TB_KEY_BACKSPACE || key == TB_KEY_BACKSPACE2) { + // collapse all lines under current + assert(Trace_index.find(Display_row) != Trace_index.end()); + long long int start_index = Trace_index[Display_row]; + long long int index = 0; + // end_index is the next line at a depth same as or lower than start_index + int initial_depth = Trace_stream->past_lines.at(start_index).depth; + for (index = start_index+1; index < SIZE(Trace_stream->past_lines); ++index) { + if (Visible.find(index) == Visible.end()) continue; + trace_line& curr_line = Trace_stream->past_lines.at(index); + if (curr_line.depth == 0) continue; + if (curr_line.depth <= initial_depth) break; + } + long long int end_index = index; + // mark as visible all intervening indices at min_depth + for (index = start_index+1; index < end_index; ++index) { + Visible.erase(index); + } + refresh_screen_rows(); + } + } + tb_shutdown(); +} + +// update Trace_indices for each screen_row on the basis of Top_of_screen and Visible +void refresh_screen_rows() { + long long int screen_row = 0, index = 0; + Trace_index.clear(); + for (screen_row = 0, index = Top_of_screen; screen_row < tb_height() && index < SIZE(Trace_stream->past_lines); ++screen_row, ++index) { + // skip lines without depth for now + while (Visible.find(index) == Visible.end()) { + ++index; + if (index >= SIZE(Trace_stream->past_lines)) goto done; + } + assert(index < SIZE(Trace_stream->past_lines)); + Trace_index[screen_row] = index; + } +done:; +} + +void render() { + long long int screen_row = 0; + for (screen_row = 0; screen_row < tb_height(); ++screen_row) { + if (Trace_index.find(screen_row) == Trace_index.end()) break; + trace_line& curr_line = Trace_stream->past_lines.at(Trace_index[screen_row]); + ostringstream out; + out << std::setw(4) << curr_line.depth << ' ' << curr_line.label << ": " << curr_line.contents; + render_line(screen_row, out.str()); + } + // clear rest of screen + Last_printed_row = screen_row-1; + for (; screen_row < tb_height(); ++screen_row) { + render_line(screen_row, "~"); + } + // move cursor back to display row at the end + tb_set_cursor(0, Display_row); + tb_present(); +} + +void render_line(int screen_row, const string& s) { + long long int col = 0; + for (col = 0; col < tb_width() && col < SIZE(s); ++col) { + char c = s.at(col); + if (c == '\n') c = ';'; // replace newlines with semi-colons + tb_change_cell(col, screen_row, c, TB_WHITE, TB_BLACK); + } + for (; col < tb_width(); ++col) { + tb_change_cell(col, screen_row, ' ', TB_WHITE, TB_BLACK); + } +} diff --git a/081run_interactive.cc b/081run_interactive.cc new file mode 100644 index 00000000..95a40533 --- /dev/null +++ b/081run_interactive.cc @@ -0,0 +1,122 @@ +//: Helper for the repl. + +:(before "End Primitive Recipe Declarations") +RUN_INTERACTIVE, +:(before "End Primitive Recipe Numbers") +Recipe_number["run-interactive"] = RUN_INTERACTIVE; +//? cerr << "run-interactive: " << RUN_INTERACTIVE << '\n'; //? 1 +:(before "End Primitive Recipe Implementations") +case RUN_INTERACTIVE: { + assert(scalar(ingredients.at(0))); +//? cerr << "AAA 0\n"; //? 1 + run_interactive(ingredients.at(0).at(0)); +//? cerr << "ZZZ\n"; //? 1 + continue; // not done with caller; don't increment current_step_index() +} + +:(code) +// manual tests: +// empty string (excluding whitespace and comments) does nothing +// ctrl-d +// just an integer (excluding whitespace and comments) prints value of that location in memory +// instruction executes +// backspace at start begins new attempt +void run_interactive(long long int address) { +//? tb_shutdown(); //? 1 + long long int size = Memory[address]; + if (size == 0) { + ++current_step_index(); + return; + } + ostringstream tmp; + for (long long int curr = address+1; curr < address+size; ++curr) { + // todo: unicode + tmp << (char)(int)Memory[curr]; + } +//? cerr << size << ' ' << Memory[address+size] << '\n'; //? 1 + assert(Memory[address+size] == 10); // skip the newline + if (Recipe_number.find("interactive") == Recipe_number.end()) + Recipe_number["interactive"] = Next_recipe_number++; + string command = trim(strip_comments(tmp.str())); + if (command.empty()) { + ++current_step_index(); + return; + } + if (is_integer(command)) { + print_value_of_location_as_response(to_integer(command)); + ++current_step_index(); + return; + } +//? exit(0); //? 1 + if (Name[Recipe_number["interactive"]].find(command) != Name[Recipe_number["interactive"]].end()) { + print_value_of_location_as_response(Name[Recipe_number["interactive"]][command]); + ++current_step_index(); + return; + } +//? tb_shutdown(); //? 1 +//? cerr << command; //? 1 +//? exit(0); //? 1 +//? cerr << "AAA 1\n"; //? 1 + Recipe.erase(Recipe_number["interactive"]); + // call run(string) but without the scheduling +//? cerr << ("recipe interactive [\n"+command+"\n]\n"); //? 1 + load("recipe interactive [\n"+command+"\n]\n"); + transform_all(); +//? cerr << "names: " << Name[Recipe_number["interactive"]].size() << "; "; //? 1 +//? cerr << "steps: " << Recipe[Recipe_number["interactive"]].steps.size() << "; "; //? 1 +//? cerr << "interactive transformed_until: " << Recipe[Recipe_number["interactive"]].transformed_until << '\n'; //? 1 + Current_routine->calls.push_front(call(Recipe_number["interactive"])); +} + +string strip_comments(string in) { + ostringstream result; +//? cerr << in; //? 1 + 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; + } + } +//? cerr << "ZZZ"; //? 1 + return result.str(); +} + +void print_value_of_location_as_response(long long int address) { + // convert to string + ostringstream out; + out << "=> " << Memory[address]; + string result = out.str(); + // handle regular I/O + if (!tb_is_active()) { + cerr << result << '\n'; + return; + } + // raw I/O; use termbox to print + long long int bound = SIZE(result); + if (bound > tb_width()) bound = tb_width(); + for (long long int i = 0; i < bound; ++i) { + tb_change_cell(i, Display_row, result.at(i), /*computer's color*/245, TB_BLACK); + } + // newline + if (Display_row < tb_height()-1) + ++Display_row; + Display_column = 0; + tb_set_cursor(Display_column, Display_row); + tb_present(); +} + +//:: debugging tool + +:(before "End Primitive Recipe Declarations") +_RUN_DEPTH, +:(before "End Primitive Recipe Numbers") +Recipe_number["$run-depth"] = _RUN_DEPTH; +:(before "End Primitive Recipe Implementations") +case _RUN_DEPTH: { + cerr << Current_routine->calls.size(); + break; +} -- cgit 1.4.1-2-gfad0