Browse Source

rename grapheme to code-point-utf8

Longer name, but it doesn't lie. We have no data structure right now for
combining multiple code points. And it makes no sense for the notion of
a grapheme to conflate its Unicode encoding.
main
Kartik K. Agaram 8 months ago
parent
commit
d253a31828
  1. 4
      126write-int-decimal.subx
  2. 4
      400.mu
  3. 141
      403unicode.mu
  4. 20
      411string.mu
  5. 4
      500fake-screen.mu
  6. 14
      501draw-text.mu
  7. 66
      504test-screen.mu
  8. 336
      513grapheme-stack.mu
  9. 444
      514gap-buffer.mu
  10. 80
      apps/ex15.mu
  11. 2
      apps/ex9.mu
  12. 4
      apps/hest-life.mu
  13. 12
      browse-slack/environment.mu
  14. 2
      editor/Mu.tmbundle/Syntaxes/Mu.tmLanguage
  15. 2
      editor/VSCode/syntaxes/Mu.tmLanguage
  16. 4
      linux/126write-int-decimal.subx
  17. 14
      linux/304screen.subx
  18. 6
      linux/305keyboard.subx
  19. 8
      linux/400.mu
  20. 146
      linux/403unicode.mu
  21. 390
      linux/405screen.mu
  22. 2
      linux/407right-justify.mu
  23. 20
      linux/411string.mu
  24. 46
      linux/apps/arith.mu
  25. 2
      linux/apps/parse-int.mu
  26. 4
      linux/apps/print-file.mu
  27. 2
      linux/apps/tui.mu
  28. 40
      linux/browse/main.mu
  29. 176
      linux/browse/paginated-screen.mu
  30. BIN
      linux/mu
  31. 10
      linux/mu.subx
  32. 4
      linux/tile/box.mu
  33. 114
      linux/tile/environment.mu
  34. 188
      linux/tile/gap-buffer.mu
  35. 124
      linux/tile/grapheme-stack.mu
  36. 6
      linux/tile/main.mu
  37. 18
      linux/tile/surface.mu
  38. 12
      linux/tile/value.mu
  39. 48
      linux/tile/word.mu
  40. 12
      linux/vocabulary.md
  41. 8
      mu.md
  42. 2
      shell/README.md
  43. 6
      shell/environment.mu
  44. 2
      shell/global.mu
  45. 30
      shell/infix.mu
  46. 2
      shell/main.mu
  47. 18
      shell/primitives.mu
  48. 2
      shell/sandbox.mu
  49. 100
      shell/tokenize.mu
  50. 2
      shell/trace.mu
  51. 82
      signatures.mu
  52. 2
      tutorial/converter.mu
  53. 2
      tutorial/converter2.mu
  54. 12
      tutorial/index.md
  55. 10
      vocabulary.md

4
126write-int-decimal.subx

@ -324,7 +324,7 @@ test-write-int32-decimal-negative-multiple-digits:
# . end
c3/return
decimal-digit?: # c: grapheme -> result/eax: boolean
decimal-digit?: # c: code-point-utf8 -> result/eax: boolean
# . prologue
55/push-ebp
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
@ -423,7 +423,7 @@ test-decimal-digit-above-9:
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
c3/return
to-decimal-digit: # in: grapheme -> out/eax: int
to-decimal-digit: # in: code-point-utf8 -> out/eax: int
# . prologue
55/push-ebp
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp

4
400.mu

@ -97,8 +97,8 @@ sig write-slice out: (addr stream byte), s: (addr slice)
# bad name alert
sig slice-to-string ad: (addr allocation-descriptor), in: (addr slice), out: (addr handle array byte)
sig write-int32-decimal out: (addr stream byte), n: int
sig decimal-digit? c: grapheme -> _/eax: boolean
sig to-decimal-digit in: grapheme -> _/eax: int
sig decimal-digit? c: code-point-utf8 -> _/eax: boolean
sig to-decimal-digit in: code-point-utf8 -> _/eax: int
# bad name alert
# next-word really tokenizes
# next-raw-word really reads whitespace-separated words

141
403unicode.mu

