diff options
author | Kartik K. Agaram <vc@akkartik.com> | 2021-06-09 09:16:52 -0700 |
---|---|---|
committer | Kartik K. Agaram <vc@akkartik.com> | 2021-06-09 09:16:52 -0700 |
commit | b7e8c2810a5008f68446ef62770ff2ec2c06a813 (patch) | |
tree | 6ffefd69cea31763fa2437634c538f84095afab0 /shell/global.mu | |
parent | 8cff44fef442bab0b6c75ac0ef1e3616c5149139 (diff) | |
download | mu-b7e8c2810a5008f68446ef62770ff2ec2c06a813.tar.gz |
snapshot: attempt at modifying a function name
It turns out there's another problem, and it predates the ability to create new definitions: ctrl-s triggers a call to `evaluate`, which inserts a new definition into globals. which has a null gap buffer. All this happens long before the new code in this commit, resulting in a null gap buffer by the time we get to word-at-cursor. Which in turn happens because we perform a raw `evaluate`, which doesn't update the gap buffer like `run` does (using `maybe-stash-gap-buffer-to-global`). And arguably `evaluate` shouldn't mess with the gap buffer. Gap buffers are a UI concern. The hardest version of this immediate scenario: It's unclear how to guarantee that every definition have a gap buffer, when two definitions may share one (closures sharing a lexical environment). New plan: - improve the logic for detecting definitions. Looking at the outermost layer isn't enough. And a single expression can create multiple definitions. - extract a helper to attach a single gap buffer to multiple definitions. - have the UI detect conflicts in gap buffers and prompt the user for a decision if a different gap buffer already exists for a definition.
Diffstat (limited to 'shell/global.mu')
-rw-r--r-- | shell/global.mu | 68 |
1 files changed, 57 insertions, 11 deletions
diff --git a/shell/global.mu b/shell/global.mu index 9b68e91e..a76e7148 100644 --- a/shell/global.mu +++ b/shell/global.mu @@ -285,10 +285,41 @@ fn refresh-definition _self: (addr global-table), _index: int { var nil-ah/eax: (addr handle cell) <- address nil-h allocate-pair nil-ah } - var curr-value-ah/eax: (addr handle cell) <- get curr-global, value + var curr-value-ah/edi: (addr handle cell) <- get curr-global, value debug-print "GL", 4/fg, 0/bg evaluate read-result-ah, curr-value-ah, nil-h, self, trace, 0/no-screen-cell, 0/no-keyboard-cell, 1/call-number debug-print "GZ", 4/fg, 0/bg + { + var error?/eax: boolean <- has-errors? trace + compare error?, 0/false + break-if-= + return + } + # update definition name if necessary + var curr-global-name-ah/ecx: (addr handle array byte) <- get curr-global, name + var _curr-global-name/eax: (addr array byte) <- lookup *curr-global-name-ah + var curr-global-name/ebx: (addr array byte) <- copy _curr-global-name + var read-result/eax: (addr cell) <- lookup *read-result-ah + { + var is-definition?/eax: boolean <- is-definition? read-result + compare is-definition?, 0/false + break-if-!= + return + } + # (no error checking since it's a definition and there were no errors) + var rest-ah/eax: (addr handle cell) <- get read-result, right + var rest/eax: (addr cell) <- lookup *rest-ah + var correct-definition-symbol-ah/eax: (addr handle cell) <- get rest, left + var correct-definition-symbol/eax: (addr cell) <- lookup *correct-definition-symbol-ah + var correct-definition-name-ah/eax: (addr handle stream byte) <- get correct-definition-symbol, text-data + var correct-definition-name/eax: (addr stream byte) <- lookup *correct-definition-name-ah + { + var still-matches?/eax: boolean <- stream-data-equal? correct-definition-name, curr-global-name + compare still-matches?, 0/false + break-if-= + return + } + stream-to-array correct-definition-name, curr-global-name-ah } fn assign-or-create-global _self: (addr global-table), name: (addr array byte), value: (handle cell), trace: (addr trace) { @@ -493,20 +524,14 @@ fn maybe-stash-gap-buffer-to-global _globals: (addr global-table), _expr-ah: (ad break-if-= return } - # if expr->left is neither "define" nor "set", return - var left-ah/eax: (addr handle cell) <- get expr, left - var _left/eax: (addr cell) <- lookup *left-ah - var left/ecx: (addr cell) <- copy _left + # if expr is not a definition, return { - var def?/eax: boolean <- symbol-equal? left, "define" - compare def?, 0/false - break-if-!= - var set?/eax: boolean <- symbol-equal? left, "set" - compare set?, 0/false + var is-definition?/eax: boolean <- is-definition? expr + compare is-definition?, 0/false break-if-!= return } - # locate the global for expr->right->left + # locate the global for definition->right->left var right-ah/eax: (addr handle cell) <- get expr, right var right/eax: (addr cell) <- lookup *right-ah var defined-symbol-ah/eax: (addr handle cell) <- get right, left @@ -542,6 +567,27 @@ fn maybe-stash-gap-buffer-to-global _globals: (addr global-table), _expr-ah: (ad initialize-gap-buffer gap-addr, capacity } +fn is-definition? _expr: (addr cell) -> _/eax: boolean { + var expr/eax: (addr cell) <- copy _expr + # if expr->left is neither "define" nor "set", return + var left-ah/eax: (addr handle cell) <- get expr, left + var _left/eax: (addr cell) <- lookup *left-ah + var left/ecx: (addr cell) <- copy _left + { + var def?/eax: boolean <- symbol-equal? left, "define" + compare def?, 0/false + break-if-= + return 1/true + } + { + var set?/eax: boolean <- symbol-equal? left, "set" + compare set?, 0/false + break-if-= + return 1/true + } + return 0/false +} + # Accepts an input s-expression, naively checks if it is a definition, and if # so saves the gap-buffer to the appropriate global. fn move-gap-buffer-to-global _globals: (addr global-table), _definition-ah: (addr handle cell), gap: (addr handle gap-buffer) { |