From dd60caa3f51c5117c0193f8f3272e1c7f5230eb7 Mon Sep 17 00:00:00 2001
From: Kartik Agaram
- 1 type environment { - 2 globals: global-table - 3 sandbox: sandbox - 4 partial-function-name: (handle gap-buffer) - 5 cursor-in-globals?: boolean - 6 cursor-in-function-modal?: boolean - 7 } - 8 - 9 fn initialize-environment _self: (addr environment) { - 10 var self/esi: (addr environment) <- copy _self - 11 var globals/eax: (addr global-table) <- get self, globals - 12 initialize-globals globals - 13 var sandbox/eax: (addr sandbox) <- get self, sandbox - 14 initialize-sandbox sandbox, 1/with-screen - 15 var partial-function-name-ah/eax: (addr handle gap-buffer) <- get self, partial-function-name - 16 allocate partial-function-name-ah - 17 var partial-function-name/eax: (addr gap-buffer) <- lookup *partial-function-name-ah - 18 initialize-gap-buffer partial-function-name, 0x40/function-name-capacity - 19 } - 20 - 21 fn render-environment screen: (addr screen), _self: (addr environment) { - 22 # globals layout: 1 char padding, 41 code, 1 padding, 41 code, 1 padding = 85 - 23 # sandbox layout: 1 padding, 41 code, 1 padding = 43 - 24 # total = 128 chars - 25 var self/esi: (addr environment) <- copy _self - 26 var cursor-in-globals-a/eax: (addr boolean) <- get self, cursor-in-globals? - 27 var cursor-in-globals?/eax: boolean <- copy *cursor-in-globals-a - 28 var globals/ecx: (addr global-table) <- get self, globals - 29 render-globals screen, globals, cursor-in-globals? - 30 var sandbox/edx: (addr sandbox) <- get self, sandbox - 31 var cursor-in-sandbox?/ebx: boolean <- copy 1/true - 32 cursor-in-sandbox? <- subtract cursor-in-globals? - 33 render-sandbox screen, sandbox, 0x55/sandbox-left-margin, 0/sandbox-top-margin, 0x80/screen-width, 0x2f/screen-height-without-menu, cursor-in-sandbox? - 34 # modal if necessary - 35 { - 36 var cursor-in-function-modal-a/eax: (addr boolean) <- get self, cursor-in-function-modal? - 37 compare *cursor-in-function-modal-a, 0/false - 38 break-if-= - 39 render-function-modal screen, self - 40 render-function-modal-menu screen, self - 41 return - 42 } - 43 # render menu - 44 { - 45 var cursor-in-globals?/eax: (addr boolean) <- get self, cursor-in-globals? - 46 compare *cursor-in-globals?, 0/false - 47 break-if-= - 48 render-globals-menu screen, globals - 49 return - 50 } - 51 render-sandbox-menu screen, sandbox - 52 } - 53 - 54 fn edit-environment _self: (addr environment), key: grapheme, data-disk: (addr disk) { - 55 var self/esi: (addr environment) <- copy _self - 56 var globals/edi: (addr global-table) <- get self, globals - 57 var sandbox/ecx: (addr sandbox) <- get self, sandbox - 58 # ctrl-r - 59 # Assumption: 'real-screen' and 'real-keyboard' are 0 - 60 { - 61 compare key, 0x12/ctrl-r - 62 break-if-!= - 63 var tmp/eax: (addr handle cell) <- copy 0 - 64 var nil: (handle cell) - 65 tmp <- address nil - 66 allocate-pair tmp - 67 # (main real-screen real-keyboard) - 68 var real-keyboard: (handle cell) - 69 tmp <- address real-keyboard - 70 allocate-keyboard tmp - 71 # args = cons(real-keyboard, nil) - 72 var args: (handle cell) - 73 tmp <- address args - 74 new-pair tmp, real-keyboard, nil - 75 # - 76 var real-screen: (handle cell) - 77 tmp <- address real-screen - 78 allocate-screen tmp - 79 # args = cons(real-screen, args) - 80 tmp <- address args - 81 new-pair tmp, real-screen, *tmp - 82 # - 83 var main: (handle cell) - 84 tmp <- address main - 85 new-symbol tmp, "main" - 86 # args = cons(main, args) - 87 tmp <- address args - 88 new-pair tmp, main, *tmp - 89 # clear real screen - 90 clear-screen 0/screen - 91 set-cursor-position 0/screen, 0, 0 - 92 # run - 93 var out: (handle cell) - 94 var out-ah/ecx: (addr handle cell) <- address out - 95 var trace-storage: trace - 96 var trace/ebx: (addr trace) <- address trace-storage - 97 initialize-trace trace, 1/only-errors, 0x10/capacity, 0/visible - 98 evaluate tmp, out-ah, nil, globals, trace, 0/no-fake-screen, 0/no-fake-keyboard, 0/call-number - 99 # wait for a keypress -100 { -101 var tmp/eax: byte <- read-key 0/keyboard -102 compare tmp, 0 -103 loop-if-= -104 } -105 # -106 return -107 } -108 # ctrl-s: send multiple places -109 { -110 compare key, 0x13/ctrl-s -111 break-if-!= -112 { -113 # cursor in function modal? do nothing -114 var cursor-in-function-modal-a/eax: (addr boolean) <- get self, cursor-in-function-modal? -115 compare *cursor-in-function-modal-a, 0/false -116 break-if-!= -117 { -118 # cursor in globals? update current definition -119 var cursor-in-globals-a/edx: (addr boolean) <- get self, cursor-in-globals? -120 compare *cursor-in-globals-a, 0/false -121 break-if-= -122 edit-globals globals, key -123 } -124 # update sandbox whether the cursor is in globals or sandbox -125 edit-sandbox sandbox, key, globals, data-disk, 1/tweak-real-screen -126 } -127 return -128 } -129 # ctrl-g: go to a function (or the repl) -130 { -131 compare key, 7/ctrl-g -132 break-if-!= -133 var cursor-in-function-modal-a/eax: (addr boolean) <- get self, cursor-in-function-modal? -134 compare *cursor-in-function-modal-a, 0/false -135 break-if-!= -136 # look for a word to prepopulate the modal -137 var current-word-storage: (stream byte 0x40) -138 var current-word/edi: (addr stream byte) <- address current-word-storage -139 word-at-cursor self, current-word -140 var partial-function-name-ah/eax: (addr handle gap-buffer) <- get self, partial-function-name -141 var partial-function-name/eax: (addr gap-buffer) <- lookup *partial-function-name-ah -142 clear-gap-buffer partial-function-name -143 load-gap-buffer-from-stream partial-function-name, current-word -144 # enable the modal -145 var cursor-in-function-modal-a/eax: (addr boolean) <- get self, cursor-in-function-modal? -146 copy-to *cursor-in-function-modal-a, 1/true -147 return -148 } -149 # dispatch to function modal if necessary -150 { -151 var cursor-in-function-modal-a/eax: (addr boolean) <- get self, cursor-in-function-modal? -152 compare *cursor-in-function-modal-a, 0/false -153 break-if-= -154 # nested events for modal dialog -155 # ignore spaces -156 { -157 compare key, 0x20/space -158 break-if-!= -159 return -160 } -161 # esc = exit modal dialog -162 { -163 compare key, 0x1b/escape -164 break-if-!= -165 var cursor-in-function-modal-a/eax: (addr boolean) <- get self, cursor-in-function-modal? -166 copy-to *cursor-in-function-modal-a, 0/false -167 return -168 } -169 # enter = switch to function name and exit modal dialog -170 { -171 compare key, 0xa/newline -172 break-if-!= -173 var cursor-in-globals-a/edx: (addr boolean) <- get self, cursor-in-globals? -174 copy-to *cursor-in-globals-a, 1/true -175 var partial-function-name-ah/eax: (addr handle gap-buffer) <- get self, partial-function-name -176 var partial-function-name/eax: (addr gap-buffer) <- lookup *partial-function-name-ah -177 { -178 { -179 var empty?/eax: boolean <- gap-buffer-empty? partial-function-name -180 compare empty?, 0/false -181 } -182 break-if-!= -183 set-global-cursor-index globals, partial-function-name -184 } -185 var cursor-in-globals-a/ecx: (addr boolean) <- get self, cursor-in-globals? -186 copy-to *cursor-in-globals-a, 1/true -187 { -188 var empty?/eax: boolean <- gap-buffer-empty? partial-function-name -189 compare empty?, 0/false -190 break-if-= -191 copy-to *cursor-in-globals-a, 0/false -192 } -193 clear-gap-buffer partial-function-name -194 var cursor-in-function-modal-a/eax: (addr boolean) <- get self, cursor-in-function-modal? -195 copy-to *cursor-in-function-modal-a, 0/false -196 return -197 } -198 # otherwise process like a regular gap-buffer -199 var partial-function-name-ah/eax: (addr handle gap-buffer) <- get self, partial-function-name -200 var partial-function-name/eax: (addr gap-buffer) <- lookup *partial-function-name-ah -201 edit-gap-buffer partial-function-name, key -202 return -203 } -204 # dispatch the key to either sandbox or globals -205 { -206 var cursor-in-globals-a/eax: (addr boolean) <- get self, cursor-in-globals? -207 compare *cursor-in-globals-a, 0/false -208 break-if-= -209 edit-globals globals, key -210 return -211 } -212 edit-sandbox sandbox, key, globals, data-disk, 1/tweak-real-screen -213 } -214 -215 fn word-at-cursor _self: (addr environment), out: (addr stream byte) { -216 var self/esi: (addr environment) <- copy _self -217 var cursor-in-function-modal-a/eax: (addr boolean) <- get self, cursor-in-function-modal? -218 compare *cursor-in-function-modal-a, 0/false -219 { -220 break-if-= -221 # cursor in function modal -222 return -223 } -224 var cursor-in-globals-a/edx: (addr boolean) <- get self, cursor-in-globals? -225 compare *cursor-in-globals-a, 0/false -226 { -227 break-if-= -228 # cursor in some function editor -229 var globals/eax: (addr global-table) <- get self, globals -230 var cursor-index-addr/ecx: (addr int) <- get globals, cursor-index -231 var cursor-index/ecx: int <- copy *cursor-index-addr -232 var globals-data-ah/eax: (addr handle array global) <- get globals, data -233 var globals-data/eax: (addr array global) <- lookup *globals-data-ah -234 var cursor-offset/ecx: (offset global) <- compute-offset globals-data, cursor-index -235 var curr-global/eax: (addr global) <- index globals-data, cursor-offset -236 var curr-global-data-ah/eax: (addr handle gap-buffer) <- get curr-global, input -237 var curr-global-data/eax: (addr gap-buffer) <- lookup *curr-global-data-ah -238 word-at-gap curr-global-data, out -239 return -240 } -241 # cursor in sandbox -242 var sandbox/ecx: (addr sandbox) <- get self, sandbox -243 var sandbox-data-ah/eax: (addr handle gap-buffer) <- get sandbox, data -244 var sandbox-data/eax: (addr gap-buffer) <- lookup *sandbox-data-ah -245 word-at-gap sandbox-data, out -246 } -247 -248 fn render-function-modal screen: (addr screen), _self: (addr environment) { -249 var self/esi: (addr environment) <- copy _self -250 var width/eax: int <- copy 0 -251 var height/ecx: int <- copy 0 -252 width, height <- screen-size screen -253 # xmin = max(0, width/2 - 0x20) -254 var xmin: int -255 var tmp/edx: int <- copy width -256 tmp <- shift-right 1 -257 tmp <- subtract 0x20/half-function-name-capacity -258 { -259 compare tmp, 0 -260 break-if->= -261 tmp <- copy 0 -262 } -263 copy-to xmin, tmp -264 # xmax = min(width, width/2 + 0x20) -265 var xmax: int -266 tmp <- copy width -267 tmp <- shift-right 1 -268 tmp <- add 0x20/half-function-name-capacity -269 { -270 compare tmp, width -271 break-if-<= -272 tmp <- copy width -273 } -274 copy-to xmax, tmp -275 # ymin = height/2 - 2 -276 var ymin: int -277 tmp <- copy height -278 tmp <- shift-right 1 -279 tmp <- subtract 2 -280 copy-to ymin, tmp -281 # ymax = height/2 + 1 -282 var ymax: int -283 tmp <- add 3 -284 copy-to ymax, tmp -285 # -286 clear-rect screen, xmin, ymin, xmax, ymax, 0xf/bg=modal -287 add-to xmin, 4 -288 set-cursor-position screen, xmin, ymin -289 draw-text-rightward-from-cursor screen, "go to function (or leave blank to go to REPL)", xmax, 8/fg=dark-grey, 0xf/bg=modal -290 var partial-function-name-ah/eax: (addr handle gap-buffer) <- get self, partial-function-name -291 var _partial-function-name/eax: (addr gap-buffer) <- lookup *partial-function-name-ah -292 var partial-function-name/edx: (addr gap-buffer) <- copy _partial-function-name -293 subtract-from xmin, 4 -294 add-to ymin 2 -295 var dummy/eax: int <- copy 0 -296 var dummy2/ecx: int <- copy 0 -297 dummy, dummy2 <- render-gap-buffer-wrapping-right-then-down screen, partial-function-name, xmin, ymin, xmax, ymax, 1/always-render-cursor, 0/fg=black, 0xf/bg=modal -298 } -299 -300 fn render-function-modal-menu screen: (addr screen), _self: (addr environment) { -301 var self/esi: (addr environment) <- copy _self -302 var _width/eax: int <- copy 0 -303 var height/ecx: int <- copy 0 -304 _width, height <- screen-size screen -305 var width/edx: int <- copy _width -306 var y/ecx: int <- copy height -307 y <- decrement -308 var height/ebx: int <- copy y -309 height <- increment -310 clear-rect screen, 0/x, y, width, height, 0xc5/bg=blue-bg -311 set-cursor-position screen, 0/x, y -312 draw-text-rightward-from-cursor screen, " ^r ", width, 0/fg, 0x5c/bg=menu-highlight -313 draw-text-rightward-from-cursor screen, " run main ", width, 7/fg, 0xc5/bg=blue-bg -314 draw-text-rightward-from-cursor screen, " enter ", width, 0/fg, 0x5c/bg=menu-highlight -315 draw-text-rightward-from-cursor screen, " submit ", width, 7/fg, 0xc5/bg=blue-bg -316 draw-text-rightward-from-cursor screen, " esc ", width, 0/fg, 0x5c/bg=menu-highlight -317 draw-text-rightward-from-cursor screen, " cancel ", width, 7/fg, 0xc5/bg=blue-bg -318 draw-text-rightward-from-cursor screen, " ^a ", width, 0/fg, 0x5c/bg=menu-highlight -319 draw-text-rightward-from-cursor screen, " << ", width, 7/fg, 0xc5/bg=blue-bg -320 draw-text-rightward-from-cursor screen, " ^b ", width, 0/fg, 0x5c/bg=menu-highlight -321 draw-text-rightward-from-cursor screen, " <word ", width, 7/fg, 0xc5/bg=blue-bg -322 draw-text-rightward-from-cursor screen, " ^f ", width, 0/fg, 0x5c/bg=menu-highlight -323 draw-text-rightward-from-cursor screen, " word> ", width, 7/fg, 0xc5/bg=blue-bg -324 draw-text-rightward-from-cursor screen, " ^e ", width, 0/fg, 0x5c/bg=menu-highlight -325 draw-text-rightward-from-cursor screen, " >> ", width, 7/fg, 0xc5/bg=blue-bg -326 } -327 -328 # Gotcha: some saved state may not load. -329 fn load-state _self: (addr environment), data-disk: (addr disk) { -330 var self/esi: (addr environment) <- copy _self -331 # data-disk -> stream -332 var s-storage: (stream byte 0x1000) # space for 8/sectors -333 var s/ebx: (addr stream byte) <- address s-storage -334 draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "loading sectors from data disk", 3/fg, 0/bg -335 move-cursor-to-left-margin-of-next-line 0/screen -336 load-sectors data-disk, 0/lba, 8/sectors, s -337 #? draw-stream-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, s, 7/fg, 0xc5/bg=blue-bg -338 # stream -> gap-buffer (HACK: we temporarily cannibalize the sandbox's gap-buffer) -339 draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "parsing", 3/fg, 0/bg -340 move-cursor-to-left-margin-of-next-line 0/screen -341 var sandbox/eax: (addr sandbox) <- get self, sandbox -342 var data-ah/eax: (addr handle gap-buffer) <- get sandbox, data -343 var data/eax: (addr gap-buffer) <- lookup *data-ah -344 load-gap-buffer-from-stream data, s -345 draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, " into gap buffer", 3/fg, 0/bg -346 move-cursor-to-left-margin-of-next-line 0/screen -347 clear-stream s -348 # read: gap-buffer -> cell -349 var initial-root-storage: (handle cell) -350 var initial-root/ecx: (addr handle cell) <- address initial-root-storage -351 var trace-storage: trace -352 var trace/edi: (addr trace) <- address trace-storage -353 initialize-trace trace, 1/only-errors, 0x10/capacity, 0/visible -354 read-cell data, initial-root, trace -355 draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, " into s-expressions", 3/fg, 0/bg -356 move-cursor-to-left-margin-of-next-line 0/screen -357 clear-gap-buffer data -358 # -359 { -360 var initial-root-addr/eax: (addr cell) <- lookup *initial-root -361 compare initial-root-addr, 0 -362 break-if-!= -363 return -364 } -365 # load globals from assoc(initial-root, 'globals) -366 var globals-literal-storage: (handle cell) -367 var globals-literal-ah/eax: (addr handle cell) <- address globals-literal-storage -368 new-symbol globals-literal-ah, "globals" -369 var globals-literal/eax: (addr cell) <- lookup *globals-literal-ah -370 var globals-cell-storage: (handle cell) -371 var globals-cell-ah/edx: (addr handle cell) <- address globals-cell-storage -372 clear-trace trace -373 lookup-symbol globals-literal, globals-cell-ah, *initial-root, 0/no-globals, trace, 0/no-screen, 0/no-keyboard -374 var globals-cell/eax: (addr cell) <- lookup *globals-cell-ah -375 { -376 compare globals-cell, 0 -377 break-if-= -378 var globals/eax: (addr global-table) <- get self, globals -379 load-globals globals-cell-ah, globals -380 } -381 # sandbox = assoc(initial-root, 'sandbox) -382 draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "loading sandbox", 3/fg, 0/bg -383 var sandbox-literal-storage: (handle cell) -384 var sandbox-literal-ah/eax: (addr handle cell) <- address sandbox-literal-storage -385 new-symbol sandbox-literal-ah, "sandbox" -386 var sandbox-literal/eax: (addr cell) <- lookup *sandbox-literal-ah -387 var sandbox-cell-storage: (handle cell) -388 var sandbox-cell-ah/edx: (addr handle cell) <- address sandbox-cell-storage -389 clear-trace trace -390 lookup-symbol sandbox-literal, sandbox-cell-ah, *initial-root, 0/no-globals, trace, 0/no-screen, 0/no-keyboard -391 var sandbox-cell/eax: (addr cell) <- lookup *sandbox-cell-ah -392 { -393 compare sandbox-cell, 0 -394 break-if-= -395 # print: cell -> stream -396 clear-trace trace -397 print-cell sandbox-cell-ah, s, trace -398 # stream -> gap-buffer -399 var sandbox/eax: (addr sandbox) <- get self, sandbox -400 var data-ah/eax: (addr handle gap-buffer) <- get sandbox, data -401 var data/eax: (addr gap-buffer) <- lookup *data-ah -402 load-gap-buffer-from-stream data, s -403 } -404 } -405 -406 # Save state as an alist of alists: -407 # ((globals . ((a . (fn ...)) -408 # ...)) -409 # (sandbox . ...)) -410 fn store-state data-disk: (addr disk), sandbox: (addr sandbox), globals: (addr global-table) { -411 compare data-disk, 0/no-disk -412 { -413 break-if-!= -414 return -415 } -416 var stream-storage: (stream byte 0x1000) # space enough for 8/sectors -417 var stream/edi: (addr stream byte) <- address stream-storage -418 write stream, "(\n" -419 write-globals stream, globals -420 write-sandbox stream, sandbox -421 write stream, ")\n" -422 store-sectors data-disk, 0/lba, 8/sectors, stream -423 } + 1 # The top-level data structure for the Mu shell. + 2 # + 3 # vim:textwidth& + 4 # It would be nice for tests to use a narrower screen than the standard 0x80 of + 5 # 1024 pixels with 8px-wide graphemes. But it complicates rendering logic to + 6 # make width configurable, so we just use longer lines than usual. + 7 + 8 type environment { + 9 globals: global-table + 10 sandbox: sandbox + 11 # some state for a modal dialog for navigating between globals + 12 partial-global-name: (handle gap-buffer) + 13 go-modal-error: (handle array byte) + 14 # + 15 cursor-in-globals?: boolean + 16 cursor-in-go-modal?: boolean + 17 } + 18 + 19 # Here's a sample usage session and what it will look like on the screen. + 20 fn test-environment { + 21 var env-storage: environment + 22 var env/esi: (addr environment) <- address env-storage + 23 initialize-environment env, 8/fake-screen-width, 3/fake-screen-height + 24 # setup: screen + 25 var screen-on-stack: screen + 26 var screen/edi: (addr screen) <- address screen-on-stack + 27 initialize-screen screen, 0x80/width=72, 0x10/height, 0/no-pixel-graphics + 28 # type some code into sandbox + 29 type-in env, screen, "(+ 3 4)" # we don't have any global definitions here, so no macros + 30 # run code in sandbox + 31 edit-environment env, 0x13/ctrl-s, 0/no-disk + 32 render-environment screen, env + 33 # | global definitions | sandbox + 34 # top row blank for now + 35 check-screen-row screen, 0/y, " ", "F - test-environment/0" + 36 check-screen-row screen, 1/y, " screen: ", "F - test-environment/1" + 37 check-background-color-in-screen-row screen, 0/bg, 2/y, " ........ ", "F - test-environment/2" + 38 check-background-color-in-screen-row screen, 0/bg, 3/y, " ........ ", "F - test-environment/3" + 39 check-background-color-in-screen-row screen, 0/bg, 4/y, " ........ ", "F - test-environment/4" + 40 check-screen-row screen, 5/y, " ", "F - test-environment/5" + 41 check-screen-row screen, 6/y, " keyboard: ", "F - test-environment/6" + 42 check-background-color-in-screen-row screen, 0/bg, 6/y, " ................ ", "F - test-environment/6-2" + 43 check-screen-row screen, 7/y, " ", "F - test-environment/7" + 44 check-screen-row screen, 8/y, " (+ 3 4) ", "F - test-environment/8" + 45 check-screen-row screen, 9/y, " ... trace depth: 4 ", "F - test-environment/9" + 46 check-screen-row screen, 0xa/y, " => 7 ", "F - test-environment/10" + 47 check-screen-row screen, 0xb/y, " ", "F - test-environment/11" + 48 check-screen-row screen, 0xc/y, " ", "F - test-environment/12" + 49 check-screen-row screen, 0xd/y, " ", "F - test-environment/13" + 50 check-screen-row screen, 0xe/y, " ", "F - test-environment/14" + 51 # bottom row is for a wordstar-style menu + 52 check-screen-row screen, 0xf/y, " ^r run main ^s run sandbox ^g go to ^m to trace ^a << ^b <word ^f word> ^e >> ", "F - test-environment/15" + 53 } + 54 + 55 fn test-definition-in-environment { + 56 var env-storage: environment + 57 var env/esi: (addr environment) <- address env-storage + 58 initialize-environment env, 8/fake-screen-width, 3/fake-screen-height + 59 # setup: screen + 60 var screen-on-stack: screen + 61 var screen/edi: (addr screen) <- address screen-on-stack + 62 initialize-screen screen, 0x80/width=72, 0x10/height, 0/no-pixel-graphics + 63 # define a global on the right (sandbox) side + 64 type-in env, screen, "(define f 42)" + 65 edit-environment env, 0x13/ctrl-s, 0/no-disk + 66 render-environment screen, env + 67 # | global definitions | sandbox + 68 check-screen-row screen, 0/y, " ", "F - test-definition-in-environment/0" + 69 # global definition is now on the left side + 70 check-screen-row screen, 1/y, " (define f 42) screen: ", "F - test-definition-in-environment/1" + 71 check-background-color-in-screen-row screen, 0/bg, 2/y, " ........ ", "F - test-environment/2" + 72 check-background-color-in-screen-row screen, 0/bg, 3/y, " ........ ", "F - test-environment/3" + 73 check-background-color-in-screen-row screen, 0/bg, 4/y, " ........ ", "F - test-environment/4" + 74 check-screen-row screen, 5/y, " ", "F - test-definition-in-environment/4" + 75 check-screen-row screen, 6/y, " keyboard: ", "F - test-definition-in-environment/5" + 76 check-background-color-in-screen-row screen, 0/bg, 6/y, " ................ ", "F - test-definition-in-environment/5-2" + 77 check-screen-row screen, 7/y, " ", "F - test-definition-in-environment/6" + 78 check-screen-row screen, 8/y, " ", "F - test-definition-in-environment/7" + 79 # you can still see the trace on the right for what you just added to the left + 80 check-screen-row screen, 9/y, " ... trace depth: 4 ", "F - test-definition-in-environment/8" + 81 } + 82 + 83 # helper for testing + 84 fn type-in self: (addr environment), screen: (addr screen), keys: (addr array byte) { + 85 # clear the buffer + 86 edit-environment self, 0x15/ctrl-u, 0/no-disk + 87 render-environment screen, self + 88 # type in all the keys + 89 var input-stream-storage: (stream byte 0x40/capacity) + 90 var input-stream/ecx: (addr stream byte) <- address input-stream-storage + 91 write input-stream, keys + 92 { + 93 var done?/eax: boolean <- stream-empty? input-stream + 94 compare done?, 0/false + 95 break-if-!= + 96 var key/eax: grapheme <- read-grapheme input-stream + 97 edit-environment self, key, 0/no-disk + 98 render-environment screen, self + 99 loop + 100 } + 101 } + 102 + 103 fn initialize-environment _self: (addr environment), fake-screen-width: int, fake-screen-height: int { + 104 var self/esi: (addr environment) <- copy _self + 105 var globals/eax: (addr global-table) <- get self, globals + 106 initialize-globals globals + 107 var sandbox/eax: (addr sandbox) <- get self, sandbox + 108 initialize-sandbox sandbox, fake-screen-width, fake-screen-height + 109 var partial-global-name-ah/eax: (addr handle gap-buffer) <- get self, partial-global-name + 110 allocate partial-global-name-ah + 111 var partial-global-name/eax: (addr gap-buffer) <- lookup *partial-global-name-ah + 112 initialize-gap-buffer partial-global-name, 0x40/global-name-capacity + 113 } + 114 + 115 fn render-environment screen: (addr screen), _self: (addr environment) { + 116 # globals layout: 1 char padding, 41 code, 1 padding, 41 code, 1 padding = 85 + 117 # sandbox layout: 1 padding, 41 code, 1 padding = 43 + 118 # total = 128 chars + 119 var self/esi: (addr environment) <- copy _self + 120 var cursor-in-globals-a/eax: (addr boolean) <- get self, cursor-in-globals? + 121 var cursor-in-globals?/eax: boolean <- copy *cursor-in-globals-a + 122 var globals/ecx: (addr global-table) <- get self, globals + 123 render-globals screen, globals, cursor-in-globals? + 124 var sandbox/edx: (addr sandbox) <- get self, sandbox + 125 var cursor-in-sandbox?/ebx: boolean <- copy 1/true + 126 cursor-in-sandbox? <- subtract cursor-in-globals? + 127 render-sandbox screen, sandbox, 0x55/sandbox-left-margin, 0/sandbox-top-margin, 0x80/screen-width, 0x2f/screen-height-without-menu, cursor-in-sandbox? + 128 # modal if necessary + 129 { + 130 var cursor-in-go-modal-a/eax: (addr boolean) <- get self, cursor-in-go-modal? + 131 compare *cursor-in-go-modal-a, 0/false + 132 break-if-= + 133 render-go-modal screen, self + 134 render-go-modal-menu screen, self + 135 return + 136 } + 137 # render menu + 138 { + 139 var cursor-in-globals?/eax: (addr boolean) <- get self, cursor-in-globals? + 140 compare *cursor-in-globals?, 0/false + 141 break-if-= + 142 render-globals-menu screen, globals + 143 return + 144 } + 145 render-sandbox-menu screen, sandbox + 146 } + 147 + 148 fn edit-environment _self: (addr environment), key: grapheme, data-disk: (addr disk) { + 149 var self/esi: (addr environment) <- copy _self + 150 var globals/edi: (addr global-table) <- get self, globals + 151 var sandbox/ecx: (addr sandbox) <- get self, sandbox + 152 # ctrl-r + 153 # Assumption: 'real-screen' and 'real-keyboard' are 0 + 154 { + 155 compare key, 0x12/ctrl-r + 156 break-if-!= + 157 var tmp/eax: (addr handle cell) <- copy 0 + 158 var nil: (handle cell) + 159 tmp <- address nil + 160 allocate-pair tmp + 161 # (main real-screen real-keyboard) + 162 var real-keyboard: (handle cell) + 163 tmp <- address real-keyboard + 164 allocate-keyboard tmp + 165 # args = cons(real-keyboard, nil) + 166 var args: (handle cell) + 167 tmp <- address args + 168 new-pair tmp, real-keyboard, nil + 169 # + 170 var real-screen: (handle cell) + 171 tmp <- address real-screen + 172 allocate-screen tmp + 173 # args = cons(real-screen, args) + 174 tmp <- address args + 175 new-pair tmp, real-screen, *tmp + 176 # + 177 var main: (handle cell) + 178 tmp <- address main + 179 new-symbol tmp, "main" + 180 # args = cons(main, args) + 181 tmp <- address args + 182 new-pair tmp, main, *tmp + 183 # clear real screen + 184 clear-screen 0/screen + 185 set-cursor-position 0/screen, 0, 0 + 186 # run + 187 var out: (handle cell) + 188 var out-ah/ecx: (addr handle cell) <- address out + 189 var trace-storage: trace + 190 var trace/ebx: (addr trace) <- address trace-storage + 191 initialize-trace trace, 1/only-errors, 0x10/capacity, 0/visible + 192 evaluate tmp, out-ah, nil, globals, trace, 0/no-fake-screen, 0/no-fake-keyboard, 0/definitions-created, 0/call-number + 193 # wait for a keypress + 194 { + 195 var tmp/eax: byte <- read-key 0/keyboard + 196 compare tmp, 0 + 197 loop-if-= + 198 } + 199 # + 200 return + 201 } + 202 # ctrl-s: send multiple places + 203 { + 204 compare key, 0x13/ctrl-s + 205 break-if-!= + 206 { + 207 # cursor in go modal? do nothing + 208 var cursor-in-go-modal-a/eax: (addr boolean) <- get self, cursor-in-go-modal? + 209 compare *cursor-in-go-modal-a, 0/false + 210 break-if-!= + 211 { + 212 # cursor in globals? update current definition + 213 var cursor-in-globals-a/edx: (addr boolean) <- get self, cursor-in-globals? + 214 compare *cursor-in-globals-a, 0/false + 215 break-if-= + 216 edit-globals globals, key + 217 } + 218 # update sandbox whether the cursor is in globals or sandbox + 219 edit-sandbox sandbox, key, globals, data-disk + 220 } + 221 return + 222 } + 223 # dispatch to go modal if necessary + 224 { + 225 var cursor-in-go-modal-a/eax: (addr boolean) <- get self, cursor-in-go-modal? + 226 compare *cursor-in-go-modal-a, 0/false + 227 break-if-= + 228 # nested events for modal dialog + 229 # ignore spaces + 230 { + 231 compare key, 0x20/space + 232 break-if-!= + 233 return + 234 } + 235 # esc = exit modal dialog + 236 { + 237 compare key, 0x1b/escape + 238 break-if-!= + 239 var cursor-in-go-modal-a/eax: (addr boolean) <- get self, cursor-in-go-modal? + 240 copy-to *cursor-in-go-modal-a, 0/false + 241 var go-modal-error-ah/eax: (addr handle array byte) <- get self, go-modal-error + 242 clear-object go-modal-error-ah + 243 return + 244 } + 245 # enter = switch to global name and exit modal dialog + 246 { + 247 compare key, 0xa/newline + 248 break-if-!= + 249 # if no global name typed in, switch to sandbox + 250 var partial-global-name-ah/eax: (addr handle gap-buffer) <- get self, partial-global-name + 251 var partial-global-name/eax: (addr gap-buffer) <- lookup *partial-global-name-ah + 252 { + 253 var empty?/eax: boolean <- gap-buffer-empty? partial-global-name + 254 compare empty?, 0/false + 255 break-if-= + 256 var cursor-in-globals-a/eax: (addr boolean) <- get self, cursor-in-globals? + 257 copy-to *cursor-in-globals-a, 0/false + 258 # reset error state + 259 var go-modal-error-ah/eax: (addr handle array byte) <- get self, go-modal-error + 260 clear-object go-modal-error-ah + 261 # done with go modal + 262 var cursor-in-go-modal-a/eax: (addr boolean) <- get self, cursor-in-go-modal? + 263 copy-to *cursor-in-go-modal-a, 0/false + 264 return + 265 } + 266 # turn global name into a stream + 267 var name-storage: (stream byte 0x40) + 268 var name/ecx: (addr stream byte) <- address name-storage + 269 emit-gap-buffer partial-global-name, name + 270 # compute global index + 271 var index/ecx: int <- find-symbol-in-globals globals, name + 272 # if global not found, set error and return + 273 { + 274 compare index, 0 + 275 break-if->= + 276 var go-modal-error-ah/eax: (addr handle array byte) <- get self, go-modal-error + 277 copy-array-object "no such global", go-modal-error-ah + 278 return + 279 } + 280 # otherwise clear modal state + 281 clear-gap-buffer partial-global-name + 282 var go-modal-error-ah/eax: (addr handle array byte) <- get self, go-modal-error + 283 clear-object go-modal-error-ah + 284 var cursor-in-go-modal-a/eax: (addr boolean) <- get self, cursor-in-go-modal? + 285 copy-to *cursor-in-go-modal-a, 0/false + 286 # switch focus to global at index + 287 var globals-cursor-index/eax: (addr int) <- get globals, cursor-index + 288 copy-to *globals-cursor-index, index + 289 var cursor-in-globals-a/ecx: (addr boolean) <- get self, cursor-in-globals? + 290 copy-to *cursor-in-globals-a, 1/true + 291 return + 292 } + 293 # ctrl-m = create given global name and exit modal dialog + 294 { + 295 compare key, 0xd/ctrl-m + 296 break-if-!= + 297 # if no global name typed in, set error and return + 298 var partial-global-name-ah/eax: (addr handle gap-buffer) <- get self, partial-global-name + 299 var partial-global-name/eax: (addr gap-buffer) <- lookup *partial-global-name-ah + 300 { + 301 var empty?/eax: boolean <- gap-buffer-empty? partial-global-name + 302 compare empty?, 0/false + 303 break-if-= + 304 var go-modal-error-ah/eax: (addr handle array byte) <- get self, go-modal-error + 305 copy-array-object "create what?", go-modal-error-ah + 306 return + 307 } + 308 # turn global name into a stream + 309 var name-storage: (stream byte 0x40) + 310 var name/edx: (addr stream byte) <- address name-storage + 311 emit-gap-buffer partial-global-name, name + 312 # compute global index + 313 var index/ecx: int <- find-symbol-in-globals globals, name + 314 # if global found, set error and return + 315 { + 316 compare index, 0 + 317 break-if-< + 318 var go-modal-error-ah/eax: (addr handle array byte) <- get self, go-modal-error + 319 copy-array-object "already exists", go-modal-error-ah + 320 return + 321 } + 322 # otherwise clear modal state + 323 clear-gap-buffer partial-global-name + 324 var go-modal-error-ah/eax: (addr handle array byte) <- get self, go-modal-error + 325 clear-object go-modal-error-ah + 326 var cursor-in-go-modal-a/eax: (addr boolean) <- get self, cursor-in-go-modal? + 327 copy-to *cursor-in-go-modal-a, 0/false + 328 # create new global + 329 create-empty-global globals, name, 0x2000/default-gap-buffer-size=8KB + 330 var globals-final-index/eax: (addr int) <- get globals, final-index + 331 var new-index/ecx: int <- copy *globals-final-index + 332 var globals-cursor-index/eax: (addr int) <- get globals, cursor-index + 333 copy-to *globals-cursor-index, new-index + 334 var cursor-in-globals-a/ecx: (addr boolean) <- get self, cursor-in-globals? + 335 copy-to *cursor-in-globals-a, 1/true + 336 return + 337 } + 338 # otherwise process like a regular gap-buffer + 339 var partial-global-name-ah/eax: (addr handle gap-buffer) <- get self, partial-global-name + 340 var partial-global-name/eax: (addr gap-buffer) <- lookup *partial-global-name-ah + 341 edit-gap-buffer partial-global-name, key + 342 return + 343 } + 344 # ctrl-g: go to a global (or the repl) + 345 { + 346 compare key, 7/ctrl-g + 347 break-if-!= + 348 # look for a word to prepopulate the modal + 349 var current-word-storage: (stream byte 0x40) + 350 var current-word/edi: (addr stream byte) <- address current-word-storage + 351 word-at-cursor self, current-word + 352 var partial-global-name-ah/eax: (addr handle gap-buffer) <- get self, partial-global-name + 353 var partial-global-name/eax: (addr gap-buffer) <- lookup *partial-global-name-ah + 354 clear-gap-buffer partial-global-name + 355 load-gap-buffer-from-stream partial-global-name, current-word + 356 # enable the modal + 357 var cursor-in-go-modal-a/eax: (addr boolean) <- get self, cursor-in-go-modal? + 358 copy-to *cursor-in-go-modal-a, 1/true + 359 return + 360 } + 361 # dispatch the key to either sandbox or globals + 362 { + 363 var cursor-in-globals-a/eax: (addr boolean) <- get self, cursor-in-globals? + 364 compare *cursor-in-globals-a, 0/false + 365 break-if-= + 366 edit-globals globals, key + 367 return + 368 } + 369 edit-sandbox sandbox, key, globals, data-disk + 370 } + 371 + 372 fn read-and-evaluate-and-save-gap-buffer-to-globals _in-ah: (addr handle gap-buffer), result-ah: (addr handle cell), globals: (addr global-table), definitions-created: (addr stream int), trace: (addr trace), inner-screen-var: (addr handle cell), inner-keyboard-var: (addr handle cell) { + 373 var in-ah/eax: (addr handle gap-buffer) <- copy _in-ah + 374 var in/eax: (addr gap-buffer) <- lookup *in-ah + 375 var read-result-h: (handle cell) + 376 var read-result-ah/esi: (addr handle cell) <- address read-result-h + 377 read-cell in, read-result-ah, trace + 378 var error?/eax: boolean <- has-errors? trace + 379 { + 380 compare error?, 0/false + 381 break-if-= + 382 return + 383 } + 384 macroexpand read-result-ah, globals, trace + 385 var error?/eax: boolean <- has-errors? trace + 386 { + 387 compare error?, 0/false + 388 break-if-= + 389 return + 390 } + 391 var nil-h: (handle cell) + 392 var nil-ah/eax: (addr handle cell) <- address nil-h + 393 allocate-pair nil-ah + 394 #? set-cursor-position 0/screen, 0 0 + 395 #? turn-on-debug-print + 396 var call-number-storage: int + 397 var call-number/edi: (addr int) <- address call-number-storage + 398 debug-print "^", 4/fg, 0/bg + 399 evaluate read-result-ah, result-ah, *nil-ah, globals, trace, inner-screen-var, inner-keyboard-var, definitions-created, call-number + 400 debug-print "$", 4/fg, 0/bg + 401 var error?/eax: boolean <- has-errors? trace + 402 { + 403 compare error?, 0/false + 404 break-if-= + 405 return + 406 } + 407 # refresh various rendering caches + 408 mark-lines-dirty trace + 409 # If any definitions were created or modified in the process, link this gap + 410 # buffer to them. + 411 # TODO: detect and create UI for conflicts. + 412 stash-gap-buffer-to-globals globals, definitions-created, _in-ah + 413 } + 414 + 415 fn test-go-modal { + 416 var env-storage: environment + 417 var env/esi: (addr environment) <- address env-storage + 418 initialize-environment env, 8/fake-screen-width, 3/fake-screen-height + 419 # setup: screen + 420 var screen-on-stack: screen + 421 var screen/edi: (addr screen) <- address screen-on-stack + 422 initialize-screen screen, 0x80/width=72, 0x10/height, 0/no-pixel-graphics + 423 # hit ctrl-g + 424 edit-environment env, 7/ctrl-g, 0/no-disk + 425 render-environment screen, env + 426 # + 427 check-background-color-in-screen-row screen, 0xf/bg=modal, 0/y, " ", "F - test-go-modal/0" + 428 check-background-color-in-screen-row screen, 0xf/bg=modal, 1/y, " ", "F - test-go-modal/1" + 429 check-background-color-in-screen-row screen, 0xf/bg=modal, 2/y, " ", "F - test-go-modal/2" + 430 check-background-color-in-screen-row screen, 0xf/bg=modal, 3/y, " ", "F - test-go-modal/3" + 431 check-background-color-in-screen-row screen, 0xf/bg=modal, 4/y, " ", "F - test-go-modal/4" + 432 check-background-color-in-screen-row screen, 0xf/bg=modal, 5/y, " ", "F - test-go-modal/5" + 433 check-screen-row screen, 6/y, " go to global (or leave blank to go to REPL) ", "F - test-go-modal/6-text" + 434 check-background-color-in-screen-row screen, 0xf/bg=modal, 6/y, " ................................................................ ", "F - test-go-modal/6" + 435 check-background-color-in-screen-row screen, 0xf/bg=modal, 7/y, " ................................................................ ", "F - test-go-modal/7" + 436 # cursor is in the modal + 437 check-background-color-in-screen-row screen, 0/bg=cursor, 8/y, " | ", "F - test-go-modal/8-cursor" + 438 check-background-color-in-screen-row screen, 0xf/bg=modal, 8/y, " ............................................................... ", "F - test-go-modal/8" + 439 check-background-color-in-screen-row screen, 0xf/bg=modal, 9/y, " ", "F - test-go-modal/9" + 440 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xa/y, " ", "F - test-go-modal/10" + 441 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xb/y, " ", "F - test-go-modal/11" + 442 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xc/y, " ", "F - test-go-modal/12" + 443 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xd/y, " ", "F - test-go-modal/13" + 444 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xe/y, " ", "F - test-go-modal/14" + 445 # menu at bottom is correct in context + 446 check-screen-row screen, 0xf/y, " ^r run main enter go ^m create esc cancel ^a << ^b <word ^f word> ^e >> ", "F - test-go-modal/15-text" + 447 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xf/y, " ", "F - test-go-modal/15" + 448 } + 449 + 450 fn test-leave-go-modal { + 451 var env-storage: environment + 452 var env/esi: (addr environment) <- address env-storage + 453 initialize-environment env, 8/fake-screen-width, 3/fake-screen-height + 454 # setup: screen + 455 var screen-on-stack: screen + 456 var screen/edi: (addr screen) <- address screen-on-stack + 457 initialize-screen screen, 0x80/width=72, 0x10/height, 0/no-pixel-graphics + 458 # hit ctrl-g + 459 edit-environment env, 7/ctrl-g, 0/no-disk + 460 render-environment screen, env + 461 # cancel + 462 edit-environment env, 0x1b/escape, 0/no-disk + 463 render-environment screen, env + 464 # no modal + 465 check-background-color-in-screen-row screen, 0xf/bg=modal, 0/y, " ", "F - test-leave-go-modal/0" + 466 check-background-color-in-screen-row screen, 0xf/bg=modal, 1/y, " ", "F - test-leave-go-modal/1" + 467 check-background-color-in-screen-row screen, 0xf/bg=modal, 2/y, " ", "F - test-leave-go-modal/2" + 468 check-background-color-in-screen-row screen, 0xf/bg=modal, 3/y, " ", "F - test-leave-go-modal/3" + 469 check-background-color-in-screen-row screen, 0xf/bg=modal, 4/y, " ", "F - test-leave-go-modal/4" + 470 check-background-color-in-screen-row screen, 0xf/bg=modal, 5/y, " ", "F - test-leave-go-modal/5" + 471 check-background-color-in-screen-row screen, 0xf/bg=modal, 6/y, " ", "F - test-leave-go-modal/6" + 472 check-background-color-in-screen-row screen, 0xf/bg=modal, 7/y, " ", "F - test-leave-go-modal/7" + 473 check-background-color-in-screen-row screen, 0xf/bg=modal, 8/y, " ", "F - test-leave-go-modal/8" + 474 check-background-color-in-screen-row screen, 0xf/bg=modal, 9/y, " ", "F - test-leave-go-modal/9" + 475 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xa/y, " ", "F - test-leave-go-modal/10" + 476 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xb/y, " ", "F - test-leave-go-modal/11" + 477 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xc/y, " ", "F - test-leave-go-modal/12" + 478 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xd/y, " ", "F - test-leave-go-modal/13" + 479 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xe/y, " ", "F - test-leave-go-modal/14" + 480 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xf/y, " ", "F - test-leave-go-modal/15" + 481 } + 482 + 483 fn test-jump-to-global { + 484 var env-storage: environment + 485 var env/esi: (addr environment) <- address env-storage + 486 initialize-environment env, 8/fake-screen-width, 3/fake-screen-height + 487 # setup: screen + 488 var screen-on-stack: screen + 489 var screen/edi: (addr screen) <- address screen-on-stack + 490 initialize-screen screen, 0x80/width=72, 0x10/height, 0/no-pixel-graphics + 491 # define a global + 492 type-in env, screen, "(define f 42)" + 493 edit-environment env, 0x13/ctrl-s, 0/no-disk + 494 render-environment screen, env + 495 # hit ctrl-g + 496 edit-environment env, 7/ctrl-g, 0/no-disk + 497 render-environment screen, env + 498 # type global name + 499 type-in env, screen, "f" + 500 # submit + 501 edit-environment env, 0xa/newline, 0/no-disk + 502 render-environment screen, env + 503 # | global definitions | sandbox + 504 # cursor now in global definition + 505 check-screen-row screen, 1/y, " (define f 42) screen: ", "F - test-jump-to-global/1" + 506 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " | ", "F - test-jump-to-global/1-cursor" + 507 # no modal + 508 check-background-color-in-screen-row screen, 0xf/bg=modal, 0/y, " ", "F - test-jump-to-global/bg0" + 509 check-background-color-in-screen-row screen, 0xf/bg=modal, 1/y, " ", "F - test-jump-to-global/bg1" + 510 check-background-color-in-screen-row screen, 0xf/bg=modal, 2/y, " ", "F - test-jump-to-global/bg2" + 511 check-background-color-in-screen-row screen, 0xf/bg=modal, 3/y, " ", "F - test-jump-to-global/bg3" + 512 check-background-color-in-screen-row screen, 0xf/bg=modal, 4/y, " ", "F - test-jump-to-global/bg4" + 513 check-background-color-in-screen-row screen, 0xf/bg=modal, 5/y, " ", "F - test-jump-to-global/bg5" + 514 check-background-color-in-screen-row screen, 0xf/bg=modal, 6/y, " ", "F - test-jump-to-global/bg6" + 515 check-background-color-in-screen-row screen, 0xf/bg=modal, 7/y, " ", "F - test-jump-to-global/bg7" + 516 check-background-color-in-screen-row screen, 0xf/bg=modal, 8/y, " ", "F - test-jump-to-global/bg8" + 517 check-background-color-in-screen-row screen, 0xf/bg=modal, 9/y, " ", "F - test-jump-to-global/bg9" + 518 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xa/y, " ", "F - test-jump-to-global/bg10" + 519 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xb/y, " ", "F - test-jump-to-global/bg11" + 520 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xc/y, " ", "F - test-jump-to-global/bg12" + 521 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xd/y, " ", "F - test-jump-to-global/bg13" + 522 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xe/y, " ", "F - test-jump-to-global/bg14" + 523 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xf/y, " ", "F - test-jump-to-global/bg15" + 524 } + 525 + 526 fn test-go-modal-prepopulates-word-at-cursor { + 527 var env-storage: environment + 528 var env/esi: (addr environment) <- address env-storage + 529 initialize-environment env, 8/fake-screen-width, 3/fake-screen-height + 530 # setup: screen + 531 var screen-on-stack: screen + 532 var screen/edi: (addr screen) <- address screen-on-stack + 533 initialize-screen screen, 0x80/width=72, 0x10/height, 0/no-pixel-graphics + 534 # type a word at the cursor + 535 type-in env, screen, "fn1" + 536 # hit ctrl-g + 537 edit-environment env, 7/ctrl-g, 0/no-disk + 538 render-environment screen, env + 539 # modal prepopulates word at cursor + 540 check-background-color-in-screen-row screen, 0xf/bg=modal, 0/y, " ", "F - test-go-modal-prepopulates-word-at-cursor/0" + 541 check-background-color-in-screen-row screen, 0xf/bg=modal, 1/y, " ", "F - test-go-modal-prepopulates-word-at-cursor/1" + 542 check-background-color-in-screen-row screen, 0xf/bg=modal, 2/y, " ", "F - test-go-modal-prepopulates-word-at-cursor/2" + 543 check-background-color-in-screen-row screen, 0xf/bg=modal, 3/y, " ", "F - test-go-modal-prepopulates-word-at-cursor/3" + 544 check-background-color-in-screen-row screen, 0xf/bg=modal, 4/y, " ", "F - test-go-modal-prepopulates-word-at-cursor/4" + 545 check-background-color-in-screen-row screen, 0xf/bg=modal, 5/y, " ", "F - test-go-modal-prepopulates-word-at-cursor/5" + 546 check-screen-row screen, 6/y, " go to global (or leave blank to go to REPL) ", "F - test-go-modal-prepopulates-word-at-cursor/6-text" + 547 check-background-color-in-screen-row screen, 0xf/bg=modal, 6/y, " ................................................................ ", "F - test-go-modal-prepopulates-word-at-cursor/6" + 548 check-background-color-in-screen-row screen, 0xf/bg=modal, 7/y, " ................................................................ ", "F - test-go-modal-prepopulates-word-at-cursor/7" + 549 # word at cursor + 550 check-screen-row screen, 8/y, " fn1 ", "F - test-go-modal-prepopulates-word-at-cursor/8-text" + 551 # new cursor position + 552 check-background-color-in-screen-row screen, 0/bg=cursor, 8/y, " | ", "F - test-go-modal-prepopulates-word-at-cursor/8-cursor" + 553 check-background-color-in-screen-row screen, 0xf/bg=modal, 8/y, " ... ............................................................ ", "F - test-go-modal-prepopulates-word-at-cursor/8" + 554 check-background-color-in-screen-row screen, 0xf/bg=modal, 9/y, " ", "F - test-go-modal-prepopulates-word-at-cursor/9" + 555 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xa/y, " ", "F - test-go-modal-prepopulates-word-at-cursor/10" + 556 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xb/y, " ", "F - test-go-modal-prepopulates-word-at-cursor/11" + 557 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xc/y, " ", "F - test-go-modal-prepopulates-word-at-cursor/12" + 558 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xd/y, " ", "F - test-go-modal-prepopulates-word-at-cursor/13" + 559 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xe/y, " ", "F - test-go-modal-prepopulates-word-at-cursor/14" + 560 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xf/y, " ", "F - test-go-modal-prepopulates-word-at-cursor/15" + 561 # cancel + 562 edit-environment env, 0x1b/escape, 0/no-disk + 563 render-environment screen, env + 564 # type one more space + 565 edit-environment env, 0x20/space, 0/no-disk + 566 render-environment screen, env + 567 # hit ctrl-g again + 568 edit-environment env, 7/ctrl-g, 0/no-disk + 569 render-environment screen, env + 570 # no word prepopulated since cursor is not on the word + 571 check-background-color-in-screen-row screen, 0xf/bg=modal, 0/y, " ", "F - test-go-modal-prepopulates-word-at-cursor/test2-0" + 572 check-background-color-in-screen-row screen, 0xf/bg=modal, 1/y, " ", "F - test-go-modal-prepopulates-word-at-cursor/test2-1" + 573 check-background-color-in-screen-row screen, 0xf/bg=modal, 2/y, " ", "F - test-go-modal-prepopulates-word-at-cursor/test2-2" + 574 check-background-color-in-screen-row screen, 0xf/bg=modal, 3/y, " ", "F - test-go-modal-prepopulates-word-at-cursor/test2-3" + 575 check-background-color-in-screen-row screen, 0xf/bg=modal, 4/y, " ", "F - test-go-modal-prepopulates-word-at-cursor/test2-4" + 576 check-background-color-in-screen-row screen, 0xf/bg=modal, 5/y, " ", "F - test-go-modal-prepopulates-word-at-cursor/test2-5" + 577 check-screen-row screen, 6/y, " go to global (or leave blank to go to REPL) ", "F - test-go-modal-prepopulates-word-at-cursor/test2-6-text" + 578 check-background-color-in-screen-row screen, 0xf/bg=modal, 6/y, " ................................................................ ", "F - test-go-modal-prepopulates-word-at-cursor/test2-6" + 579 check-background-color-in-screen-row screen, 0xf/bg=modal, 7/y, " ................................................................ ", "F - test-go-modal-prepopulates-word-at-cursor/test2-7" + 580 # no word at cursor + 581 check-screen-row screen, 8/y, " ", "F - test-go-modal-prepopulates-word-at-cursor/test2-8-text" + 582 # new cursor position + 583 check-background-color-in-screen-row screen, 0/bg=cursor, 8/y, " | ", "F - test-go-modal-prepopulates-word-at-cursor/test2-8-cursor" + 584 check-background-color-in-screen-row screen, 0xf/bg=modal, 8/y, " ............................................................... ", "F - test-go-modal-prepopulates-word-at-cursor/test2-8" + 585 check-background-color-in-screen-row screen, 0xf/bg=modal, 9/y, " ", "F - test-go-modal-prepopulates-word-at-cursor/test2-9" + 586 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xa/y, " ", "F - test-go-modal-prepopulates-word-at-cursor/test2-10" + 587 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xb/y, " ", "F - test-go-modal-prepopulates-word-at-cursor/test2-11" + 588 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xc/y, " ", "F - test-go-modal-prepopulates-word-at-cursor/test2-12" + 589 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xd/y, " ", "F - test-go-modal-prepopulates-word-at-cursor/test2-13" + 590 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xe/y, " ", "F - test-go-modal-prepopulates-word-at-cursor/test2-14" + 591 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xf/y, " ", "F - test-go-modal-prepopulates-word-at-cursor/test2-15" + 592 # cancel + 593 edit-environment env, 0x1b/escape, 0/no-disk + 594 render-environment screen, env + 595 # move cursor to the left until it's on the word again + 596 edit-environment env, 0x80/left-arrow, 0/no-disk + 597 render-environment screen, env + 598 edit-environment env, 0x80/left-arrow, 0/no-disk + 599 render-environment screen, env + 600 # hit ctrl-g again + 601 edit-environment env, 7/ctrl-g, 0/no-disk + 602 render-environment screen, env + 603 # word prepopulated like before + 604 check-background-color-in-screen-row screen, 0xf/bg=modal, 0/y, " ", "F - test-go-modal-prepopulates-word-at-cursor/test3-0" + 605 check-background-color-in-screen-row screen, 0xf/bg=modal, 1/y, " ", "F - test-go-modal-prepopulates-word-at-cursor/test3-1" + 606 check-background-color-in-screen-row screen, 0xf/bg=modal, 2/y, " ", "F - test-go-modal-prepopulates-word-at-cursor/test3-2" + 607 check-background-color-in-screen-row screen, 0xf/bg=modal, 3/y, " ", "F - test-go-modal-prepopulates-word-at-cursor/test3-3" + 608 check-background-color-in-screen-row screen, 0xf/bg=modal, 4/y, " ", "F - test-go-modal-prepopulates-word-at-cursor/test3-4" + 609 check-background-color-in-screen-row screen, 0xf/bg=modal, 5/y, " ", "F - test-go-modal-prepopulates-word-at-cursor/test3-5" + 610 check-screen-row screen, 6/y, " go to global (or leave blank to go to REPL) ", "F - test-go-modal-prepopulates-word-at-cursor/test3-6-text" + 611 check-background-color-in-screen-row screen, 0xf/bg=modal, 6/y, " ................................................................ ", "F - test-go-modal-prepopulates-word-at-cursor/test3-6" + 612 check-background-color-in-screen-row screen, 0xf/bg=modal, 7/y, " ................................................................ ", "F - test-go-modal-prepopulates-word-at-cursor/test3-7" + 613 # word at cursor + 614 check-screen-row screen, 8/y, " fn1 ", "F - test-go-modal-prepopulates-word-at-cursor/test3-8-text" + 615 # new cursor position + 616 check-background-color-in-screen-row screen, 0/bg=cursor, 8/y, " | ", "F - test-go-modal-prepopulates-word-at-cursor/test3-8-cursor" + 617 check-background-color-in-screen-row screen, 0xf/bg=modal, 8/y, " ... ............................................................ ", "F - test-go-modal-prepopulates-word-at-cursor/test3-8" + 618 check-background-color-in-screen-row screen, 0xf/bg=modal, 9/y, " ", "F - test-go-modal-prepopulates-word-at-cursor/test3-9" + 619 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xa/y, " ", "F - test-go-modal-prepopulates-word-at-cursor/test3-10" + 620 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xb/y, " ", "F - test-go-modal-prepopulates-word-at-cursor/test3-11" + 621 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xc/y, " ", "F - test-go-modal-prepopulates-word-at-cursor/test3-12" + 622 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xd/y, " ", "F - test-go-modal-prepopulates-word-at-cursor/test3-13" + 623 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xe/y, " ", "F - test-go-modal-prepopulates-word-at-cursor/test3-14" + 624 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xf/y, " ", "F - test-go-modal-prepopulates-word-at-cursor/test3-15" + 625 } + 626 + 627 fn test-jump-to-nonexistent-global { + 628 var env-storage: environment + 629 var env/esi: (addr environment) <- address env-storage + 630 initialize-environment env, 8/fake-screen-width, 3/fake-screen-height + 631 # setup: screen + 632 var screen-on-stack: screen + 633 var screen/edi: (addr screen) <- address screen-on-stack + 634 initialize-screen screen, 0x80/width=72, 0x10/height, 0/no-pixel-graphics + 635 # type in any (nonexistent) global name + 636 type-in env, screen, "f" + 637 # hit ctrl-g + 638 edit-environment env, 7/ctrl-g, 0/no-disk + 639 render-environment screen, env + 640 # submit + 641 edit-environment env, 0xa/newline, 0/no-disk + 642 render-environment screen, env + 643 # modal now shows an error + 644 # | global definitions | sandbox + 645 check-background-color-in-screen-row screen, 0xf/bg=modal, 0/y, " ", "F - test-jump-to-nonexistent-global/0" + 646 check-background-color-in-screen-row screen, 0xf/bg=modal, 1/y, " ", "F - test-jump-to-nonexistent-global/1" + 647 check-background-color-in-screen-row screen, 0xf/bg=modal, 2/y, " ", "F - test-jump-to-nonexistent-global/2" + 648 check-background-color-in-screen-row screen, 0xf/bg=modal, 3/y, " ", "F - test-jump-to-nonexistent-global/3" + 649 check-background-color-in-screen-row screen, 0xf/bg=modal, 4/y, " ", "F - test-jump-to-nonexistent-global/4" + 650 check-background-color-in-screen-row screen, 0xf/bg=modal, 5/y, " ", "F - test-jump-to-nonexistent-global/5" + 651 check-screen-row screen, 6/y, " go to global (or leave blank to go to REPL) ", "F - test-jump-to-nonexistent-global/6-text" + 652 check-background-color-in-screen-row screen, 0xf/bg=modal, 6/y, " ................................................................ ", "F - test-jump-to-nonexistent-global/6" + 653 check-screen-row-in-color screen, 4/fg=error, 7/y, " no such global ", "F - test-jump-to-nonexistent-global/7-text" + 654 check-background-color-in-screen-row screen, 0xf/bg=modal, 7/y, " ................................................................ ", "F - test-jump-to-nonexistent-global/7" + 655 check-screen-row screen, 8/y, " f ", "F - test-jump-to-nonexistent-global/8-text" + 656 check-background-color-in-screen-row screen, 0/bg=cursor, 8/y, " | ", "F - test-jump-to-nonexistent-global/8-cursor" + 657 check-background-color-in-screen-row screen, 0xf/bg=modal, 8/y, " . .............................................................. ", "F - test-jump-to-nonexistent-global/8" + 658 check-background-color-in-screen-row screen, 0xf/bg=modal, 9/y, " ", "F - test-jump-to-nonexistent-global/9" + 659 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xa/y, " ", "F - test-jump-to-nonexistent-global/10" + 660 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xb/y, " ", "F - test-jump-to-nonexistent-global/11" + 661 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xc/y, " ", "F - test-jump-to-nonexistent-global/12" + 662 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xd/y, " ", "F - test-jump-to-nonexistent-global/13" + 663 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xe/y, " ", "F - test-jump-to-nonexistent-global/14" + 664 # menu at bottom is correct in context + 665 check-screen-row screen, 0xf/y, " ^r run main enter go ^m create esc cancel ^a << ^b <word ^f word> ^e >> ", "F - test-jump-to-nonexistent-global/15-text" + 666 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xf/y, " ", "F - test-jump-to-nonexistent-global/15" + 667 # cancel + 668 edit-environment env, 0x1b/escape, 0/no-disk + 669 render-environment screen, env + 670 # hit ctrl-g again + 671 edit-environment env, 7/ctrl-g, 0/no-disk + 672 render-environment screen, env + 673 # word prepopulated like before, but no error + 674 check-background-color-in-screen-row screen, 0xf/bg=modal, 0/y, " ", "F - test-jump-to-nonexistent-global/test2-0" + 675 check-background-color-in-screen-row screen, 0xf/bg=modal, 1/y, " ", "F - test-jump-to-nonexistent-global/test2-1" + 676 check-background-color-in-screen-row screen, 0xf/bg=modal, 2/y, " ", "F - test-jump-to-nonexistent-global/test2-2" + 677 check-background-color-in-screen-row screen, 0xf/bg=modal, 3/y, " ", "F - test-jump-to-nonexistent-global/test2-3" + 678 check-background-color-in-screen-row screen, 0xf/bg=modal, 4/y, " ", "F - test-jump-to-nonexistent-global/test2-4" + 679 check-background-color-in-screen-row screen, 0xf/bg=modal, 5/y, " ", "F - test-jump-to-nonexistent-global/test2-5" + 680 check-screen-row screen, 6/y, " go to global (or leave blank to go to REPL) ", "F - test-jump-to-nonexistent-global/test2-6-text" + 681 check-background-color-in-screen-row screen, 0xf/bg=modal, 6/y, " ................................................................ ", "F - test-jump-to-nonexistent-global/test2-6" + 682 check-screen-row-in-color screen, 4/fg=error, 7/y, " ", "F - test-jump-to-nonexistent-global/test2-7-text" + 683 check-background-color-in-screen-row screen, 0xf/bg=modal, 7/y, " ................................................................ ", "F - test-jump-to-nonexistent-global/test2-7" + 684 # same word at cursor + 685 check-screen-row screen, 8/y, " f ", "F - test-jump-to-nonexistent-global/test2-8-text" + 686 # new cursor position + 687 check-background-color-in-screen-row screen, 0/bg=cursor, 8/y, " | ", "F - test-jump-to-nonexistent-global/test2-8-cursor" + 688 check-background-color-in-screen-row screen, 0xf/bg=modal, 8/y, " . .............................................................. ", "F - test-jump-to-nonexistent-global/test2-8" + 689 check-background-color-in-screen-row screen, 0xf/bg=modal, 9/y, " ", "F - test-jump-to-nonexistent-global/test2-9" + 690 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xa/y, " ", "F - test-jump-to-nonexistent-global/test2-10" + 691 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xb/y, " ", "F - test-jump-to-nonexistent-global/test2-11" + 692 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xc/y, " ", "F - test-jump-to-nonexistent-global/test2-12" + 693 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xd/y, " ", "F - test-jump-to-nonexistent-global/test2-13" + 694 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xe/y, " ", "F - test-jump-to-nonexistent-global/test2-14" + 695 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xf/y, " ", "F - test-jump-to-nonexistent-global/test2-15" + 696 } + 697 + 698 fn test-create-global { + 699 var env-storage: environment + 700 var env/esi: (addr environment) <- address env-storage + 701 initialize-environment env, 8/fake-screen-width, 3/fake-screen-height + 702 # setup: screen + 703 var screen-on-stack: screen + 704 var screen/edi: (addr screen) <- address screen-on-stack + 705 initialize-screen screen, 0x80/width=72, 0x10/height, 0/no-pixel-graphics + 706 # hit ctrl-g + 707 edit-environment env, 7/ctrl-g, 0/no-disk + 708 render-environment screen, env + 709 # type global name + 710 type-in env, screen, "fn1" + 711 # create + 712 edit-environment env, 0xd/ctrl-m, 0/no-disk + 713 render-environment screen, env + 714 # | global definitions | sandbox + 715 # cursor now on global side + 716 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " | ", "F - test-create-global/1-cursor" + 717 # no modal + 718 check-background-color-in-screen-row screen, 0xf/bg=modal, 0/y, " ", "F - test-create-global/bg0" + 719 check-background-color-in-screen-row screen, 0xf/bg=modal, 1/y, " ", "F - test-create-global/bg1" + 720 check-background-color-in-screen-row screen, 0xf/bg=modal, 2/y, " ", "F - test-create-global/bg2" + 721 check-background-color-in-screen-row screen, 0xf/bg=modal, 3/y, " ", "F - test-create-global/bg3" + 722 check-background-color-in-screen-row screen, 0xf/bg=modal, 4/y, " ", "F - test-create-global/bg4" + 723 check-background-color-in-screen-row screen, 0xf/bg=modal, 5/y, " ", "F - test-create-global/bg5" + 724 check-background-color-in-screen-row screen, 0xf/bg=modal, 6/y, " ", "F - test-create-global/bg6" + 725 check-background-color-in-screen-row screen, 0xf/bg=modal, 7/y, " ", "F - test-create-global/bg7" + 726 check-background-color-in-screen-row screen, 0xf/bg=modal, 8/y, " ", "F - test-create-global/bg8" + 727 check-background-color-in-screen-row screen, 0xf/bg=modal, 9/y, " ", "F - test-create-global/bg9" + 728 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xa/y, " ", "F - test-create-global/bg10" + 729 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xb/y, " ", "F - test-create-global/bg11" + 730 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xc/y, " ", "F - test-create-global/bg12" + 731 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xd/y, " ", "F - test-create-global/bg13" + 732 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xe/y, " ", "F - test-create-global/bg14" + 733 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xf/y, " ", "F - test-create-global/bg15" + 734 } + 735 + 736 fn test-create-nonexistent-global { + 737 var env-storage: environment + 738 var env/esi: (addr environment) <- address env-storage + 739 initialize-environment env, 8/fake-screen-width, 3/fake-screen-height + 740 # setup: screen + 741 var screen-on-stack: screen + 742 var screen/edi: (addr screen) <- address screen-on-stack + 743 initialize-screen screen, 0x80/width=72, 0x10/height, 0/no-pixel-graphics + 744 # define a global + 745 type-in env, screen, "(define f 42)" + 746 edit-environment env, 0x13/ctrl-s, 0/no-disk + 747 render-environment screen, env + 748 # type in its name + 749 type-in env, screen, "f" + 750 # hit ctrl-g + 751 edit-environment env, 7/ctrl-g, 0/no-disk + 752 render-environment screen, env + 753 # submit + 754 edit-environment env, 0xd/ctrl-m, 0/no-disk + 755 render-environment screen, env + 756 # modal now shows an error + 757 # | global definitions | sandbox + 758 check-background-color-in-screen-row screen, 0xf/bg=modal, 0/y, " ", "F - test-create-nonexistent-global/0" + 759 check-background-color-in-screen-row screen, 0xf/bg=modal, 1/y, " ", "F - test-create-nonexistent-global/1" + 760 check-background-color-in-screen-row screen, 0xf/bg=modal, 2/y, " ", "F - test-create-nonexistent-global/2" + 761 check-background-color-in-screen-row screen, 0xf/bg=modal, 3/y, " ", "F - test-create-nonexistent-global/3" + 762 check-background-color-in-screen-row screen, 0xf/bg=modal, 4/y, " ", "F - test-create-nonexistent-global/4" + 763 check-background-color-in-screen-row screen, 0xf/bg=modal, 5/y, " ", "F - test-create-nonexistent-global/5" + 764 check-screen-row screen, 6/y, " go to global (or leave blank to go to REPL) ", "F - test-create-nonexistent-global/6-text" + 765 check-background-color-in-screen-row screen, 0xf/bg=modal, 6/y, " ................................................................ ", "F - test-create-nonexistent-global/6" + 766 check-screen-row-in-color screen, 4/fg=error, 7/y, " already exists ", "F - test-create-nonexistent-global/7-text" + 767 check-background-color-in-screen-row screen, 0xf/bg=modal, 7/y, " ................................................................ ", "F - test-create-nonexistent-global/7" + 768 check-screen-row-in-color screen, 0/fg, 8/y, " f ", "F - test-create-nonexistent-global/8-text" + 769 check-background-color-in-screen-row screen, 0/bg=cursor, 8/y, " | ", "F - test-create-nonexistent-global/8-cursor" + 770 check-background-color-in-screen-row screen, 0xf/bg=modal, 8/y, " . .............................................................. ", "F - test-create-nonexistent-global/8" + 771 check-background-color-in-screen-row screen, 0xf/bg=modal, 9/y, " ", "F - test-create-nonexistent-global/9" + 772 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xa/y, " ", "F - test-create-nonexistent-global/10" + 773 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xb/y, " ", "F - test-create-nonexistent-global/11" + 774 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xc/y, " ", "F - test-create-nonexistent-global/12" + 775 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xd/y, " ", "F - test-create-nonexistent-global/13" + 776 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xe/y, " ", "F - test-create-nonexistent-global/14" + 777 # menu at bottom is correct in context + 778 check-screen-row screen, 0xf/y, " ^r run main enter go ^m create esc cancel ^a << ^b <word ^f word> ^e >> ", "F - test-create-nonexistent-global/15-text" + 779 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xf/y, " ", "F - test-create-nonexistent-global/15" + 780 # cancel + 781 edit-environment env, 0x1b/escape, 0/no-disk + 782 render-environment screen, env + 783 # hit ctrl-g again + 784 edit-environment env, 7/ctrl-g, 0/no-disk + 785 render-environment screen, env + 786 # word prepopulated like before, but no error + 787 check-background-color-in-screen-row screen, 0xf/bg=modal, 0/y, " ", "F - test-create-nonexistent-global/test2-0" + 788 check-background-color-in-screen-row screen, 0xf/bg=modal, 1/y, " ", "F - test-create-nonexistent-global/test2-1" + 789 check-background-color-in-screen-row screen, 0xf/bg=modal, 2/y, " ", "F - test-create-nonexistent-global/test2-2" + 790 check-background-color-in-screen-row screen, 0xf/bg=modal, 3/y, " ", "F - test-create-nonexistent-global/test2-3" + 791 check-background-color-in-screen-row screen, 0xf/bg=modal, 4/y, " ", "F - test-create-nonexistent-global/test2-4" + 792 check-background-color-in-screen-row screen, 0xf/bg=modal, 5/y, " ", "F - test-create-nonexistent-global/test2-5" + 793 check-screen-row screen, 6/y, " go to global (or leave blank to go to REPL) ", "F - test-create-nonexistent-global/test2-6-text" + 794 check-background-color-in-screen-row screen, 0xf/bg=modal, 6/y, " ................................................................ ", "F - test-create-nonexistent-global/test2-6" + 795 check-screen-row-in-color screen, 4/fg=error, 7/y, " ", "F - test-create-nonexistent-global/test2-7-text" + 796 check-background-color-in-screen-row screen, 0xf/bg=modal, 7/y, " ................................................................ ", "F - test-create-nonexistent-global/test2-7" + 797 # same word at cursor + 798 check-screen-row-in-color screen, 0/fg, 8/y, " f ", "F - test-create-nonexistent-global/test2-8-text" + 799 # new cursor position + 800 check-background-color-in-screen-row screen, 0/bg=cursor, 8/y, " | ", "F - test-create-nonexistent-global/test2-8-cursor" + 801 check-background-color-in-screen-row screen, 0xf/bg=modal, 8/y, " . .............................................................. ", "F - test-create-nonexistent-global/test2-8" + 802 check-background-color-in-screen-row screen, 0xf/bg=modal, 9/y, " ", "F - test-create-nonexistent-global/test2-9" + 803 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xa/y, " ", "F - test-create-nonexistent-global/test2-10" + 804 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xb/y, " ", "F - test-create-nonexistent-global/test2-11" + 805 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xc/y, " ", "F - test-create-nonexistent-global/test2-12" + 806 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xd/y, " ", "F - test-create-nonexistent-global/test2-13" + 807 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xe/y, " ", "F - test-create-nonexistent-global/test2-14" + 808 check-background-color-in-screen-row screen, 0xf/bg=modal, 0xf/y, " ", "F - test-create-nonexistent-global/test2-15" + 809 } + 810 + 811 fn render-go-modal screen: (addr screen), _self: (addr environment) { + 812 var self/esi: (addr environment) <- copy _self + 813 var width/eax: int <- copy 0 + 814 var height/ecx: int <- copy 0 + 815 width, height <- screen-size screen + 816 # xmin = max(0, width/2 - 0x20) + 817 var xmin: int + 818 var tmp/edx: int <- copy width + 819 tmp <- shift-right 1 + 820 tmp <- subtract 0x20/half-global-name-capacity + 821 { + 822 compare tmp, 0 + 823 break-if->= + 824 tmp <- copy 0 + 825 } + 826 copy-to xmin, tmp + 827 # xmax = min(width, width/2 + 0x20) + 828 var xmax: int + 829 tmp <- copy width + 830 tmp <- shift-right 1 + 831 tmp <- add 0x20/half-global-name-capacity + 832 { + 833 compare tmp, width + 834 break-if-<= + 835 tmp <- copy width + 836 } + 837 copy-to xmax, tmp + 838 # ymin = height/2 - 2 + 839 var ymin: int + 840 tmp <- copy height + 841 tmp <- shift-right 1 + 842 tmp <- subtract 2 + 843 copy-to ymin, tmp + 844 # ymax = height/2 + 1 + 845 var ymax: int + 846 tmp <- add 3 + 847 copy-to ymax, tmp + 848 # + 849 clear-rect screen, xmin, ymin, xmax, ymax, 0xf/bg=modal + 850 add-to xmin, 4 + 851 set-cursor-position screen, xmin, ymin + 852 draw-text-rightward-from-cursor screen, "go to global (or leave blank to go to REPL)", xmax, 8/fg=dark-grey, 0xf/bg=modal + 853 var partial-global-name-ah/eax: (addr handle gap-buffer) <- get self, partial-global-name + 854 var _partial-global-name/eax: (addr gap-buffer) <- lookup *partial-global-name-ah + 855 var partial-global-name/edx: (addr gap-buffer) <- copy _partial-global-name + 856 subtract-from xmin, 4 + 857 increment ymin + 858 { + 859 var go-modal-error-ah/eax: (addr handle array byte) <- get self, go-modal-error + 860 var go-modal-error/eax: (addr array byte) <- lookup *go-modal-error-ah + 861 compare go-modal-error, 0 + 862 break-if-= + 863 var dummy/eax: int <- draw-text-rightward screen, go-modal-error, xmin, xmax, ymin, 4/fg=error, 0xf/bg=modal + 864 } + 865 increment ymin + 866 var dummy/eax: int <- copy 0 + 867 var dummy2/ecx: int <- copy 0 + 868 dummy, dummy2 <- render-gap-buffer-wrapping-right-then-down screen, partial-global-name, xmin, ymin, xmax, ymax, 1/always-render-cursor, 0/fg=black, 0xf/bg=modal + 869 } + 870 + 871 fn render-go-modal-menu screen: (addr screen), _self: (addr environment) { + 872 var self/esi: (addr environment) <- copy _self + 873 var _width/eax: int <- copy 0 + 874 var height/ecx: int <- copy 0 + 875 _width, height <- screen-size screen + 876 var width/edx: int <- copy _width + 877 var y/ecx: int <- copy height + 878 y <- decrement + 879 var height/ebx: int <- copy y + 880 height <- increment + 881 clear-rect screen, 0/x, y, width, height, 0xc5/bg=blue-bg + 882 set-cursor-position screen, 0/x, y + 883 draw-text-rightward-from-cursor screen, " ^r ", width, 0/fg, 0x5c/bg=menu-highlight + 884 draw-text-rightward-from-cursor screen, " run main ", width, 7/fg, 0xc5/bg=blue-bg + 885 draw-text-rightward-from-cursor screen, " enter ", width, 0/fg, 0xc/bg=menu-really-highlight + 886 draw-text-rightward-from-cursor screen, " go ", width, 7/fg, 0xc5/bg=blue-bg + 887 draw-text-rightward-from-cursor screen, " ^m ", width, 0/fg, 0xc/bg=menu-really-highlight + 888 draw-text-rightward-from-cursor screen, " create ", width, 7/fg, 0xc5/bg=blue-bg + 889 draw-text-rightward-from-cursor screen, " esc ", width, 0/fg, 0x5c/bg=menu-highlight + 890 draw-text-rightward-from-cursor screen, " cancel ", width, 7/fg, 0xc5/bg=blue-bg + 891 draw-text-rightward-from-cursor screen, " ^a ", width, 0/fg, 0x5c/bg=menu-highlight + 892 draw-text-rightward-from-cursor screen, " << ", width, 7/fg, 0xc5/bg=blue-bg + 893 draw-text-rightward-from-cursor screen, " ^b ", width, 0/fg, 0x5c/bg=menu-highlight + 894 draw-text-rightward-from-cursor screen, " <word ", width, 7/fg, 0xc5/bg=blue-bg + 895 draw-text-rightward-from-cursor screen, " ^f ", width, 0/fg, 0x5c/bg=menu-highlight + 896 draw-text-rightward-from-cursor screen, " word> ", width, 7/fg, 0xc5/bg=blue-bg + 897 draw-text-rightward-from-cursor screen, " ^e ", width, 0/fg, 0x5c/bg=menu-highlight + 898 draw-text-rightward-from-cursor screen, " >> ", width, 7/fg, 0xc5/bg=blue-bg + 899 } + 900 + 901 fn word-at-cursor _self: (addr environment), out: (addr stream byte) { + 902 var self/esi: (addr environment) <- copy _self + 903 var cursor-in-go-modal-a/eax: (addr boolean) <- get self, cursor-in-go-modal? + 904 compare *cursor-in-go-modal-a, 0/false + 905 { + 906 break-if-= + 907 # cursor in go modal + 908 return + 909 } + 910 var cursor-in-globals-a/edx: (addr boolean) <- get self, cursor-in-globals? + 911 compare *cursor-in-globals-a, 0/false + 912 { + 913 break-if-= + 914 # cursor in some global editor + 915 var globals/eax: (addr global-table) <- get self, globals + 916 var cursor-index-addr/ecx: (addr int) <- get globals, cursor-index + 917 var cursor-index/ecx: int <- copy *cursor-index-addr + 918 var globals-data-ah/eax: (addr handle array global) <- get globals, data + 919 var globals-data/eax: (addr array global) <- lookup *globals-data-ah + 920 var cursor-offset/ecx: (offset global) <- compute-offset globals-data, cursor-index + 921 var curr-global/eax: (addr global) <- index globals-data, cursor-offset + 922 var curr-global-data-ah/eax: (addr handle gap-buffer) <- get curr-global, input + 923 var curr-global-data/eax: (addr gap-buffer) <- lookup *curr-global-data-ah + 924 word-at-gap curr-global-data, out + 925 return + 926 } + 927 # cursor in sandbox + 928 var sandbox/ecx: (addr sandbox) <- get self, sandbox + 929 var sandbox-data-ah/eax: (addr handle gap-buffer) <- get sandbox, data + 930 var sandbox-data/eax: (addr gap-buffer) <- lookup *sandbox-data-ah + 931 word-at-gap sandbox-data, out + 932 } + 933 + 934 # Gotcha: some saved state may not load. + 935 fn load-state _self: (addr environment), data-disk: (addr disk) { + 936 var self/esi: (addr environment) <- copy _self + 937 # data-disk -> stream + 938 var s-storage: (stream byte 0x2000) # space for 16/sectors + 939 var s/ebx: (addr stream byte) <- address s-storage + 940 draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "loading sectors from data disk", 3/fg, 0/bg + 941 move-cursor-to-left-margin-of-next-line 0/screen + 942 load-sectors data-disk, 0/lba, 0x10/sectors, s + 943 #? draw-stream-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, s, 7/fg, 0xc5/bg=blue-bg + 944 # stream -> gap-buffer (HACK: we temporarily cannibalize the sandbox's gap-buffer) + 945 draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "parsing", 3/fg, 0/bg + 946 move-cursor-to-left-margin-of-next-line 0/screen + 947 var sandbox/eax: (addr sandbox) <- get self, sandbox + 948 var data-ah/eax: (addr handle gap-buffer) <- get sandbox, data + 949 var data/eax: (addr gap-buffer) <- lookup *data-ah + 950 load-gap-buffer-from-stream data, s + 951 draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, " into gap buffer", 3/fg, 0/bg + 952 move-cursor-to-left-margin-of-next-line 0/screen + 953 clear-stream s + 954 # read: gap-buffer -> cell + 955 var initial-root-storage: (handle cell) + 956 var initial-root/ecx: (addr handle cell) <- address initial-root-storage + 957 var trace-storage: trace + 958 var trace/edi: (addr trace) <- address trace-storage + 959 initialize-trace trace, 1/only-errors, 0x10/capacity, 0/visible + 960 read-cell data, initial-root, trace + 961 draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, " into s-expressions", 3/fg, 0/bg + 962 move-cursor-to-left-margin-of-next-line 0/screen + 963 clear-gap-buffer data + 964 # + 965 { + 966 var initial-root-addr/eax: (addr cell) <- lookup *initial-root + 967 compare initial-root-addr, 0 + 968 break-if-!= + 969 return + 970 } + 971 # load globals from assoc(initial-root, 'globals) + 972 var globals-literal-storage: (handle cell) + 973 var globals-literal-ah/eax: (addr handle cell) <- address globals-literal-storage + 974 new-symbol globals-literal-ah, "globals" + 975 var globals-literal/eax: (addr cell) <- lookup *globals-literal-ah + 976 var globals-cell-storage: (handle cell) + 977 var globals-cell-ah/edx: (addr handle cell) <- address globals-cell-storage + 978 clear-trace trace + 979 lookup-symbol globals-literal, globals-cell-ah, *initial-root, 0/no-globals, trace, 0/no-screen, 0/no-keyboard + 980 var globals-cell/eax: (addr cell) <- lookup *globals-cell-ah + 981 { + 982 compare globals-cell, 0 + 983 break-if-= + 984 var globals/eax: (addr global-table) <- get self, globals + 985 load-globals globals-cell-ah, globals + 986 } + 987 # sandbox = assoc(initial-root, 'sandbox) + 988 draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "loading sandbox", 3/fg, 0/bg + 989 var sandbox-literal-storage: (handle cell) + 990 var sandbox-literal-ah/eax: (addr handle cell) <- address sandbox-literal-storage + 991 new-symbol sandbox-literal-ah, "sandbox" + 992 var sandbox-literal/eax: (addr cell) <- lookup *sandbox-literal-ah + 993 var sandbox-cell-storage: (handle cell) + 994 var sandbox-cell-ah/edx: (addr handle cell) <- address sandbox-cell-storage + 995 clear-trace trace + 996 lookup-symbol sandbox-literal, sandbox-cell-ah, *initial-root, 0/no-globals, trace, 0/no-screen, 0/no-keyboard + 997 var sandbox-cell/eax: (addr cell) <- lookup *sandbox-cell-ah + 998 { + 999 compare sandbox-cell, 0 +1000 break-if-= +1001 # print: cell -> stream +1002 clear-trace trace +1003 print-cell sandbox-cell-ah, s, trace +1004 # stream -> gap-buffer +1005 var sandbox/eax: (addr sandbox) <- get self, sandbox +1006 var data-ah/eax: (addr handle gap-buffer) <- get sandbox, data +1007 var data/eax: (addr gap-buffer) <- lookup *data-ah +1008 load-gap-buffer-from-stream data, s +1009 } +1010 } +1011 +1012 # Save state as an alist of alists: +1013 # ((globals . ((a . (fn ...)) +1014 # ...)) +1015 # (sandbox . ...)) +1016 fn store-state data-disk: (addr disk), sandbox: (addr sandbox), globals: (addr global-table) { +1017 compare data-disk, 0/no-disk +1018 { +1019 break-if-!= +1020 return +1021 } +1022 var stream-storage: (stream byte 0x2000) # space enough for 16/sectors +1023 var stream/edi: (addr stream byte) <- address stream-storage +1024 write stream, "(\n" +1025 write-globals stream, globals +1026 write-sandbox stream, sandbox +1027 write stream, ")\n" +1028 store-sectors data-disk, 0/lba, 0x10/sectors, stream +1029 }