diff options
Diffstat (limited to '071print.mu')
-rw-r--r-- | 071print.mu | 274 |
1 files changed, 274 insertions, 0 deletions
diff --git a/071print.mu b/071print.mu new file mode 100644 index 00000000..2bf1df0b --- /dev/null +++ b/071print.mu @@ -0,0 +1,274 @@ +# Wrappers around print primitives that take a 'screen' object and are thus +# easier to test. + +container screen [ + num-rows:integer + num-columns:integer + cursor-row:integer + cursor-column:integer + data:address:array:character +] + +recipe init-fake-screen [ + default-space:address:array:location <- new location:type, 30:literal/capacity + result:address:screen <- new screen:type + width:address:integer <- get-address result:address:screen/deref, num-columns:offset + width:address:integer/deref <- next-ingredient + height:address:integer <- get-address result:address:screen/deref, num-rows:offset + height:address:integer/deref <- next-ingredient + row:address:integer <- get-address result:address:screen/deref, cursor-row:offset + row:address:integer/deref <- copy 0:literal + column:address:integer <- get-address result:address:screen/deref, cursor-column:offset + column:address:integer/deref <- copy 0:literal + bufsize:integer <- multiply width:address:integer/deref, height:address:integer/deref + buf:address:address:array:character <- get-address result:address:screen/deref, data:offset + buf:address:address:array:character/deref <- new character:literal, bufsize:integer + clear-screen result:address:screen + reply result:address:screen +] + +recipe clear-screen [ + default-space:address:array:location <- new location:type, 30:literal + x:address:screen <- next-ingredient + # if x exists + { + break-unless x:address:screen + # clear fake screen + buf:address:array:character <- get x:address:screen/deref, data:offset + max:integer <- length buf:address:array:character/deref + i:integer <- copy 0:literal + { + done?:boolean <- greater-or-equal i:integer, max:integer + break-if done?:boolean + c:address:character <- index-address buf:address:array:character/deref, i:integer + c:address:character/deref <- copy [ ] + i:integer <- add i:integer, 1:literal + loop + } + reply x:address:screen/same-as-ingredient:0 + } + # otherwise, real screen + clear-display + reply x:address:screen/same-as-ingredient:0 +] + +recipe print-character [ + default-space:address:array:location <- new location:type, 30:literal + x:address:screen <- next-ingredient + c:character <- next-ingredient +#? $print x:address:character #? 1 +#? $print [ print-character #? 1 +#? ] #? 1 + { + # if x exists + break-unless x:address:screen +#? $print [print-character2 #? 1 +#? ] #? 1 + # save character in fake screen + row:address:integer <- get-address x:address:screen/deref, cursor-row:offset + column:address:integer <- get-address x:address:screen/deref, cursor-column:offset + width:integer <- get x:address:screen/deref, num-columns:offset + index:integer <- multiply row:address:integer/deref, width:integer + index:integer <- add index:integer, column:address:integer/deref + buf:address:array:character <- get x:address:screen/deref, data:offset + cursor:address:character <- index-address buf:address:array:character/deref, index:integer +#? $print cursor:address:character #? 1 +#? $print [ #? 1 +#? ] #? 1 + cursor:address:character/deref <- copy c:character # todo: newline, etc. + # increment column unless it's already all the way to the right + { + at-right?:boolean <- equal column:address:integer/deref, width:integer + break-if at-right?:boolean + column:address:integer/deref <- add column:address:integer/deref, 1:literal + } + reply x:address:screen/same-as-ingredient:0 + } + # otherwise, real screen + print-character-to-display c:character + reply x:address:screen/same-as-ingredient:0 +] + +scenario print-character-at-top-left [ + run [ +#? $start-tracing #? 3 + 1:address:screen <- init-fake-screen 3:literal/width, 2:literal/height + 1:address:screen <- print-character 1:address:screen, 97:literal # 'a' + 2:address:array:character <- get 1:address:screen/deref, data:offset + 3:array:character <- copy 2:address:array:character/deref + ] + memory-should-contain [ + 3 <- 6 # width*height + 4 <- 97 # 'a' + 5 <- 0 + ] +] + +recipe clear-line [ + default-space:address:array:location <- new location:type, 30:literal + x:address:screen <- next-ingredient + # if x exists, clear line in fake screen + { + break-unless x:address:screen + n:integer <- get x:address:screen/deref, num-columns:offset + column:address:integer <- get-address x:address:screen/deref, cursor-column:offset + original-column:integer <- copy column:address:integer/deref + # space over the entire line + { + done?:boolean <- greater-or-equal column:address:integer/deref, n:integer + break-if done?:boolean + print-character x:address:screen, [ ] # implicitly updates 'column' + loop + } + # now back to where the cursor was + column:address:integer/deref <- copy original-column:integer + reply x:address:screen/same-as-ingredient:0 + } + # otherwise, real screen + clear-line-on-display + reply x:address:screen/same-as-ingredient:0 +] + +recipe cursor-position [ + default-space:address:array:location <- new location:type, 30:literal + x:address:screen <- next-ingredient + # if x exists, lookup cursor in fake screen + { + break-unless x:address:screen + row:integer <- get x:address:screen/deref, cursor-row:offset + column:integer <- get x:address:screen/deref, cursor-column:offset + reply row:integer, column:integer + } + row:integer, column:integer <- cursor-position-on-display + reply row:integer, column:integer +] + +recipe move-cursor [ + default-space:address:array:location <- new location:type, 30:literal + x:address:screen <- next-ingredient + new-row:integer <- next-ingredient + new-column:integer <- next-ingredient + # if x exists, move cursor in fake screen + { + break-unless x:address:screen + row:address:integer <- get-address x:address:screen/deref cursor-row:offset + row:address:integer/deref <- copy new-row:integer + column:address:integer <- get-address x:address:screen/deref cursor-column:offset + column:address:integer/deref <- copy new-column:integer + reply x:address:screen/same-as-ingredient:0 + } + # otherwise, real screen + move-cursor-on-display new-row:integer, new-column:integer + reply x:address:screen/same-as-ingredient:0 +] + +scenario clear-line-erases-printed-characters [ + run [ +#? $start-tracing #? 3 + 1:address:screen <- init-fake-screen 3:literal/width, 2:literal/height + # print a character + 1:address:screen <- print-character 1:address:screen, 97:literal # 'a' + # move cursor to start of line + 1:address:screen <- move-cursor 1:address:screen, 0:literal/row, 0:literal/column + # clear line + 1:address:screen <- clear-line 1:address:screen + 2:address:array:character <- get 1:address:screen/deref, data:offset + 3:array:character <- copy 2:address:array:character/deref + ] + # screen should be blank + memory-should-contain [ + 3 <- 6 # width*height + 4 <- 0 + 5 <- 0 + 6 <- 0 + 7 <- 0 + 8 <- 0 + 9 <- 0 + ] +] + +recipe cursor-down [ + default-space:address:array:location <- new location:type, 30:literal + x:address:screen <- next-ingredient + # if x exists, move cursor in fake screen + { + break-unless x:address:screen + { + # if row < height + height:integer <- get x:address:screen/deref, num-rows:offset + row:address:integer <- get-address x:address:screen/deref cursor-row:offset + at-bottom?:boolean <- greater-or-equal row:address:integer/deref, height:integer + break-if at-bottom?:boolean + # row = row+1 + row:address:integer/deref <- add row:address:integer, 1:literal + } + reply x:address:screen/same-as-ingredient:0 + } + # otherwise, real screen + move-cursor-down-on-display + reply x:address:screen/same-as-ingredient:0 +] + +recipe cursor-up [ + default-space:address:array:location <- new location:type, 30:literal + x:address:screen <- next-ingredient + # if x exists, move cursor in fake screen + { + break-unless x:address:screen + { + # if row >= 0 + row:address:integer <- get-address x:address:screen/deref cursor-row:offset + at-top?:boolean <- lesser-than row:address:integer/deref, 0:literal + break-if at-top?:boolean + # row = row-1 + row:address:integer/deref <- subtract row:address:integer, 1:literal + } + reply x:address:screen/same-as-ingredient:0 + } + # otherwise, real screen + move-cursor-up-on-display + reply x:address:screen/same-as-ingredient:0 +] + +recipe cursor-right [ + default-space:address:array:location <- new location:type, 30:literal + x:address:screen <- next-ingredient + # if x exists, move cursor in fake screen + { + break-unless x:address:screen + { + # if column < width + width:integer <- get x:address:screen/deref, num-columns:offset + column:address:integer <- get-address x:address:screen/deref cursor-column:offset + at-bottom?:boolean <- greater-or-equal column:address:integer/deref, width:integer + break-if at-bottom?:boolean + # column = column+1 + column:address:integer/deref <- add column:address:integer, 1:literal + } + reply x:address:screen/same-as-ingredient:0 + } + # otherwise, real screen + move-cursor-right-on-display + reply x:address:screen/same-as-ingredient:0 +] + +recipe cursor-left [ + default-space:address:array:location <- new location:type, 30:literal + x:address:screen <- next-ingredient + # if x exists, move cursor in fake screen + { + break-unless x:address:screen + { + # if column >= 0 + column:address:integer <- get-address x:address:screen/deref cursor-column:offset + at-top?:boolean <- lesser-than column:address:integer/deref, 0:literal + break-if at-top?:boolean + # column = column-1 + column:address:integer/deref <- subtract column:address:integer, 1:literal + } + reply x:address:screen/same-as-ingredient:0 + } + # otherwise, real screen + move-cursor-left-on-display + reply x:address:screen/same-as-ingredient:0 +] |