diff --git a/shell/gap-buffer.mu b/shell/gap-buffer.mu index 893dc176..7abe57c1 100644 --- a/shell/gap-buffer.mu +++ b/shell/gap-buffer.mu @@ -24,6 +24,15 @@ fn clear-gap-buffer _self: (addr gap-buffer) { clear-grapheme-stack right } +fn gap-buffer-capacity _gap: (addr gap-buffer) -> _/ecx: int { + var gap/esi: (addr gap-buffer) <- copy _gap + var left/eax: (addr grapheme-stack) <- get gap, left + var left-data-ah/eax: (addr handle array grapheme) <- get left, data + var left-data/eax: (addr array grapheme) <- lookup *left-data-ah + var result/eax: int <- length left-data + return result +} + # just for tests fn initialize-gap-buffer-with self: (addr gap-buffer), s: (addr array byte) { initialize-gap-buffer self, 0x10/capacity diff --git a/shell/global.mu b/shell/global.mu index eb70753d..575fd40b 100644 --- a/shell/global.mu +++ b/shell/global.mu @@ -1,5 +1,6 @@ type global { name: (handle array byte) + input: (handle gap-buffer) value: (handle cell) } @@ -1851,3 +1852,60 @@ fn apply-height _args-ah: (addr handle cell), out: (addr handle cell), trace: (a var result/xmm0: float <- convert height new-float out, result } + +# Accepts an input s-expression, naively checks if it is a definition, and if +# so saves the gap-buffer to the appropriate global, spinning up a new empty +# one to replace it with. +fn maybe-stash-gap-buffer-to-global _globals: (addr global-table), _definition-ah: (addr handle cell), gap: (addr handle gap-buffer) { + # if 'definition' is not a pair, return + var definition-ah/eax: (addr handle cell) <- copy _definition-ah + var _definition/eax: (addr cell) <- lookup *definition-ah + var definition/esi: (addr cell) <- copy _definition + var definition-type/eax: (addr int) <- get definition, type + compare *definition-type, 0/pair + { + break-if-= + return + } + # if definition->left is neither "def" nor "set", return + var left-ah/eax: (addr handle cell) <- get definition, left + var _left/eax: (addr cell) <- lookup *left-ah + var left/ecx: (addr cell) <- copy _left + { + var def?/eax: boolean <- symbol-equal? left, "def" + compare def?, 0/false + break-if-!= + var set?/eax: boolean <- symbol-equal? left, "set" + compare set?, 0/false + break-if-!= + return + } + # locate the global for definition->right->left + var right-ah/eax: (addr handle cell) <- get definition, right + var right/eax: (addr cell) <- lookup *right-ah + var defined-symbol-ah/eax: (addr handle cell) <- get right, left + var defined-symbol/eax: (addr cell) <- lookup *defined-symbol-ah + var defined-symbol-name-ah/eax: (addr handle stream byte) <- get defined-symbol, text-data + var defined-symbol-name/eax: (addr stream byte) <- lookup *defined-symbol-name-ah + var index/ecx: int <- find-symbol-in-globals _globals, defined-symbol-name + { + compare index, -1/not-found + break-if-!= + return + } + # stash 'gap' to it + var globals/eax: (addr global-table) <- copy _globals + var global-data-ah/eax: (addr handle array global) <- get globals, data + var global-data/eax: (addr array global) <- lookup *global-data-ah + var offset/ebx: (offset global) <- compute-offset global-data, index + var dest-global/eax: (addr global) <- index global-data, offset + var dest-ah/eax: (addr handle gap-buffer) <- get dest-global, input + copy-object gap, dest-ah + # initialize a new gap-buffer in 'gap' + var dest/eax: (addr gap-buffer) <- lookup *dest-ah + var capacity/ecx: int <- gap-buffer-capacity dest + var gap2/eax: (addr handle gap-buffer) <- copy gap + allocate gap2 + var gap-addr/eax: (addr gap-buffer) <- lookup *gap2 + initialize-gap-buffer gap-addr, capacity +} diff --git a/shell/sandbox.mu b/shell/sandbox.mu index 68ea1060..20d9f5fd 100644 --- a/shell/sandbox.mu +++ b/shell/sandbox.mu @@ -568,9 +568,7 @@ fn edit-sandbox _self: (addr sandbox), key: byte, globals: (addr global-table), # we'll need to revisit where serialization happens. store-state data-disk, self, globals # run sandbox - var data-ah/eax: (addr handle gap-buffer) <- get self, data - var _data/eax: (addr gap-buffer) <- lookup *data-ah - var data/ecx: (addr gap-buffer) <- copy _data + var data-ah/ecx: (addr handle gap-buffer) <- get self, data var value-ah/eax: (addr handle stream byte) <- get self, value var _value/eax: (addr stream byte) <- lookup *value-ah var value/edx: (addr stream byte) <- copy _value @@ -592,7 +590,7 @@ fn edit-sandbox _self: (addr sandbox), key: byte, globals: (addr global-table), break-if-= set-cursor-position real-screen, 0/x, 0/y # for any debug prints during evaluation } - run data, value, globals, trace, screen-cell, keyboard-cell + run data-ah, value, globals, trace, screen-cell, keyboard-cell return } # ctrl-m @@ -699,10 +697,12 @@ fn edit-sandbox _self: (addr sandbox), key: byte, globals: (addr global-table), } } -fn run in: (addr gap-buffer), out: (addr stream byte), globals: (addr global-table), trace: (addr trace), screen-cell: (addr handle cell), keyboard-cell: (addr handle cell) { - var read-result-storage: (handle cell) - var read-result/esi: (addr handle cell) <- address read-result-storage - read-cell in, read-result, trace +fn run _in-ah: (addr handle gap-buffer), out: (addr stream byte), globals: (addr global-table), trace: (addr trace), screen-cell: (addr handle cell), keyboard-cell: (addr handle cell) { + var in-ah/eax: (addr handle gap-buffer) <- copy _in-ah + var in/eax: (addr gap-buffer) <- lookup *in-ah + var read-result-h: (handle cell) + var read-result-ah/esi: (addr handle cell) <- address read-result-h + read-cell in, read-result-ah, trace var error?/eax: boolean <- has-errors? trace { compare error?, 0/false @@ -715,7 +715,7 @@ fn run in: (addr gap-buffer), out: (addr stream byte), globals: (addr global-tab var eval-result-storage: (handle cell) var eval-result/edi: (addr handle cell) <- address eval-result-storage debug-print "^", 4/fg, 0/bg - evaluate read-result, eval-result, *nil-ah, globals, trace, screen-cell, keyboard-cell, 1/call-number + evaluate read-result-ah, eval-result, *nil-ah, globals, trace, screen-cell, keyboard-cell, 1/call-number debug-print "$", 4/fg, 0/bg var error?/eax: boolean <- has-errors? trace { @@ -723,6 +723,10 @@ fn run in: (addr gap-buffer), out: (addr stream byte), globals: (addr global-tab break-if-= return } + # if there was no error and the read-result starts with "set" or "def", save + # the gap buffer in the modified global, then create a new one for the next + # command. + maybe-stash-gap-buffer-to-global globals, read-result-ah, _in-ah clear-stream out print-cell eval-result, out, trace mark-lines-dirty trace