about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-05-08 08:21:36 -0700
committerKartik K. Agaram <vc@akkartik.com>2015-05-08 08:21:36 -0700
commita6cdf15c09f762c49a04937eb7e76b096221ba83 (patch)
tree52c2e5e59f7e210dd7bf9b02358bc779cad23060
parent3a622511fcdc0931ffeb3c08e2c104b1568a940b (diff)
downloadmu-a6cdf15c09f762c49a04937eb7e76b096221ba83.tar.gz
1308
-rw-r--r--003trace.cc1
-rw-r--r--027debug.cc10
-rw-r--r--038scheduler.cc13
-rw-r--r--039wait.cc8
-rw-r--r--061channel.mu77
5 files changed, 105 insertions, 4 deletions
diff --git a/003trace.cc b/003trace.cc
index 585ab413..04e0b9c7 100644
--- a/003trace.cc
+++ b/003trace.cc
@@ -117,6 +117,7 @@ struct trace_stream {
     past_lines.push_back(pair<string, pair<int, string> >(curr_layer, pair<int, string>(frame[curr_layer], curr_contents)));
     if (curr_layer == dump_layer || curr_layer == "dump" || dump_layer == "all" ||
         (!Hide_warnings && curr_layer == "warn"))
+//?     if (dump_layer == "all" && (Current_routine->id == 3 || curr_layer == "schedule")) //? 1
       cerr << curr_layer << '/' << frame[curr_layer] << ": " << curr_contents << '\n';
     delete curr_stream;
     curr_stream = NULL;
diff --git a/027debug.cc b/027debug.cc
index c4d39104..60b38319 100644
--- a/027debug.cc
+++ b/027debug.cc
@@ -52,3 +52,13 @@ case _EXIT: {
   exit(0);
   break;
 }
+
+:(before "End Primitive Recipe Declarations")
+_DUMP_LAYER,
+:(before "End Primitive Recipe Numbers")
+Recipe_number["$dump-layer"] = _DUMP_LAYER;
+:(before "End Primitive Recipe Implementations")
+case _DUMP_LAYER: {
+  Trace_stream->dump_layer = current_instruction().ingredients.at(0).name;
+  break;
+}
diff --git a/038scheduler.cc b/038scheduler.cc
index 012a1761..00d37371 100644
--- a/038scheduler.cc
+++ b/038scheduler.cc
@@ -51,6 +51,7 @@ void run(recipe_number r) {
     assert(Current_routine);
     assert(Current_routine->state == RUNNING);
     trace("schedule") << current_recipe_name();
+//?     trace("schedule") << Current_routine->id << " " << current_recipe_name(); //? 1
     run_current_routine(Scheduling_interval);
     if (Current_routine->completed())
       Current_routine->state = COMPLETED;
@@ -257,3 +258,15 @@ case RESTART: {
   }
   break;
 }
+
+:(before "End Primitive Recipe Declarations")
+_DUMP_ROUTINES,
+:(before "End Primitive Recipe Numbers")
+Recipe_number["$dump-routines"] = _DUMP_ROUTINES;
+:(before "End Primitive Recipe Implementations")
+case _DUMP_ROUTINES: {
+  for (index_t i = 0; i < Routines.size(); ++i) {
+    cerr << Routines.at(i)->id << ": " << Routines.at(i)->state << '\n';
+  }
+  break;
+}
diff --git a/039wait.cc b/039wait.cc
index dd397bde..78293d85 100644
--- a/039wait.cc
+++ b/039wait.cc
@@ -41,7 +41,7 @@ case WAIT_FOR_LOCATION: {
   Current_routine->waiting_on_location = loc.value;
   Current_routine->old_value_of_waiting_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
+//?   trace("schedule") << Current_routine->id << ": waiting for location " << loc.value << " to change from " << Memory[loc.value]; //? 2
   break;
 }
 
@@ -52,9 +52,9 @@ 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;
 //?   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.at(i)->old_value_of_waiting_location; //? 1
+//?   if (Routines.at(i)->waiting_on_location) //? 2
+//?     trace("schedule") << "checking routine " << Routines.at(i)->id << " waiting on location " //? 2
+//?       << Routines.at(i)->waiting_on_location << ": " << Memory[Routines.at(i)->waiting_on_location] << " vs " << Routines.at(i)->old_value_of_waiting_location; //? 2
   if (Routines.at(i)->waiting_on_location &&
       Memory[Routines.at(i)->waiting_on_location] != Routines.at(i)->old_value_of_waiting_location) {
     trace("schedule") << "waking up routine\n";
diff --git a/061channel.mu b/061channel.mu
index bee6b785..af34b13c 100644
--- a/061channel.mu
+++ b/061channel.mu
@@ -264,3 +264,80 @@ scenario channel-read-not-full [
     3 <- 0  # full?
   ]
 ]
+
+# helper for channels of characters in particular
+# out:address:channel <- buffer-lines in:address:channel, out:address:channel
+recipe buffer-lines [
+  default-space:address:address:array:location <- new location:type, 30:literal
+  in:address:channel <- next-ingredient
+  out:address:channel <- next-ingredient
+  # repeat forever
+  {
+    line:address:buffer <- init-buffer, 30:literal
+    # read characters from 'in' until newline, copy into line
+    {
+      c:character, in:address:channel <- read in:address:channel
+      # todo: handle backspace
+      line:address:buffer <- buffer-append line:address:buffer, c:character
+      line-done?:boolean <- equal c:character, 10:literal/newline
+      break-if line-done?:boolean
+      loop
+    }
+    # copy line into 'out'
+    i:integer <- copy 0:literal
+    line-contents:address:array:character <- get line:address:buffer/deref, data:offset
+    max:integer <- get line:address:buffer/deref, length:offset
+    {
+      done?:boolean <- greater-or-equal i:integer, max:integer
+      break-if done?:boolean
+      c:character <- index line-contents:address:array:character/deref, i:integer
+      out:address:channel <- write out:address:channel, c:character
+      i:integer <- add i:integer, 1:literal
+      loop
+    }
+    loop
+  }
+  reply out:address:channel/same-as-ingredient:1
+]
+
+scenario buffer-lines-blocks-until-newline [
+  run [
+    1:address:channel/stdin <- init-channel 10:literal/capacity
+    2:address:channel/buffered-stdin <- init-channel 10:literal/capacity
+    3:boolean <- channel-empty? 2:address:channel/buffered-stdin
+    assert 3:boolean, [
+F buffer-lines-blocks-until-newline: channel should be empty after init]
+    # buffer stdin into buffered-stdin, try to read from buffered-stdin
+    4:integer/buffer-routine <- start-running buffer-lines:recipe, 1:address:channel/stdin, 2:address:channel/buffered-stdin
+    wait-for-routine 4:integer/buffer-routine
+    5:boolean <- channel-empty? 2:address:channel/buffered-stdin
+    assert 5:boolean, [
+F buffer-lines-blocks-until-newline: channel should be empty after buffer-lines bring-up]
+    # write 'a'
+    1:address:channel <- write 1:address:channel, 97:literal/a
+    restart 4:integer/buffer-routine
+    wait-for-routine 4:integer/buffer-routine
+    6:boolean <- channel-empty? 2:address:channel/buffered-stdin
+    assert 6:boolean, [
+F buffer-lines-blocks-until-newline: channel should be empty after writing 'a']
+    # write 'b'
+    1:address:channel <- write 1:address:channel, 98:literal/b
+    restart 4:integer/buffer-routine
+    wait-for-routine 4:integer/buffer-routine
+    7:boolean <- channel-empty? 2:address:channel/buffered-stdin
+    assert 7:boolean, [
+F buffer-lines-blocks-until-newline: channel should be empty after writing 'b']
+    # write newline
+    1:address:channel <- write 1:address:channel, 10:literal/newline
+    restart 4:integer/buffer-routine
+    wait-for-routine 4:integer/buffer-routine
+    8:boolean <- channel-empty? 2:address:channel/buffered-stdin
+    9:boolean/completed? <- not 8:boolean
+    assert 9:boolean/completed?, [
+F buffer-lines-blocks-until-newline: channel should contain data after writing newline]
+    trace [test], [reached end]
+  ]
+  trace-should-contain [
+    test: reached end
+  ]
+]