diff options
-rw-r--r-- | 020run.cc | 1 | ||||
-rw-r--r-- | 037call_reply.cc | 3 | ||||
-rw-r--r-- | 038scheduler.cc | 17 | ||||
-rw-r--r-- | 039wait.cc | 11 | ||||
-rw-r--r-- | chessboard.mu | 176 |
5 files changed, 206 insertions, 2 deletions
diff --git a/020run.cc b/020run.cc index 0f196b82..c2a44019 100644 --- a/020run.cc +++ b/020run.cc @@ -96,6 +96,7 @@ void run_current_routine() //? cout << "DDD: " << current_instruction().to_string() << '\n'; //? 1 current_step_index() = instruction_counter+1; } + stop_running_current_routine:; } //: Some helpers. diff --git a/037call_reply.cc b/037call_reply.cc index a13c88e5..81f9c7c2 100644 --- a/037call_reply.cc +++ b/037call_reply.cc @@ -21,7 +21,8 @@ Recipe_number["reply"] = REPLY; case REPLY: { const instruction& reply_inst = current_instruction(); // save pointer into recipe before pop Current_routine->calls.pop(); - assert(!Current_routine->calls.empty()); + // just in case 'main' returns a value, drop it for now + if (Current_routine->calls.empty()) goto stop_running_current_routine; const instruction& caller_instruction = current_instruction(); // make reply results available to caller copy(ingredients.begin(), ingredients.end(), inserter(products, products.begin())); diff --git a/038scheduler.cc b/038scheduler.cc index b8c51e40..012a1761 100644 --- a/038scheduler.cc +++ b/038scheduler.cc @@ -240,3 +240,20 @@ case ROUTINE_STATE: { products.at(0).push_back(result); break; } + +:(before "End Primitive Recipe Declarations") +RESTART, +:(before "End Primitive Recipe Numbers") +Recipe_number["restart"] = RESTART; +:(before "End Primitive Recipe Implementations") +case RESTART: { + assert(ingredients.at(0).size() == 1); // routine id must be scalar + index_t id = ingredients.at(0).at(0); + for (index_t i = 0; i < Routines.size(); ++i) { + if (Routines.at(i)->id == id) { + Routines.at(i)->state = RUNNING; + break; + } + } + break; +} diff --git a/039wait.cc b/039wait.cc index 8d9086d6..89871022 100644 --- a/039wait.cc +++ b/039wait.cc @@ -41,6 +41,7 @@ case WAIT_FOR_LOCATION: { Current_routine->waiting_on_location = loc.value; Current_routine->old_value_of_wating_location = Memory[loc.value]; trace("run") << "waiting for location " << loc.value << " to change from " << Memory[loc.value]; +//? trace("schedule") << Current_routine->id << ": waiting for location " << loc.value << " to change from " << Memory[loc.value]; //? 1 break; } @@ -48,8 +49,13 @@ case WAIT_FOR_LOCATION: { :(before "End Scheduler State Transitions") for (index_t i = 0; i < Routines.size(); ++i) { +//? trace("schedule") << "wake up loop 1: routine " << Routines.at(i)->id << " has state " << Routines.at(i)->state; //? 1 if (Routines.at(i)->state != WAITING) continue; - if (Memory[Routines.at(i)->waiting_on_location] && +//? trace("schedule") << "waiting on location: " << Routines.at(i)->waiting_on_location; //? 1 +//? if (Routines.at(i)->waiting_on_location) //? 1 +//? trace("schedule") << "checking routine " << Routines.at(i)->id << " waiting on location " //? 1 +//? << Routines.at(i)->waiting_on_location << ": " << Memory[Routines.at(i)->waiting_on_location] << " vs " << Routines[i]->old_value_of_wating_location; //? 1 + if (Routines.at(i)->waiting_on_location && Memory[Routines.at(i)->waiting_on_location] != Routines.at(i)->old_value_of_wating_location) { trace("schedule") << "waking up routine\n"; Routines.at(i)->state = RUNNING; @@ -93,6 +99,9 @@ case WAIT_FOR_ROUTINE: { } :(before "End Scheduler State Transitions") +// Wake up any routines waiting for other routines to go to sleep. +// Important: this must come after the scheduler loop above giving routines +// waiting for locations to change a chance to wake up. for (index_t i = 0; i < Routines.size(); ++i) { if (Routines.at(i)->state != WAITING) continue; if (!Routines.at(i)->waiting_on_routine) continue; diff --git a/chessboard.mu b/chessboard.mu index d4b00b6f..d9ed4618 100644 --- a/chessboard.mu +++ b/chessboard.mu @@ -1,3 +1,7 @@ +# chessboard program: takes moves in algebraic notation and displays the +# position after each + +## a board is an array of files, a file is an array of characters (squares) recipe init-board [ default-space:address:array:location <- new location:type, 30:literal initial-position:address:array:integer <- next-ingredient @@ -140,3 +144,175 @@ scenario printing-the-board [ . . ] ] + +## data structure: move +container move [ + # valid range: 0-7 + from-file:integer + from-rank:integer + to-file:integer + to-rank:integer +] + +recipe read-move [ + default-space:address:array:location <- new location:type, 30:literal + stdin:address:channel <- next-ingredient + from-file:integer <- read-file stdin:address:channel + { + q-pressed?:boolean <- lesser-than from-file:integer, 0:literal + break-unless q-pressed?:boolean + reply 0:literal + } + # construct the move object + result:address:move <- new move:literal + x:address:integer <- get-address result:address:move/deref, from-file:offset + x:address:integer/deref <- copy from-file:integer + x:address:integer <- get-address result:address:move/deref, from-rank:offset + x:address:integer/deref <- read-rank stdin:address:channel + expect-from-channel stdin:address:channel, 45:literal # '-' + x:address:integer <- get-address result:address:move/deref, to-file:offset + x:address:integer/deref <- read-file stdin:address:channel + x:address:integer <- get-address result:address:move/deref, to-rank:offset + x:address:integer/deref <- read-rank stdin:address:channel + expect-from-channel stdin:address:channel, 10:literal # newline + reply result:address:move +] + +recipe read-file [ + default-space:address:array:location <- new location:type, 30:literal + stdin:address:channel <- next-ingredient + c:character, stdin:address:channel <- read stdin:address:channel + { + q-pressed?:boolean <- equal c:character, 81:literal # 'q' + break-unless q-pressed?:boolean + reply -1:literal + } + file:integer <- subtract c:character, 97:literal # 'a' + # 'a' <= file <= 'h' + above-min:boolean <- greater-or-equal file:integer, 0:literal + assert above-min:boolean [file too low] + below-max:boolean <- lesser-than file:integer, 8:literal + assert below-max:boolean [file too high] + reply file:integer +] + +recipe read-rank [ + default-space:address:array:location <- new location:type, 30:literal + stdin:address:channel <- next-ingredient + c:character, stdin:address:channel <- read stdin:address:channel + { + q-pressed?:boolean <- equal c:character, 81:literal # 'q' + break-unless q-pressed?:boolean + reply -1:literal + } + rank:integer <- subtract c:character, 49:literal # '1' + # assert'1' <= rank <= '8' + above-min:boolean <- greater-or-equal rank:integer 0:literal + assert above-min:boolean [rank too low] + below-max:boolean <- lesser-or-equal rank:integer 7:literal + assert below-max:boolean [rank too high] + reply rank:integer +] + +# read a character from the given channel and check that it's what we expect +recipe expect-from-channel [ + default-space:address:array:location <- new location:type, 30:literal + stdin:address:channel <- next-ingredient + expected:character <- next-ingredient + c:character, stdin:address:channel <- read stdin:address:channel + match?:boolean <- equal c:character, expected:character + assert match?:boolean [expected character not found] +] + +scenario read-move-blocking [ + run [ +#? $start-tracing #? 1 + 1:address:channel <- init-channel 2:literal +#? $print [aaa channel address: ], 1:address:channel, [ #? 1 +#? ] #? 1 + 2:integer/routine <- start-running read-move:recipe, 1:address:channel + # 'read-move' is waiting for input + wait-for-routine 2:integer +#? $print [bbb channel address: ], 1:address:channel, [ #? 1 +#? ] #? 1 + 3:integer <- routine-state 2:integer/id +#? $print [I: routine ], 2:integer, [ state ], 3:integer [ #? 1 +#? ] #? 1 + 4:boolean/waiting? <- equal 3:integer/routine-state, 2:literal/waiting + assert 4:boolean/waiting?, [ +F read-move-blocking: routine failed to pause after coming up (before any keys were pressed)] + # press 'a' +#? $print [ccc channel address: ], 1:address:channel, [ #? 1 +#? ] #? 1 +#? $exit #? 1 + 1:address:channel <- write 1:address:channel, 97:literal # 'a' + restart 2:integer/routine + # 'read-move' still waiting for input + wait-for-routine 2:integer + 3:integer <- routine-state 2:integer/id +#? $print [II: routine ], 2:integer, [ state ], 3:integer [ #? 1 +#? ] #? 1 + 4:boolean/waiting? <- equal 3:integer/routine-state, 2:literal/waiting + assert 4:boolean/waiting?, [ +F read-move-blocking: routine failed to pause after rank 'a'] + # press '2' + 1:address:channel <- write 1:address:channel, 50:literal # '2' + restart 2:integer/routine + # 'read-move' still waiting for input + wait-for-routine 2:integer + 3:integer <- routine-state 2:integer/id +#? $print [III: routine ], 2:integer, [ state ], 3:integer [ #? 1 +#? ] #? 1 + 4:boolean/waiting? <- equal 3:integer/routine-state, 2:literal/waiting + assert 4:boolean/waiting?, [ +F read-move-blocking: routine failed to pause after file 'a2'] + # press '-' + 1:address:channel <- write 1:address:channel, 45:literal # '-' + restart 2:integer/routine + # 'read-move' still waiting for input + wait-for-routine 2:integer + 3:integer <- routine-state 2:integer +#? $print [IV: routine ], 2:integer, [ state ], 3:integer [ #? 1 +#? ] #? 1 + 4:boolean/waiting? <- equal 3:integer/routine-state, 2:literal/waiting + assert 4:boolean/waiting?/routine-state, [ +F read-move-blocking: routine failed to pause after hyphen 'a2-'] + # press 'a' + 1:address:channel <- write 1:address:channel, 97:literal # 'a' + restart 2:integer/routine + # 'read-move' still waiting for input + wait-for-routine 2:integer + 3:integer <- routine-state 2:integer +#? $print [V: routine ], 2:integer, [ state ], 3:integer [ #? 1 +#? ] #? 1 + 4:boolean/waiting? <- equal 3:integer/routine-state, 2:literal/waiting + assert 4:boolean/waiting?/routine-state, [ +F read-move-blocking: routine failed to pause after rank 'a2-a'] + # press '4' + 1:address:channel <- write 1:address:channel, 52:literal # '4' + restart 2:integer/routine + # 'read-move' still waiting for input + wait-for-routine 2:integer + 3:integer <- routine-state 2:integer +#? $print [VI: routine ], 2:integer, [ state ], 3:integer [ #? 1 +#? ] #? 1 + 4:boolean/waiting? <- equal 3:integer/routine-state, 2:literal/waiting + assert 4:boolean/waiting?, [ +F read-move-blocking: routine failed to pause after file 'a2-a4'] + # press 'newline' + 1:address:channel <- write 1:address:channel, 10:literal # newline + restart 2:integer/routine + # 'read-move' now completes + wait-for-routine 2:integer + 3:integer <- routine-state 2:integer +#? $print [VII: routine ], 2:integer, [ state ], 3:integer [ #? 1 +#? ] #? 1 + 4:boolean/completed? <- equal 3:integer/routine-state, 1:literal/completed + assert 4:boolean/completed?, [ +F read-move-blocking: routine failed to terminate on newline] + trace [test], [reached end] + ] + trace-should-contain [ + test: reached end + ] +] |