@ -1,16 +1,11 @@
# Helpers for Unicode.
#
# Mu has no characters, only code points and graphemes.
# Code points are the indivisible atoms of text streams.
# The basic unit for rendering Unicode is the code point.
# https://en.wikipedia.org/wiki/Code_point
# Graphemes are the smallest self-contained unit of text.
# Graphemes may consist of multiple code points.
# The glyph a non-cursive font displays may represent multiple code points.
#
# Mu graphemes are always represented in utf-8, and they are required to fit
# in 4 bytes. (This can be confusing if you focus just on ASCII, where Mu's
# graphemes and code-points are identical.)
#
# Mu doesn't yet support graphemes consisting of multiple code points.
# In addition to raw code points (just integers assigned special meaning), Mu
# provides a common encoding as a convenience: code-point-utf8.
fn test-unicode-serialization-and-deserialization {
var i/ebx: int <- copy 0
@ -20,8 +15,8 @@ fn test-unicode-serialization-and-deserialization {
# but not emoji
break-if->=
var c/eax: code-point <- copy i
var _g/eax: grapheme <- to-grapheme c
var g/ecx: grapheme <- copy _g
var _g/eax: code-point-utf8 <- to-utf8 c
var g/ecx: code-point-utf8 <- copy _g
var c2/eax: code-point <- to-code-point g
compare i, c2
{
@ -51,7 +46,7 @@ fn test-unicode-serialization-and-deserialization {
}
# transliterated from tb_utf8_char_to_unicode in https://github.com/nsf/termbox
fn to-code-point in: grapheme -> _/eax: code-point {
fn to-code-point in: code-point-utf8 -> _/eax: code-point {
var g/ebx: int <- copy in
# if single byte, just return it
{
@ -61,7 +56,7 @@ fn to-code-point in: grapheme -> _/eax: code-point {
return result
}
#
var len/edx: int <- grapheme-length in
var len/edx: int <- utf8-length in
# extract bits from first byte
var b/eax: byte <- copy-byte g
var result/edi: code-point <- copy b
@ -99,16 +94,16 @@ fn to-code-point in: grapheme -> _/eax: code-point {
# transliterated from tb_utf8_unicode_to_char in https://github.com/nsf/termbox
# https://wiki.tcl-lang.org/page/UTF%2D8+bit+by+bit explains the algorithm
fn to-grapheme in: code-point -> _/eax: grapheme {
fn to-utf8 in: code-point -> _/eax: code-point-utf8 {
var c/eax: int <- copy in
var num-trailers/ecx: int <- copy 0
var first/edx: int <- copy 0
$to-grapheme:compute-length: {
$to-utf8:compute-length: {
# single byte: just return it
compare c, 0x7f
{
break-if->
var g/eax: grapheme <- copy c
var g/eax: code-point-utf8 <- copy c
return g
}
# 2 bytes
@ -117,7 +112,7 @@ fn to-grapheme in: code-point -> _/eax: grapheme {
break-if->
num-trailers <- copy 1
first <- copy 0xc0
break $to-grapheme:compute-length
break $to-utf8:compute-length
}
# 3 bytes
compare c, 0xffff
@ -125,7 +120,7 @@ fn to-grapheme in: code-point -> _/eax: grapheme {
break-if->
num-trailers <- copy 2
first <- copy 0xe0
break $to-grapheme:compute-length
break $to-utf8:compute-length
}
# 4 bytes
compare c, 0x1fffff
@ -133,7 +128,7 @@ fn to-grapheme in: code-point -> _/eax: grapheme {
break-if->
num-trailers <- copy 3
first <- copy 0xf0
break $to-grapheme:compute-length
break $to-utf8:compute-length
}
# more than 4 bytes: unsupported
compare c, 0x1fffff
@ -144,7 +139,7 @@ fn to-grapheme in: code-point -> _/eax: grapheme {
}
}
# emit trailer bytes, 6 bits from 'in', first two bits '10'
var result/edi: grapheme <- copy 0
var result/edi: code-point-utf8 <- copy 0
{
compare num-trailers, 0
break-if-<=
@ -166,16 +161,16 @@ fn to-grapheme in: code-point -> _/eax: grapheme {
return result
}
# single-byte code point have identical graphemes
fn test-to-grapheme-single-byte {
# single-byte code point have identical code-point-utf8s
fn test-to-utf8-single-byte {
var in-int/ecx: int <- copy 0
{
compare in-int, 0x7f
break-if->
var in/eax: code-point <- copy in-int
var out/eax: grapheme <- to-grapheme in
var out/eax: code-point-utf8 <- to-utf8 in
var out-int/eax: int <- copy out
check-ints-equal out-int, in-int, "F - test-to-grapheme-single-byte"
check-ints-equal out-int, in-int, "F - test-to-utf8-single-byte"
in-int <- increment
loop
}
@ -183,55 +178,55 @@ fn test-to-grapheme-single-byte {
# byte | byte | byte | byte
# smallest 2-byte utf-8
fn test-to-grapheme-two-bytes-min {
fn test-to-utf8-two-bytes-min {
var in/eax: code-point <- copy 0x80 # 10 00-0000
var out/eax: grapheme <- to-grapheme in
var out/eax: code-point-utf8 <- to-utf8 in
var out-int/eax: int <- copy out
check-ints-equal out-int, 0x80c2, "F - to-grapheme/2a" # 110 0-0010 10 00-0000
check-ints-equal out-int, 0x80c2, "F - to-utf8/2a" # 110 0-0010 10 00-0000
}
# largest 2-byte utf-8
fn test-to-grapheme-two-bytes-max {
fn test-to-utf8-two-bytes-max {
var in/eax: code-point <- copy 0x7ff # 1-1111 11-1111
var out/eax: grapheme <- to-grapheme in
var out/eax: code-point-utf8 <- to-utf8 in
var out-int/eax: int <- copy out
check-ints-equal out-int, 0xbfdf, "F - to-grapheme/2b" # 110 1-1111 10 11-1111
check-ints-equal out-int, 0xbfdf, "F - to-utf8/2b" # 110 1-1111 10 11-1111
}
# smallest 3-byte utf-8
fn test-to-grapheme-three-bytes-min {
fn test-to-utf8-three-bytes-min {
var in/eax: code-point <- copy 0x800 # 10-0000 00-0000
var out/eax: grapheme <- to-grapheme in
var out/eax: code-point-utf8 <- to-utf8 in
var out-int/eax: int <- copy out
check-ints-equal out-int, 0x80a0e0, "F - to-grapheme/3a" # 1110 0000 10 10-0000 10 00-0000
check-ints-equal out-int, 0x80a0e0, "F - to-utf8/3a" # 1110 0000 10 10-0000 10 00-0000
}
# largest 3-byte utf-8
fn test-to-grapheme-three-bytes-max {
fn test-to-utf8-three-bytes-max {
var in/eax: code-point <- copy 0xffff # 1111 11-1111 11-1111
var out/eax: grapheme <- to-grapheme in
var out/eax: code-point-utf8 <- to-utf8 in
var out-int/eax: int <- copy out
check-ints-equal out-int, 0xbfbfef, "F - to-grapheme/3b" # 1110 1111 10 11-1111 10 11-1111
check-ints-equal out-int, 0xbfbfef, "F - to-utf8/3b" # 1110 1111 10 11-1111 10 11-1111
}
# smallest 4-byte utf-8
fn test-to-grapheme-four-bytes-min {
fn test-to-utf8-four-bytes-min {
var in/eax: code-point <- copy 0x10000 # 1-0000 00-0000 00-0000
var out/eax: grapheme <- to-grapheme in
var out/eax: code-point-utf8 <- to-utf8 in
var out-int/eax: int <- copy out
check-ints-equal out-int, 0x808090f0, "F - to-grapheme/4a" # 1111-0 000 10 01-0000 10 00-0000 10 00-0000
check-ints-equal out-int, 0x808090f0, "F - to-utf8/4a" # 1111-0 000 10 01-0000 10 00-0000 10 00-0000
}
# largest 4-byte utf-8
fn test-to-grapheme-four-bytes-max {
fn test-to-utf8-four-bytes-max {
var in/eax: code-point <- copy 0x1fffff # 111 11-1111 11-1111 11-1111
var out/eax: grapheme <- to-grapheme in
var out/eax: code-point-utf8 <- to-utf8 in
var out-int/eax: int <- copy out
check-ints-equal out-int, 0xbfbfbff7, "F - to-grapheme/4b" # 1111-0 111 10 11-1111 10 11-1111 10 11-1111
check-ints-equal out-int, 0xbfbfbff7, "F - to-utf8/4b" # 1111-0 111 10 11-1111 10 11-1111 10 11-1111
}
# read the next grapheme from a stream of bytes
fn read-grapheme in: (addr stream byte) -> _/eax: grapheme {
# read the next code-point-utf8 from a stream of bytes
fn read-code-point-utf8 in: (addr stream byte) -> _/eax: code-point-utf8 {
# if at eof, return EOF
{
var eof?/eax: boolean <- stream-empty? in
@ -241,18 +236,18 @@ fn read-grapheme in: (addr stream byte) -> _/eax: grapheme {
}
var c/eax: byte <- read-byte in
var num-trailers/ecx: int <- copy 0
$read-grapheme:compute-length: {
$read-code-point-utf8:compute-length: {
# single byte: just return it
compare c, 0xc0
{
break-if->=
var g/eax: grapheme <- copy c
var g/eax: code-point-utf8 <- copy c
return g
}
compare c, 0xfe
{
break-if-<
var g/eax: grapheme <- copy c
var g/eax: code-point-utf8 <- copy c
return g
}
# 2 bytes
@ -260,27 +255,27 @@ fn read-grapheme in: (addr stream byte) -> _/eax: grapheme {
{
break-if->=
num-trailers <- copy 1
break $read-grapheme:compute-length
break $read-code-point-utf8:compute-length
}
# 3 bytes
compare c, 0xf0
{
break-if->=
num-trailers <- copy 2
break $read-grapheme:compute-length
break $read-code-point-utf8:compute-length
}
# 4 bytes
compare c, 0xf8
{
break-if->=
num-trailers <- copy 3
break $read-grapheme:compute-length
break $read-code-point-utf8:compute-length
}
abort "utf-8 encodings larger than 4 bytes are not yet supported"
return 0
}
# prepend trailer bytes
var result/edi: grapheme <- copy c
var result/edi: code-point-utf8 <- copy c
var num-byte-shifts/edx: int <- copy 1
{
compare num-trailers, 0
@ -297,34 +292,34 @@ fn read-grapheme in: (addr stream byte) -> _/eax: grapheme {
return result
}
fn test-read-grapheme {
fn test-read-code-point-utf8 {
var s: (stream byte 0x30)
var s2/ecx: (addr stream byte) <- address s
write s2, "aΒcde"
var c/eax: grapheme <- read-grapheme s2
var c/eax: code-point-utf8 <- read-code-point-utf8 s2
var n/eax: int <- copy c
check-ints-equal n, 0x61, "F - test grapheme/0"
var c/eax: grapheme <- read-grapheme s2
check-ints-equal n, 0x61, "F - test code-point-utf8/0"
var c/eax: code-point-utf8 <- read-code-point-utf8 s2
var n/eax: int <- copy c
check-ints-equal n, 0x92ce/greek-capital-letter-beta, "F - test grapheme/1"
var c/eax: grapheme <- read-grapheme s2
check-ints-equal n, 0x92ce/greek-capital-letter-beta, "F - test code-point-utf8/1"
var c/eax: code-point-utf8 <- read-code-point-utf8 s2
var n/eax: int <- copy c
check-ints-equal n, 0x63, "F - test grapheme/2"
var c/eax: grapheme <- read-grapheme s2
check-ints-equal n, 0x63, "F - test code-point-utf8/2"
var c/eax: code-point-utf8 <- read-code-point-utf8 s2
var n/eax: int <- copy c
check-ints-equal n, 0x96b8e4, "F - test grapheme/3"
var c/eax: grapheme <- read-grapheme s2
check-ints-equal n, 0x96b8e4, "F - test code-point-utf8/3"
var c/eax: code-point-utf8 <- read-code-point-utf8 s2
var n/eax: int <- copy c
check-ints-equal n, 0x64, "F - test grapheme/4"
var c/eax: grapheme <- read-grapheme s2
check-ints-equal n, 0x64, "F - test code-point-utf8/4"
var c/eax: code-point-utf8 <- read-code-point-utf8 s2
var n/eax: int <- copy c
check-ints-equal n, 0x8c95e7, "F - test grapheme/5"
var c/eax: grapheme <- read-grapheme s2
check-ints-equal n, 0x8c95e7, "F - test code-point-utf8/5"
var c/eax: code-point-utf8 <- read-code-point-utf8 s2
var n/eax: int <- copy c
check-ints-equal n, 0x65, "F - test grapheme/6"
check-ints-equal n, 0x65, "F - test code-point-utf8/6"
}
fn grapheme-length g: grapheme -> _/edx: int {
fn utf8-length g: code-point-utf8 -> _/edx: int {
{
compare g, 0xff
break-if->
@ -389,23 +384,23 @@ fn test-shift-left-bytes-5 {
check-ints-equal result, 0, "F - shift-left-bytes >4"
}
# write a grapheme to a stream of bytes
# write a code-point-utf8 to a stream of bytes
# this is like write-to-stream, except we skip leading 0 bytes
fn write-grapheme out: (addr stream byte), g: grapheme {
$write-grapheme:body: {
fn write-code-point-utf8 out: (addr stream byte), g: code-point-utf8 {
$write-code-point-utf8:body: {
var c/eax: int <- copy g
append-byte out, c # first byte is always written
c <- shift-right 8
compare c, 0
break-if-= $write-grapheme:body
break-if-= $write-code-point-utf8:body
append-byte out, c
c <- shift-right 8
compare c, 0
break-if-= $write-grapheme:body
break-if-= $write-code-point-utf8:body
append-byte out, c
c <- shift-right 8
compare c, 0
break-if-= $write-grapheme:body
break-if-= $write-code-point-utf8:body
append-byte out, c
}
}

20
411string.mu

@ -1,4 +1,4 @@
# read up to 'len' graphemes after skipping the first 'start' ones
# read up to 'len' code-point-utf8s after skipping the first 'start' ones
fn substring in: (addr array byte), start: int, len: int, out-ah: (addr handle array byte) {
var in-stream: (stream byte 0x100)
var in-stream-addr/esi: (addr stream byte) <- address in-stream
@ -6,29 +6,29 @@ fn substring in: (addr array byte), start: int, len: int, out-ah: (addr handle a
var out-stream: (stream byte 0x100)
var out-stream-addr/edi: (addr stream byte) <- address out-stream
$substring:core: {
# skip 'start' graphemes
# skip 'start' code-point-utf8s
var i/eax: int <- copy 0
{
compare i, start
break-if->=
{
var dummy/eax: grapheme <- read-grapheme in-stream-addr
var dummy/eax: code-point-utf8 <- read-code-point-utf8 in-stream-addr
compare dummy, 0xffffffff/end-of-file
break-if-= $substring:core
}
i <- increment
loop
}
# copy 'len' graphemes
# copy 'len' code-point-utf8s
i <- copy 0
{
compare i, len
break-if->=
{
var g/eax: grapheme <- read-grapheme in-stream-addr
var g/eax: code-point-utf8 <- read-code-point-utf8 in-stream-addr
compare g, 0xffffffff/end-of-file
break-if-= $substring:core
write-grapheme out-stream-addr, g
write-code-point-utf8 out-stream-addr, g
}
i <- increment
loop
@ -85,7 +85,7 @@ fn test-substring {
check-strings-equal out, "bcde", "F - test-substring/middle-too-small"
}
fn split-string in: (addr array byte), delim: grapheme, out: (addr handle array (handle array byte)) {
fn split-string in: (addr array byte), delim: code-point-utf8, out: (addr handle array (handle array byte)) {
var in-stream: (stream byte 0x100)
var in-stream-addr/esi: (addr stream byte) <- address in-stream
write in-stream-addr, in
@ -94,10 +94,10 @@ fn split-string in: (addr array byte), delim: grapheme, out: (addr handle array
var curr-stream: (stream byte 0x100)
var curr-stream-addr/ecx: (addr stream byte) <- address curr-stream
$split-string:core: {
var g/eax: grapheme <- read-grapheme in-stream-addr
var g/eax: code-point-utf8 <- read-code-point-utf8 in-stream-addr
compare g, 0xffffffff
break-if-=
#? print-grapheme-to-real-screen g
#? print-code-point-utf8-to-real-screen g
#? print-string-to-real-screen "\n"
compare g, delim
{
@ -110,7 +110,7 @@ fn split-string in: (addr array byte), delim: grapheme, out: (addr handle array
clear-stream curr-stream-addr
loop $split-string:core
}
write-grapheme curr-stream-addr, g
write-code-point-utf8 curr-stream-addr, g
loop
}
stream-to-array tokens-stream-addr, out

4
500fake-screen.mu

@ -71,7 +71,7 @@ fn initialize-screen _screen: (addr screen), width: int, height: int, pixel-grap
copy-to *dest, 0
}
# in graphemes
# in code-point-utf8s
fn screen-size _screen: (addr screen) -> _/eax: int, _/ecx: int {
var screen/esi: (addr screen) <- copy _screen
var width/eax: int <- copy 0
@ -459,7 +459,7 @@ fn clear-rect _screen: (addr screen), xmin: int, ymin: int, xmax: int, ymax: int
set-cursor-position screen, 0, 0
}
# there's no grapheme that guarantees to cover every pixel, so we'll bump down
# there's no code-point-utf8 that guarantees to cover every pixel, so we'll bump down
# to pixels for a real screen
fn clear-real-screen {
var y/eax: int <- copy 0

14
501draw-text.mu

@ -117,7 +117,7 @@ fn draw-text-rightward screen: (addr screen), text: (addr array byte), x: int, x
fn draw-stream-rightward screen: (addr screen), stream: (addr stream byte), x: int, xmax: int, y: int, color: int, background-color: int -> _/eax: int {
var xcurr/ecx: int <- copy x
{
var g/eax: grapheme <- read-grapheme stream
var g/eax: code-point-utf8 <- read-code-point-utf8 stream
compare g, 0xffffffff/end-of-file
break-if-=
var c/eax: code-point <- to-code-point g
@ -218,7 +218,7 @@ fn draw-stream-wrapping-right-then-down screen: (addr screen), stream: (addr str
next-c <- copy 0
break $draw-stream-wrapping-right-then-down:read-base
}
var g/eax: grapheme <- read-grapheme stream
var g/eax: code-point-utf8 <- read-code-point-utf8 stream
var _c/eax: code-point <- to-code-point g
c <- copy _c
}
@ -240,7 +240,7 @@ fn draw-stream-wrapping-right-then-down screen: (addr screen), stream: (addr str
compare done?, 0/false
break-if-!=
# read a character
var g/eax: grapheme <- read-grapheme stream
var g/eax: code-point-utf8 <- read-code-point-utf8 stream
var c/eax: code-point <- to-code-point g
# if not a combining character, save for next iteration and loop
{
@ -343,7 +343,7 @@ fn draw-int32-hex-wrapping-right-then-down screen: (addr screen), n: int, xmin:
var xcurr/edx: int <- copy x
var ycurr/ecx: int <- copy y
{
var g/eax: grapheme <- read-grapheme stream
var g/eax: code-point-utf8 <- read-code-point-utf8 stream
compare g, 0xffffffff/end-of-file
break-if-=
var c/eax: code-point <- to-code-point g
@ -398,7 +398,7 @@ fn draw-int32-decimal-wrapping-right-then-down screen: (addr screen), n: int, xm
var xcurr/edx: int <- copy x
var ycurr/ecx: int <- copy y
{
var g/eax: grapheme <- read-grapheme stream
var g/eax: code-point-utf8 <- read-code-point-utf8 stream
compare g, 0xffffffff/end-of-file
break-if-=
var c/eax: code-point <- to-code-point g
@ -466,7 +466,7 @@ fn draw-text-downward screen: (addr screen), text: (addr array byte), x: int, y:
fn draw-stream-downward screen: (addr screen), stream: (addr stream byte), x: int, y: int, ymax: int, color: int, background-color: int -> _/eax: int {
var ycurr/ecx: int <- copy y
{
var g/eax: grapheme <- read-grapheme stream
var g/eax: code-point-utf8 <- read-code-point-utf8 stream
compare g, 0xffffffff/end-of-file
break-if-=
var c/eax: code-point <- to-code-point g
@ -508,7 +508,7 @@ fn draw-stream-wrapping-down-then-right screen: (addr screen), stream: (addr str
var xcurr/edx: int <- copy x
var ycurr/ecx: int <- copy y
{
var g/eax: grapheme <- read-grapheme stream
var g/eax: code-point-utf8 <- read-code-point-utf8 stream
compare g, 0xffffffff/end-of-file
break-if-=
var c/eax: code-point <- to-code-point g

66
504test-screen.mu

@ -12,7 +12,7 @@ fn check-screen-row-from _screen: (addr screen), x: int, y: int, expected: (addr
var screen/esi: (addr screen) <- copy _screen
var failure-count/edi: int <- copy 0
var index/ecx: int <- screen-cell-index screen, x, y
# compare 'expected' with the screen contents starting at 'index', grapheme by grapheme
# compare 'expected' with the screen contents starting at 'index', code-point-utf8 by code-point-utf8
var e: (stream byte 0x100)
var e-addr/edx: (addr stream byte) <- address e
write e-addr, expected
@ -26,16 +26,16 @@ fn check-screen-row-from _screen: (addr screen), x: int, y: int, expected: (addr
break-if-!=
var _c/eax: code-point <- screen-code-point-at-index screen, index
var c/ebx: code-point <- copy _c
var expected-grapheme/eax: grapheme <- read-grapheme e-addr
var expected-code-point/eax: code-point <- to-code-point expected-grapheme
# compare graphemes
$check-screen-row-from:compare-graphemes: {
# if expected-code-point is space, null grapheme is also ok
var expected-code-point-utf8/eax: code-point-utf8 <- read-code-point-utf8 e-addr
var expected-code-point/eax: code-point <- to-code-point expected-code-point-utf8
# compare code-point-utf8s
$check-screen-row-from:compare-code-point-utf8s: {
# if expected-code-point is space, null code-point-utf8 is also ok
{
compare expected-code-point, 0x20
break-if-!=
compare c, 0
break-if-= $check-screen-row-from:compare-graphemes
break-if-= $check-screen-row-from:compare-code-point-utf8s
}
# if (c == expected-code-point) print "."
compare c, expected-code-point
@ -79,7 +79,7 @@ fn check-screen-row-in-color screen: (addr screen), fg: int, y: int, expected: (
fn check-screen-row-in-color-from _screen: (addr screen), fg: int, y: int, x: int, expected: (addr array byte), msg: (addr array byte) {
var screen/esi: (addr screen) <- copy _screen
var index/ecx: int <- screen-cell-index screen, x, y
# compare 'expected' with the screen contents starting at 'index', grapheme by grapheme
# compare 'expected' with the screen contents starting at 'index', code-point-utf8 by code-point-utf8
var e: (stream byte 0x100)
var e-addr/edx: (addr stream byte) <- address e
write e-addr, expected
@ -93,11 +93,11 @@ fn check-screen-row-in-color-from _screen: (addr screen), fg: int, y: int, x: in
break-if-!=
var _c/eax: code-point <- screen-code-point-at-index screen, index
var c/ebx: code-point <- copy _c
var expected-grapheme/eax: grapheme <- read-grapheme e-addr
var _expected-code-point/eax: code-point <- to-code-point expected-grapheme
var expected-code-point-utf8/eax: code-point-utf8 <- read-code-point-utf8 e-addr
var _expected-code-point/eax: code-point <- to-code-point expected-code-point-utf8
var expected-code-point/edi: code-point <- copy _expected-code-point
$check-screen-row-in-color-from:compare-cells: {
# if expected-code-point is space, null grapheme is also ok
# if expected-code-point is space, null code-point-utf8 is also ok
{
compare expected-code-point, 0x20
break-if-!=
@ -112,14 +112,14 @@ fn check-screen-row-in-color-from _screen: (addr screen), fg: int, y: int, x: in
compare color, fg
break-if-!= $check-screen-row-in-color-from:compare-cells
}
# compare graphemes
$check-screen-row-in-color-from:compare-graphemes: {
# compare code-point-utf8s
$check-screen-row-in-color-from:compare-code-point-utf8s: {
# if (c == expected-code-point) print "."
compare c, expected-code-point
{
break-if-!=
draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, ".", 3/fg=cyan, 0/bg
break $check-screen-row-in-color-from:compare-graphemes
break $check-screen-row-in-color-from:compare-code-point-utf8s
}
# otherwise print an error
count-test-failure
@ -173,7 +173,7 @@ fn check-screen-row-in-background-color screen: (addr screen), bg: int, y: int,
fn check-screen-row-in-background-color-from _screen: (addr screen), bg: int, y: int, x: int, expected: (addr array byte), msg: (addr array byte) {
var screen/esi: (addr screen) <- copy _screen
var index/ecx: int <- screen-cell-index screen, x, y
# compare 'expected' with the screen contents starting at 'index', grapheme by grapheme
# compare 'expected' with the screen contents starting at 'index', code-point-utf8 by code-point-utf8
var e: (stream byte 0x100)
var e-addr/edx: (addr stream byte) <- address e
write e-addr, expected
@ -187,11 +187,11 @@ fn check-screen-row-in-background-color-from _screen: (addr screen), bg: int, y:
break-if-!=
var _g/eax: code-point <- screen-code-point-at-index screen, index
var g/ebx: code-point <- copy _g
var expected-grapheme/eax: grapheme <- read-grapheme e-addr
var _expected-code-point/eax: code-point <- to-code-point expected-grapheme
var expected-code-point-utf8/eax: code-point-utf8 <- read-code-point-utf8 e-addr
var _expected-code-point/eax: code-point <- to-code-point expected-code-point-utf8
var expected-code-point/edi: code-point <- copy _expected-code-point
$check-screen-row-in-background-color-from:compare-cells: {
# if expected-code-point is space, null grapheme is also ok
# if expected-code-point is space, null code-point-utf8 is also ok
{
compare expected-code-point, 0x20
break-if-!=
@ -206,14 +206,14 @@ fn check-screen-row-in-background-color-from _screen: (addr screen), bg: int, y:
compare background-color, bg
break-if-!= $check-screen-row-in-background-color-from:compare-cells
}
# compare graphemes
$check-screen-row-in-background-color-from:compare-graphemes: {
# compare code-point-utf8s
$check-screen-row-in-background-color-from:compare-code-point-utf8s: {
# if (g == expected-code-point) print "."
compare g, expected-code-point
{
break-if-!=
draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, ".", 3/fg=cyan, 0/bg
break $check-screen-row-in-background-color-from:compare-graphemes
break $check-screen-row-in-background-color-from:compare-code-point-utf8s
}
# otherwise print an error
count-test-failure
@ -228,7 +228,7 @@ fn check-screen-row-in-background-color-from _screen: (addr screen), bg: int, y:
draw-code-point-at-cursor-over-full-screen 0/screen, g, 3/cyan, 0/bg
draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "'", 3/fg=cyan, 0/bg
move-cursor-to-left-margin-of-next-line 0/screen
break $check-screen-row-in-background-color-from:compare-graphemes
break $check-screen-row-in-background-color-from:compare-code-point-utf8s
}
$check-screen-row-in-background-color-from:compare-background-colors: {
var background-color/eax: int <- screen-background-color-at-index screen, index
@ -284,8 +284,8 @@ fn check-background-color-in-screen-row-from _screen: (addr screen), bg: int, y:
var unused?/eax: boolean <- screen-cell-unused-at-index? screen, index
compare unused?, 0/false
break-if-!=
var _expected-bit/eax: grapheme <- read-grapheme e-addr
var expected-bit/edi: grapheme <- copy _expected-bit
var _expected-bit/eax: code-point-utf8 <- read-code-point-utf8 e-addr
var expected-bit/edi: code-point-utf8 <- copy _expected-bit
$check-background-color-in-screen-row-from:compare-cells: {
var background-color/eax: int <- screen-background-color-at-index screen, index
# if expected-bit is space, assert that background is NOT bg
@ -336,23 +336,23 @@ fn check-background-color-in-screen-row-from _screen: (addr screen), bg: int, y:
draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, ".", 3/fg=cyan, 0/bg
}
fn test-draw-single-grapheme {
fn test-draw-single-code-point-utf8 {
var _screen: screen
var screen/esi: (addr screen) <- address _screen
initialize-screen screen, 5, 4, 0/no-pixel-graphics
var dummy/eax: int <- draw-code-point screen, 0x61/a, 0/x, 0/y, 1/fg, 2/bg
check-screen-row screen, 0/y, "a", "F - test-draw-single-grapheme" # top-left corner of the screen
check-screen-row-in-color screen, 1/fg, 0/y, "a", "F - test-draw-single-grapheme-fg"
check-screen-row-in-background-color screen, 2/bg, 0/y, "a", "F - test-draw-single-grapheme-bg"
check-background-color-in-screen-row screen, 2/bg, 0/y, "x ", "F - test-draw-single-grapheme-bg2"
check-screen-row screen, 0/y, "a", "F - test-draw-single-code-point-utf8" # top-left corner of the screen
check-screen-row-in-color screen, 1/fg, 0/y, "a", "F - test-draw-single-code-point-utf8-fg"
check-screen-row-in-background-color screen, 2/bg, 0/y, "a", "F - test-draw-single-code-point-utf8-bg"
check-background-color-in-screen-row screen, 2/bg, 0/y, "x ", "F - test-draw-single-code-point-utf8-bg2"
}
fn test-draw-multiple-graphemes {
fn test-draw-multiple-code-point-utf8s {
var _screen: screen
var screen/esi: (addr screen) <- address _screen
initialize-screen screen, 0x10/rows, 4/cols, 0/no-pixel-graphics
draw-text-wrapping-right-then-down-from-cursor-over-full-screen screen, "Hello, 世界", 1/fg, 2/bg
check-screen-row screen, 0/y, "Hello, 世界", "F - test-draw-multiple-graphemes"
check-screen-row-in-color screen, 1/fg, 0/y, "Hello, 世界", "F - test-draw-multiple-graphemes-fg"
check-background-color-in-screen-row screen, 2/bg, 0/y, "xxxxxxxxx ", "F - test-draw-multiple-graphemes-bg2"
check-screen-row screen, 0/y, "Hello, 世界", "F - test-draw-multiple-code-point-utf8s"
check-screen-row-in-color screen, 1/fg, 0/y, "Hello, 世界", "F - test-draw-multiple-code-point-utf8s-fg"
check-background-color-in-screen-row screen, 2/bg, 0/y, "xxxxxxxxx ", "F - test-draw-multiple-code-point-utf8s-bg2"
}

336
513grapheme-stack.mu

@ -1,26 +1,26 @@
# grapheme stacks are the smallest unit of editable text
# code-point-utf8 stacks are the smallest unit of editable text
type grapheme-stack {
data: (handle array grapheme)
type code-point-utf8-stack {
data: (handle array code-point-utf8)
top: int
}
fn initialize-grapheme-stack _self: (addr grapheme-stack), n: int {
var self/esi: (addr grapheme-stack) <- copy _self
var d/edi: (addr handle array grapheme) <- get self, data
fn initialize-code-point-utf8-stack _self: (addr code-point-utf8-stack), n: int {
var self/esi: (addr code-point-utf8-stack) <- copy _self
var d/edi: (addr handle array code-point-utf8) <- get self, data
populate d, n
var top/eax: (addr int) <- get self, top
copy-to *top, 0
}
fn clear-grapheme-stack _self: (addr grapheme-stack) {
var self/esi: (addr grapheme-stack) <- copy _self
fn clear-code-point-utf8-stack _self: (addr code-point-utf8-stack) {
var self/esi: (addr code-point-utf8-stack) <- copy _self
var top/eax: (addr int) <- get self, top
copy-to *top, 0
}
fn grapheme-stack-empty? _self: (addr grapheme-stack) -> _/eax: boolean {
var self/esi: (addr grapheme-stack) <- copy _self
fn code-point-utf8-stack-empty? _self: (addr code-point-utf8-stack) -> _/eax: boolean {
var self/esi: (addr code-point-utf8-stack) <- copy _self
var top/eax: (addr int) <- get self, top
compare *top, 0
{
@ -30,26 +30,26 @@ fn grapheme-stack-empty? _self: (addr grapheme-stack) -> _/eax: boolean {
return 0/false
}
fn grapheme-stack-length _self: (addr grapheme-stack) -> _/eax: int {
var self/esi: (addr grapheme-stack) <- copy _self
fn code-point-utf8-stack-length _self: (addr code-point-utf8-stack) -> _/eax: int {
var self/esi: (addr code-point-utf8-stack) <- copy _self
var top/eax: (addr int) <- get self, top
return *top
}
fn push-grapheme-stack _self: (addr grapheme-stack), _val: grapheme {
var self/esi: (addr grapheme-stack) <- copy _self
fn push-code-point-utf8-stack _self: (addr code-point-utf8-stack), _val: code-point-utf8 {
var self/esi: (addr code-point-utf8-stack) <- copy _self
var top-addr/ecx: (addr int) <- get self, top
var data-ah/edx: (addr handle array grapheme) <- get self, data
var data/eax: (addr array grapheme) <- lookup *data-ah
var data-ah/edx: (addr handle array code-point-utf8) <- get self, data
var data/eax: (addr array code-point-utf8) <- lookup *data-ah
var top/edx: int <- copy *top-addr
var dest-addr/edx: (addr grapheme) <- index data, top
var val/eax: grapheme <- copy _val
var dest-addr/edx: (addr code-point-utf8) <- index data, top
var val/eax: code-point-utf8 <- copy _val
copy-to *dest-addr, val
add-to *top-addr, 1
}
fn pop-grapheme-stack _self: (addr grapheme-stack) -> _/eax: grapheme {
var self/esi: (addr grapheme-stack) <- copy _self
fn pop-code-point-utf8-stack _self: (addr code-point-utf8-stack) -> _/eax: code-point-utf8 {
var self/esi: (addr code-point-utf8-stack) <- copy _self
var top-addr/ecx: (addr int) <- get self, top
{
compare *top-addr, 0
@ -57,25 +57,25 @@ fn pop-grapheme-stack _self: (addr grapheme-stack) -> _/eax: grapheme {
return -1
}
subtract-from *top-addr, 1
var data-ah/edx: (addr handle array grapheme) <- get self, data
var data/eax: (addr array grapheme) <- lookup *data-ah
var data-ah/edx: (addr handle array code-point-utf8) <- get self, data
var data/eax: (addr array code-point-utf8) <- lookup *data-ah
var top/edx: int <- copy *top-addr
var result-addr/eax: (addr grapheme) <- index data, top
var result-addr/eax: (addr code-point-utf8) <- index data, top
return *result-addr
}
fn copy-grapheme-stack _src: (addr grapheme-stack), dest: (addr grapheme-stack) {
var src/esi: (addr grapheme-stack) <- copy _src
var data-ah/edi: (addr handle array grapheme) <- get src, data
var _data/eax: (addr array grapheme) <- lookup *data-ah
var data/edi: (addr array grapheme) <- copy _data
fn copy-code-point-utf8-stack _src: (addr code-point-utf8-stack), dest: (addr code-point-utf8-stack) {
var src/esi: (addr code-point-utf8-stack) <- copy _src
var data-ah/edi: (addr handle array code-point-utf8) <- get src, data
var _data/eax: (addr array code-point-utf8) <- lookup *data-ah
var data/edi: (addr array code-point-utf8) <- copy _data
var top-addr/ecx: (addr int) <- get src, top
var i/eax: int <- copy 0
{
compare i, *top-addr
break-if->=
var g/edx: (addr grapheme) <- index data, i
push-grapheme-stack dest, *g
var g/edx: (addr code-point-utf8) <- index data, i
push-code-point-utf8-stack dest, *g
i <- increment
loop
}
@ -84,12 +84,12 @@ fn copy-grapheme-stack _src: (addr grapheme-stack), dest: (addr grapheme-stack)
# dump stack to screen from bottom to top
# hardcoded colors:
# matching paren
fn render-stack-from-bottom-wrapping-right-then-down screen: (addr screen), _self: (addr grapheme-stack), xmin: int, ymin: int, xmax: int, ymax: int, _x: int, _y: int, highlight-matching-open-paren?: boolean, open-paren-depth: int, color: int, background-color: int -> _/eax: int, _/ecx: int {
var self/esi: (addr grapheme-stack) <- copy _self
fn render-stack-from-bottom-wrapping-right-then-down screen: (addr screen), _self: (addr code-point-utf8-stack), xmin: int, ymin: int, xmax: int, ymax: int, _x: int, _y: int, highlight-matching-open-paren?: boolean, open-paren-depth: int, color: int, background-color: int -> _/eax: int, _/ecx: int {
var self/esi: (addr code-point-utf8-stack) <- copy _self
var matching-open-paren-index/edx: int <- get-matching-open-paren-index self, highlight-matching-open-paren?, open-paren-depth
var data-ah/edi: (addr handle array grapheme) <- get self, data
var _data/eax: (addr array grapheme) <- lookup *data-ah
var data/edi: (addr array grapheme) <- copy _data
var data-ah/edi: (addr handle array code-point-utf8) <- get self, data
var _data/eax: (addr array code-point-utf8) <- lookup *data-ah
var data/edi: (addr array code-point-utf8) <- copy _data
var x/eax: int <- copy _x
var y/ecx: int <- copy _y
var top-addr/esi: (addr int) <- get self, top
@ -100,7 +100,7 @@ fn render-stack-from-bottom-wrapping-right-then-down screen: (addr screen), _sel
{
var c: code-point
{
var g/eax: (addr grapheme) <- index data, i
var g/eax: (addr code-point-utf8) <- index data, i
var tmp/eax: code-point <- to-code-point *g
copy-to c, tmp
}
@ -123,7 +123,7 @@ fn render-stack-from-bottom-wrapping-right-then-down screen: (addr screen), _sel
}
# helper for small words
fn render-stack-from-bottom screen: (addr screen), self: (addr grapheme-stack), x: int, y: int, highlight-matching-open-paren?: boolean, open-paren-depth: int -> _/eax: int {
fn render-stack-from-bottom screen: (addr screen), self: (addr code-point-utf8-stack), x: int, y: int, highlight-matching-open-paren?: boolean, open-paren-depth: int -> _/eax: int {
var _width/eax: int <- copy 0
var _height/ecx: int <- copy 0
_width, _height <- screen-size screen
@ -136,16 +136,16 @@ fn render-stack-from-bottom screen: (addr screen), self: (addr grapheme-stack),
}
# dump stack to screen from top to bottom
# optionally render a 'cursor' with the top grapheme
# optionally render a 'cursor' with the top code-point-utf8
# hard-coded colors:
# matching paren
# cursor
fn render-stack-from-top-wrapping-right-then-down screen: (addr screen), _self: (addr grapheme-stack), xmin: int, ymin: int, xmax: int, ymax: int, _x: int, _y: int, render-cursor?: boolean, color: int, background-color: int -> _/eax: int, _/ecx: int {
var self/esi: (addr grapheme-stack) <- copy _self
fn render-stack-from-top-wrapping-right-then-down screen: (addr screen), _self: (addr code-point-utf8-stack), xmin: int, ymin: int, xmax: int, ymax: int, _x: int, _y: int, render-cursor?: boolean, color: int, background-color: int -> _/eax: int, _/ecx: int {
var self/esi: (addr code-point-utf8-stack) <- copy _self
var matching-close-paren-index/edx: int <- get-matching-close-paren-index self, render-cursor?
var data-ah/eax: (addr handle array grapheme) <- get self, data
var _data/eax: (addr array grapheme) <- lookup *data-ah
var data/edi: (addr array grapheme) <- copy _data
var data-ah/eax: (addr handle array code-point-utf8) <- get self, data
var _data/eax: (addr array code-point-utf8) <- lookup *data-ah
var data/edi: (addr array code-point-utf8) <- copy _data
var x/eax: int <- copy _x
var y/ecx: int <- copy _y
var top-addr/ebx: (addr int) <- get self, top
@ -159,7 +159,7 @@ fn render-stack-from-top-wrapping-right-then-down screen: (addr screen), _self:
break-if-<
var c: code-point
{
var g/eax: (addr grapheme) <- index data, i
var g/eax: (addr code-point-utf8) <- index data, i
var tmp/eax: code-point <- to-code-point *g
copy-to c, tmp
}
@ -184,7 +184,7 @@ fn render-stack-from-top-wrapping-right-then-down screen: (addr screen), _self:
#
var c: code-point
{
var g/eax: (addr grapheme) <- index data, i
var g/eax: (addr code-point-utf8) <- index data, i
var tmp/eax: code-point <- to-code-point *g
copy-to c, tmp
}
@ -196,7 +196,7 @@ fn render-stack-from-top-wrapping-right-then-down screen: (addr screen), _self:
}
# helper for small words
fn render-stack-from-top screen: (addr screen), self: (addr grapheme-stack), x: int, y: int, render-cursor?: boolean -> _/eax: int {
fn render-stack-from-top screen: (addr screen), self: (addr code-point-utf8-stack), x: int, y: int, render-cursor?: boolean -> _/eax: int {
var _width/eax: int <- copy 0
var _height/ecx: int <- copy 0
_width, _height <- screen-size screen
@ -208,190 +208,190 @@ fn render-stack-from-top screen: (addr screen), self: (addr grapheme-stack), x:
return x2 # y2? yolo
}
fn test-render-grapheme-stack {
fn test-render-code-point-utf8-stack {
# setup: gs = "abc"
var gs-storage: grapheme-stack
var gs/edi: (addr grapheme-stack) <- address gs-storage
initialize-grapheme-stack gs, 5
var g/eax: grapheme <- copy 0x61/a
push-grapheme-stack gs, g
var gs-storage: code-point-utf8-stack
var gs/edi: (addr code-point-utf8-stack) <- address gs-storage
initialize-code-point-utf8-stack gs, 5
var g/eax: code-point-utf8 <- copy 0x61/a
push-code-point-utf8-stack gs, g
g <- copy 0x62/b
push-grapheme-stack gs, g
push-code-point-utf8-stack gs, g
g <- copy 0x63/c
push-grapheme-stack gs, g
push-code-point-utf8-stack gs, g
# setup: screen
var screen-storage: screen
var screen/esi: (addr screen) <- address screen-storage
initialize-screen screen, 5, 4, 0/no-pixel-graphics
#
var x/eax: int <- render-stack-from-bottom screen, gs, 0/x, 0/y, 0/no-highlight-matching-open-paren, 0/open-paren-depth
check-screen-row screen, 0/y, "abc ", "F - test-render-grapheme-stack from bottom"
check-ints-equal x, 3, "F - test-render-grapheme-stack from bottom: result"
check-background-color-in-screen-row screen, 3/bg=reverse, 0/y, " ", "F - test-render-grapheme-stack from bottom: bg"
check-screen-row screen, 0/y, "abc ", "F - test-render-code-point-utf8-stack from bottom"
check-ints-equal x, 3, "F - test-render-code-point-utf8-stack from bottom: result"
check-background-color-in-screen-row screen, 3/bg=reverse, 0/y, " ", "F - test-render-code-point-utf8-stack from bottom: bg"
#
var x/eax: int <- render-stack-from-top screen, gs, 0/x, 1/y, 0/cursor=false
check-screen-row screen, 1/y, "cba ", "F - test-render-grapheme-stack from top without cursor"
check-ints-equal x, 3, "F - test-render-grapheme-stack from top without cursor: result"
check-background-color-in-screen-row screen, 3/bg=reverse, 1/y, " ", "F - test-render-grapheme-stack from top without cursor: bg"
check-screen-row screen, 1/y, "cba ", "F - test-render-code-point-utf8-stack from top without cursor"
check-ints-equal x, 3, "F - test-render-code-point-utf8-stack from top without cursor: result"
check-background-color-in-screen-row screen, 3/bg=reverse, 1/y, " ", "F - test-render-code-point-utf8-stack from top without cursor: bg"
#
var x/eax: int <- render-stack-from-top screen, gs, 0/x, 2/y, 1/cursor=true
check-screen-row screen, 2/y, "cba ", "F - test-render-grapheme-stack from top with cursor"
check-ints-equal x, 3, "F - test-render-grapheme-stack from top with cursor: result"
check-background-color-in-screen-row screen, 3/bg=reverse, 2/y, "| ", "F - test-render-grapheme-stack from top with cursor: bg"
check-screen-row screen, 2/y, "cba ", "F - test-render-code-point-utf8-stack from top with cursor"
check-ints-equal x, 3, "F - test-render-code-point-utf8-stack from top with cursor: result"
check-background-color-in-screen-row screen, 3/bg=reverse, 2/y, "| ", "F - test-render-code-point-utf8-stack from top with cursor: bg"
}
fn test-render-grapheme-stack-while-highlighting-matching-close-paren {
fn test-render-code-point-utf8-stack-while-highlighting-matching-close-paren {
# setup: gs = "(b)"
var gs-storage: grapheme-stack
var gs/edi: (addr grapheme-stack) <- address gs-storage
initialize-grapheme-stack gs, 5
var g/eax: grapheme <- copy 0x29/close-paren
push-grapheme-stack gs, g
var gs-storage: code-point-utf8-stack
var gs/edi: (addr code-point-utf8-stack) <- address gs-storage
initialize-code-point-utf8-stack gs, 5
var g/eax: code-point-utf8 <- copy 0x29/close-paren
push-code-point-utf8-stack gs, g
g <- copy 0x62/b
push-grapheme-stack gs, g
push-code-point-utf8-stack gs, g
g <- copy 0x28/open-paren
push-grapheme-stack gs, g
push-code-point-utf8-stack gs, g
# setup: screen
var screen-storage: screen
var screen/esi: (addr screen) <- address screen-storage
initialize-screen screen, 5, 4, 0/no-pixel-graphics
#
var x/eax: int <- render-stack-from-top screen, gs, 0/x, 2/y, 1/cursor=true
check-screen-row screen, 2/y, "(b) ", "F - test-render-grapheme-stack-while-highlighting-matching-close-paren"
check-background-color-in-screen-row screen, 3/bg=reverse, 2/y, "| ", "F - test-render-grapheme-stack-while-highlighting-matching-close-paren: cursor"
check-screen-row-in-color screen, 0xf/fg=white, 2/y, " ) ", "F - test-render-grapheme-stack-while-highlighting-matching-close-paren: matching paren"
check-screen-row screen, 2/y, "(b) ", "F - test-render-code-point-utf8-stack-while-highlighting-matching-close-paren"
check-background-color-in-screen-row screen, 3/bg=reverse, 2/y, "| ", "F - test-render-code-point-utf8-stack-while-highlighting-matching-close-paren: cursor"
check-screen-row-in-color screen, 0xf/fg=white, 2/y, " ) ", "F - test-render-code-point-utf8-stack-while-highlighting-matching-close-paren: matching paren"
}
fn test-render-grapheme-stack-while-highlighting-matching-close-paren-2 {
fn test-render-code-point-utf8-stack-while-highlighting-matching-close-paren-2 {
# setup: gs = "(a (b)) c"
var gs-storage: grapheme-stack
var gs/edi: (addr grapheme-stack) <- address gs-storage
initialize-grapheme-stack gs, 0x10
var g/eax: grapheme <- copy 0x63/c
push-grapheme-stack gs, g
var gs-storage: code-point-utf8-stack
var gs/edi: (addr code-point-utf8-stack) <- address gs-storage
initialize-code-point-utf8-stack gs, 0x10
var g/eax: code-point-utf8 <- copy 0x63/c
push-code-point-utf8-stack gs, g
g <- copy 0x20/space
push-grapheme-stack gs, g
push-code-point-utf8-stack gs, g
g <- copy 0x29/close-paren
push-grapheme-stack gs, g
push-code-point-utf8-stack gs, g
g <- copy 0x29/close-paren
push-grapheme-stack gs, g
push-code-point-utf8-stack gs, g
g <- copy 0x62/b
push-grapheme-stack gs, g
push-code-point-utf8-stack gs, g
g <- copy 0x28/open-paren
push-grapheme-stack gs, g
push-code-point-utf8-stack gs, g
g <- copy 0x20/space
push-grapheme-stack gs, g
push-code-point-utf8-stack gs, g
g <- copy 0x61/a
push-grapheme-stack gs, g
push-code-point-utf8-stack gs, g
g <- copy 0x28/open-paren
push-grapheme-stack gs, g
push-code-point-utf8-stack gs, g
# setup: screen
var screen-storage: screen
var screen/esi: (addr screen) <- address screen-storage
initialize-screen screen, 5, 4, 0/no-pixel-graphics
#
var x/eax: int <- render-stack-from-top screen, gs, 0/x, 2/y, 1/cursor=true
check-screen-row screen, 2/y, "(a (b)) c ", "F - test-render-grapheme-stack-while-highlighting-matching-close-paren-2"
check-background-color-in-screen-row screen, 3/bg=reverse, 2/y, "| ", "F - test-render-grapheme-stack-while-highlighting-matching-close-paren-2: cursor"
check-screen-row-in-color screen, 0xf/fg=white, 2/y, " ) ", "F - test-render-grapheme-stack-while-highlighting-matching-close-paren-2: matching paren"
check-screen-row screen, 2/y, "(a (b)) c ", "F - test-render-code-point-utf8-stack-while-highlighting-matching-close-paren-2"
check-background-color-in-screen-row screen, 3/bg=reverse, 2/y, "| ", "F - test-render-code-point-utf8-stack-while-highlighting-matching-close-paren-2: cursor"
check-screen-row-in-color screen, 0xf/fg=white, 2/y, " ) ", "F - test-render-code-point-utf8-stack-while-highlighting-matching-close-paren-2: matching paren"
}
fn test-render-grapheme-stack-while-highlighting-matching-open-paren-with-close-paren-at-end {
fn test-render-code-point-utf8-stack-while-highlighting-matching-open-paren-with-close-paren-at-end {
# setup: gs = "(b)"
var gs-storage: grapheme-stack
var gs/edi: (addr grapheme-stack) <- address gs-