diff options
author | Kartik K. Agaram <vc@akkartik.com> | 2016-04-27 22:28:55 -0700 |
---|---|---|
committer | Kartik K. Agaram <vc@akkartik.com> | 2016-04-27 22:28:55 -0700 |
commit | 5b22547bb352f6e5a98ddd8ff42f37861a8e16ea (patch) | |
tree | cf531cce10d5f570f55dd54a46361dad882a14f6 | |
parent | b1ddb414006352b2d3af3652263a536acbd2702e (diff) | |
download | mu-5b22547bb352f6e5a98ddd8ff42f37861a8e16ea.tar.gz |
2880
Turns out we don't need a primitive to return an empty value of arbitrary type. Just create it on the heap using 'new'. But this uncovered *yet* another bug, sigh. When I specialize generic functions I was running all transforms on the generated functions after specialization completed. But there's one transform that includes code from elsewhere. If such code included type-ingredients -- kaboom. Now fixed and there's a test, so I've got that going for me which is nice.
-rw-r--r-- | 056static_dispatch.cc | 3 | ||||
-rw-r--r-- | 058shape_shifting_recipe.cc | 30 | ||||
-rw-r--r-- | 072channel.mu | 34 | ||||
-rw-r--r-- | channel.mu | 3 | ||||
-rw-r--r-- | chessboard.mu | 11 |
5 files changed, 59 insertions, 22 deletions
diff --git a/056static_dispatch.cc b/056static_dispatch.cc index ef99ae43..353b4b50 100644 --- a/056static_dispatch.cc +++ b/056static_dispatch.cc @@ -174,7 +174,8 @@ string best_variant(instruction& inst, const recipe& caller_recipe) { candidates = strictly_matching_variants(inst, variants); if (!candidates.empty()) return best_variant(inst, candidates).name; - // Static Dispatch Phase 2 (shape-shifting recipes in a later layer) + // Static Dispatch Phase 2 + //: (shape-shifting recipes in a later layer) // End Static Dispatch Phase 2 // Static Dispatch Phase 3 diff --git a/058shape_shifting_recipe.cc b/058shape_shifting_recipe.cc index 6067fe7e..0384dd57 100644 --- a/058shape_shifting_recipe.cc +++ b/058shape_shifting_recipe.cc @@ -61,6 +61,8 @@ if (!candidates.empty()) { if (!variant.steps.empty()) { trace(9992, "transform") << "transforming new specialization: " << variant.name << end(); for (int t = 0; t < SIZE(Transform); ++t) { + // one exception: skip tangle, which would have already occurred inside new_variant above + if (Transform.at(t) == insert_fragments) continue; (*Transform.at(t))(new_recipe_ordinal); } } @@ -230,8 +232,14 @@ recipe_ordinal new_variant(recipe_ordinal exemplar, const instruction& inst, con recipe& new_recipe = get(Recipe, new_recipe_ordinal); new_recipe.name = new_name; trace(9993, "transform") << "switching " << inst.name << " to specialized " << header_label(new_recipe_ordinal) << end(); - // Since the exemplar never ran any transforms, we have to redo some of the - // work of the check_types_by_name transform while supporting type-ingredients. + + // Replace type ingredients with concrete types in new_recipe. + // + // preprocessing: micro-manage a couple of transforms + // a) perform tangle *before* replacing type ingredients, just in case + // inserted code involves type ingredients + insert_fragments(new_recipe_ordinal); + // b) do the work of check_types_by_name while supporting type-ingredients compute_type_names(new_recipe); // that gives enough information to replace type-ingredients with concrete types { @@ -1027,3 +1035,21 @@ def main [ foo *z ] # shouldn't crash + +:(scenario tangle_shape_shifting_recipe) +# shape-shifting recipe +def foo a:_elem [ + local-scope + load-ingredients + <label1> +] +# tangle some code that refers to the type ingredient +after <label1> [ + b:_elem <- copy a +] +# trigger specialization +def main [ + local-scope + foo 34 +] +$exit: 0 diff --git a/072channel.mu b/072channel.mu index 993581ab..d391aeeb 100644 --- a/072channel.mu +++ b/072channel.mu @@ -12,10 +12,11 @@ scenario channel [ run [ 1:address:source:number, 2:address:sink:number <- new-channel 3/capacity 2:address:sink:number <- write 2:address:sink:number, 34 - 3:number, 1:address:source:number <- read 1:address:source:number + 3:number, 4:boolean, 1:address:source:number <- read 1:address:source:number ] memory-should-contain [ 3 <- 34 + 4 <- 0 # read was successful ] ] @@ -74,7 +75,6 @@ def write out:address:sink:_elem, val:_elem -> out:address:sink:_elem [ free:number <- get *chan, first-free:offset *circular-buffer <- put-index *circular-buffer, free, val # mark its slot as filled - # todo: clear the slot itself free <- add free, 1 { # wrap free around to 0 if necessary @@ -87,9 +87,10 @@ def write out:address:sink:_elem, val:_elem -> out:address:sink:_elem [ *chan <- put *chan, first-free:offset, free ] -def read in:address:source:_elem -> result:_elem, in:address:source:_elem [ +def read in:address:source:_elem -> result:_elem, fail?:boolean, in:address:source:_elem [ local-scope load-ingredients + fail? <- copy 0/false # default status chan:address:channel:_elem <- get *in, chan:offset { # block if chan is empty @@ -103,8 +104,10 @@ def read in:address:source:_elem -> result:_elem, in:address:source:_elem [ full:number <- get *chan, first-full:offset circular-buffer:address:array:_elem <- get *chan, data:offset result <- index *circular-buffer, full + # clear the slot + empty:address:_elem <- new _elem:type + *circular-buffer <- put-index *circular-buffer, full, *empty # mark its slot as empty - # todo: clear the slot itself full <- add full, 1 { # wrap full around to 0 if necessary @@ -124,7 +127,7 @@ def clear in:address:source:_elem -> in:address:source:_elem [ { empty?:boolean <- channel-empty? chan break-if empty? - _, in <- read in + _, _, in <- read in } ] @@ -159,7 +162,7 @@ scenario channel-read-increments-full [ run [ 1:address:source:number, 2:address:sink:number <- new-channel 3/capacity 2:address:sink:number <- write 2:address:sink:number, 34 - _, 1:address:source:number <- read 1:address:source:number + _, _, 1:address:source:number <- read 1:address:source:number 3:address:channel:number <- get *1:address:source:number, chan:offset 4:number <- get *3:address:channel:number, first-full:offset 5:number <- get *3:address:channel:number, first-free:offset @@ -177,7 +180,7 @@ scenario channel-wrap [ 3:address:channel:number <- get *1:address:source:number, chan:offset # write and read a value 2:address:sink:number <- write 2:address:sink:number, 34 - _, 1:address:source:number <- read 1:address:source:number + _, _, 1:address:source:number <- read 1:address:source:number # first-free will now be 1 4:number <- get *3:address:channel:number, first-free:offset 5:number <- get *3:address:channel:number, first-free:offset @@ -185,7 +188,7 @@ scenario channel-wrap [ 2:address:sink:number <- write 2:address:sink:number, 34 6:number <- get *3:address:channel:number, first-free:offset # read second value, verify that first-full wraps - _, 1:address:source:number <- read 1:address:source:number + _, _, 1:address:source:number <- read 1:address:source:number 7:number <- get *3:address:channel:number, first-full:offset ] memory-should-contain [ @@ -242,7 +245,7 @@ scenario channel-read-not-full [ 1:address:source:number, 2:address:sink:number <- new-channel 1/capacity 3:address:channel:number <- get *1:address:source:number, chan:offset 2:address:sink:number <- write 2:address:sink:number, 34 - _, 1:address:source:number <- read 1:address:source:number + _, _, 1:address:source:number <- read 1:address:source:number 4:boolean <- channel-empty? 3:address:channel:number 5:boolean <- channel-full? 3:address:channel:number ] @@ -288,7 +291,11 @@ after <channel-write-initial> [ after <channel-read-empty> [ closed?:boolean <- get *chan, closed?:offset - return-if closed?, 0/hack # only scalar _elems supported in channels; need to support construction of arbitrary empty containers + { + break-unless closed? + empty-result:address:_elem <- new _elem:type + return *empty-result, 1/true + } ] ## helpers @@ -335,12 +342,14 @@ def buffer-lines in:address:source:character, buffered-out:address:sink:characte local-scope load-ingredients # repeat forever + eof?:boolean <- copy 0/false { line:address:buffer <- new-buffer 30 # read characters from 'in' until newline, copy into line { +next-character - c:character, in <- read in + c:character, eof?:boolean, in <- read in + break-if eof? # drop a character on backspace { # special-case: if it's a backspace @@ -361,9 +370,6 @@ def buffer-lines in:address:source:character, buffered-out:address:sink:characte line <- append line, c line-done?:boolean <- equal c, 10/newline break-if line-done? - # stop buffering on eof (currently only generated by fake console) - eof?:boolean <- equal c, 0/eof - break-if eof? loop } # copy line into 'buffered-out' diff --git a/channel.mu b/channel.mu index d74cbcad..e7415754 100644 --- a/channel.mu +++ b/channel.mu @@ -24,7 +24,8 @@ def consumer source:address:source:character -> source:address:source:character load-ingredients { # read an integer from the channel - n:character, source <- read source + n:character, eof?:boolean, source <- read source + break-if eof? # other threads might get between these prints $print [consume: ], n:character, [ ] diff --git a/chessboard.mu b/chessboard.mu index 7ead26cb..57e40b19 100644 --- a/chessboard.mu +++ b/chessboard.mu @@ -260,7 +260,8 @@ def read-move stdin:address:source:character, screen:address:screen -> result:ad def read-file stdin:address:source:character, screen:address:screen -> file:number, quit:boolean, error:boolean, stdin:address:source:character, screen:address:screen [ local-scope load-ingredients - c:character, stdin <- read stdin + c:character, eof?:boolean, stdin <- read stdin + return-if eof?, 0/dummy, 1/quit, 0/error { q-pressed?:boolean <- equal c, 81/Q break-unless q-pressed? @@ -302,11 +303,12 @@ def read-file stdin:address:source:character, screen:address:screen -> file:numb return file, 0/quit, 0/error ] -# valid values: 0-7, -1 (quit), -2 (error) +# valid values for rank: 0-7 def read-rank stdin:address:source:character, screen:address:screen -> rank:number, quit?:boolean, error?:boolean, stdin:address:source:character, screen:address:screen [ local-scope load-ingredients - c:character, stdin <- read stdin + c:character, eof?:boolean, stdin <- read stdin + return-if eof?, 0/dummy, 1/quit, 0/error { q-pressed?:boolean <- equal c, 8/Q break-unless q-pressed? @@ -347,7 +349,8 @@ def read-rank stdin:address:source:character, screen:address:screen -> rank:numb def expect-from-channel stdin:address:source:character, expected:character, screen:address:screen -> result:boolean, stdin:address:source:character, screen:address:screen [ local-scope load-ingredients - c:character, stdin <- read stdin + c:character, eof?:boolean, stdin <- read stdin + return-if eof? 1/true { match?:boolean <- equal c, expected break-if match? |