diff options
Diffstat (limited to 'linux/tile/data.mu')
-rw-r--r-- | linux/tile/data.mu | 641 |
1 files changed, 641 insertions, 0 deletions
diff --git a/linux/tile/data.mu b/linux/tile/data.mu new file mode 100644 index 00000000..d711e7d7 --- /dev/null +++ b/linux/tile/data.mu @@ -0,0 +1,641 @@ +# widgets in the environment share the following pattern of updates: +# process-* functions read keys and update which object the cursor is at +# render-* functions print to screen and update which row/col each object's cursor is at + +type sandbox { + setup: (handle line) + data: (handle line) + # bookkeeping for process-* + cursor-call-path: (handle call-path-element) + expanded-words: (handle call-path) + partial-name-for-cursor-word: (handle word) # only when renaming word + partial-name-for-function: (handle word) # only when defining function + # bookkeeping for render-* + cursor-row: int + cursor-col: int + # + next: (handle sandbox) + prev: (handle sandbox) +} + +type function { + name: (handle array byte) + args: (handle word) # in reverse order + body: (handle line) + # bookkeeping for process-* + cursor-word: (handle word) + # bookkeeping for render-* + cursor-row: int + cursor-col: int + # todo: some sort of indication of spatial location + next: (handle function) +} + +type line { + name: (handle array byte) + data: (handle word) + result: (handle result) # might be cached + next: (handle line) + prev: (handle line) +} + +type word { + scalar-data: (handle gap-buffer) + next: (handle word) + prev: (handle word) +} + +# todo: turn this into a sum type +type value { + type: int + number-data: float # if type = 0 + text-data: (handle array byte) # if type = 1 + array-data: (handle array value) # if type = 2 + file-data: (handle buffered-file) # if type = 3 + filename: (handle array byte) # if type = 3 + screen-data: (handle screen) # if type = 4 +} + +type table { + data: (handle array bind) + next: (handle table) +} + +type bind { + key: (handle array byte) + value: (handle value) # I'd inline this but we sometimes want to return a specific value from a table +} + +# A call-path is a data structure that can unambiguously refer to any specific +# call arbitrarily deep inside the call hierarchy of a program. +type call-path { + data: (handle call-path-element) + next: (handle call-path) +} + +# A call-path element is a list of elements, each of which corresponds to some call. +type call-path-element { + word: (handle word) + next: (handle call-path-element) +} + +type result { + data: value-stack + error: (handle array byte) # single error message for now +} + +fn initialize-sandbox _sandbox: (addr sandbox) { + var sandbox/esi: (addr sandbox) <- copy _sandbox + var line-ah/eax: (addr handle line) <- get sandbox, data + allocate line-ah + var line/eax: (addr line) <- lookup *line-ah + initialize-line line + var word-ah/ecx: (addr handle word) <- get line, data + var cursor-call-path-ah/eax: (addr handle call-path-element) <- get sandbox, cursor-call-path + allocate cursor-call-path-ah + var cursor-call-path/eax: (addr call-path-element) <- lookup *cursor-call-path-ah + var dest/eax: (addr handle word) <- get cursor-call-path, word + copy-object word-ah, dest +} + +# initialize line with a single empty word +fn initialize-line _line: (addr line) { + var line/esi: (addr line) <- copy _line + var word-ah/eax: (addr handle word) <- get line, data + allocate word-ah + var word/eax: (addr word) <- lookup *word-ah + initialize-word word +} + +fn create-primitive-functions _self: (addr handle function) { + # x 2* = x 2 * + var self/esi: (addr handle function) <- copy _self + allocate self + var _f/eax: (addr function) <- lookup *self + var f/esi: (addr function) <- copy _f + var name-ah/eax: (addr handle array byte) <- get f, name + populate-text-with name-ah, "2*" + var args-ah/eax: (addr handle word) <- get f, args + allocate args-ah + var args/eax: (addr word) <- lookup *args-ah + initialize-word-with args, "x" + var body-ah/eax: (addr handle line) <- get f, body + allocate body-ah + var body/eax: (addr line) <- lookup *body-ah + initialize-line body + var curr-word-ah/ecx: (addr handle word) <- get body, data + parse-words "x 2 *", curr-word-ah + var cursor-word-ah/edx: (addr handle word) <- get f, cursor-word + copy-object curr-word-ah, cursor-word-ah + # x 1+ = x 1 + + var next/esi: (addr handle function) <- get f, next + allocate next + var _f/eax: (addr function) <- lookup *next + var f/esi: (addr function) <- copy _f + var name-ah/eax: (addr handle array byte) <- get f, name + populate-text-with name-ah, "1+" + var args-ah/eax: (addr handle word) <- get f, args + allocate args-ah + var args/eax: (addr word) <- lookup *args-ah + initialize-word-with args, "x" + var body-ah/eax: (addr handle line) <- get f, body + allocate body-ah + var body/eax: (addr line) <- lookup *body-ah + initialize-line body + curr-word-ah <- get body, data + parse-words "x 1 +", curr-word-ah + var cursor-word-ah/edx: (addr handle word) <- get f, cursor-word + copy-object curr-word-ah, cursor-word-ah + # x 2+ = x 1+ 1+ + var next/esi: (addr handle function) <- get f, next + allocate next + var _f/eax: (addr function) <- lookup *next + var f/esi: (addr function) <- copy _f + var name-ah/eax: (addr handle array byte) <- get f, name + populate-text-with name-ah, "2+" + var args-ah/eax: (addr handle word) <- get f, args + allocate args-ah + var args/eax: (addr word) <- lookup *args-ah + initialize-word-with args, "x" + var body-ah/eax: (addr handle line) <- get f, body + allocate body-ah + var body/eax: (addr line) <- lookup *body-ah + initialize-line body + curr-word-ah <- get body, data + parse-words "x 1+ 1+", curr-word-ah + var cursor-word-ah/edx: (addr handle word) <- get f, cursor-word + copy-object curr-word-ah, cursor-word-ah + # x square = x x * + var next/esi: (addr handle function) <- get f, next + allocate next + var _f/eax: (addr function) <- lookup *next + var f/esi: (addr function) <- copy _f + var name-ah/eax: (addr handle array byte) <- get f, name + populate-text-with name-ah, "square" + var args-ah/eax: (addr handle word) <- get f, args + allocate args-ah + var args/eax: (addr word) <- lookup *args-ah + initialize-word-with args, "x" + var body-ah/eax: (addr handle line) <- get f, body + allocate body-ah + var body/eax: (addr line) <- lookup *body-ah + initialize-line body + curr-word-ah <- get body, data + parse-words "x x *", curr-word-ah + var cursor-word-ah/edx: (addr handle word) <- get f, cursor-word + copy-object curr-word-ah, cursor-word-ah + # x 1- = x 1 - + var next/esi: (addr handle function) <- get f, next + allocate next + var _f/eax: (addr function) <- lookup *next + var f/esi: (addr function) <- copy _f + var name-ah/eax: (addr handle array byte) <- get f, name + populate-text-with name-ah, "1-" + var args-ah/eax: (addr handle word) <- get f, args + allocate args-ah + var args/eax: (addr word) <- lookup *args-ah + initialize-word-with args, "x" + var body-ah/eax: (addr handle line) <- get f, body + allocate body-ah + var body/eax: (addr line) <- lookup *body-ah + initialize-line body + curr-word-ah <- get body, data + parse-words "x 1 -", curr-word-ah + var cursor-word-ah/edx: (addr handle word) <- get f, cursor-word + copy-object curr-word-ah, cursor-word-ah + # x y sub = x y - + var next/esi: (addr handle function) <- get f, next + allocate next + var _f/eax: (addr function) <- lookup *next + var f/esi: (addr function) <- copy _f + var name-ah/eax: (addr handle array byte) <- get f, name + populate-text-with name-ah, "sub" + # critical lesson: args are stored in reverse order + var args-ah/eax: (addr handle word) <- get f, args + allocate args-ah + var args/eax: (addr word) <- lookup *args-ah + initialize-word-with args, "y" + var next-arg-ah/eax: (addr handle word) <- get args, next + allocate next-arg-ah + var next-arg/eax: (addr word) <- lookup *next-arg-ah + initialize-word-with next-arg, "x" + var body-ah/eax: (addr handle line) <- get f, body + allocate body-ah + var body/eax: (addr line) <- lookup *body-ah + initialize-line body + curr-word-ah <- get body, data + parse-words "x y -", curr-word-ah + var cursor-word-ah/edx: (addr handle word) <- get f, cursor-word + copy-object curr-word-ah, cursor-word-ah +} + +fn function-body functions: (addr handle function), _word: (addr handle word), out: (addr handle line) { + var function-name-storage: (handle array byte) + var function-name-ah/ecx: (addr handle array byte) <- address function-name-storage + var word-ah/esi: (addr handle word) <- copy _word + var word/eax: (addr word) <- lookup *word-ah + var gap-ah/eax: (addr handle gap-buffer) <- get word, scalar-data + var gap/eax: (addr gap-buffer) <- lookup *gap-ah + gap-buffer-to-string gap, function-name-ah + var _function-name/eax: (addr array byte) <- lookup *function-name-ah + var function-name/esi: (addr array byte) <- copy _function-name + var curr-ah/ecx: (addr handle function) <- copy functions + $function-body:loop: { + var _curr/eax: (addr function) <- lookup *curr-ah + var curr/edx: (addr function) <- copy _curr + compare curr, 0 + break-if-= + var curr-name-ah/eax: (addr handle array byte) <- get curr, name + var curr-name/eax: (addr array byte) <- lookup *curr-name-ah + var found?/eax: boolean <- string-equal? curr-name, function-name + compare found?, 0/false + { + break-if-= + var src/eax: (addr handle line) <- get curr, body + copy-object src, out + break $function-body:loop + } + curr-ah <- get curr, next + loop + } +} + +fn body-length functions: (addr handle function), function-name: (addr handle word) -> _/eax: int { + var body-storage: (handle line) + var body-ah/edi: (addr handle line) <- address body-storage + function-body functions, function-name, body-ah + var body/eax: (addr line) <- lookup *body-ah + var result/eax: int <- num-words-in-line body + return result +} + +fn num-words-in-line _in: (addr line) -> _/eax: int { + var in/esi: (addr line) <- copy _in + var curr-ah/ecx: (addr handle word) <- get in, data + var result/edi: int <- copy 0 + { + var curr/eax: (addr word) <- lookup *curr-ah + compare curr, 0 + break-if-= + curr-ah <- get curr, next + result <- increment + loop + } + return result +} + +fn populate-text-with _out: (addr handle array byte), _in: (addr array byte) { + var in/esi: (addr array byte) <- copy _in + var n/ecx: int <- length in + var out/edx: (addr handle array byte) <- copy _out + populate out, n + var _out-addr/eax: (addr array byte) <- lookup *out + var out-addr/edx: (addr array byte) <- copy _out-addr + var i/eax: int <- copy 0 + { + compare i, n + break-if->= + var src/esi: (addr byte) <- index in, i + var val/ecx: byte <- copy-byte *src + var dest/edi: (addr byte) <- index out-addr, i + copy-byte-to *dest, val + i <- increment + loop + } +} + +fn initialize-path-from-sandbox _in: (addr sandbox), _out: (addr handle call-path-element) { + var sandbox/esi: (addr sandbox) <- copy _in + var line-ah/eax: (addr handle line) <- get sandbox, data + var line/eax: (addr line) <- lookup *line-ah + var src/esi: (addr handle word) <- get line, data + var out-ah/edi: (addr handle call-path-element) <- copy _out + var out/eax: (addr call-path-element) <- lookup *out-ah + var dest/edi: (addr handle word) <- get out, word + copy-object src, dest +} + +fn initialize-path-from-line _line: (addr line), _out: (addr handle call-path-element) { + var line/eax: (addr line) <- copy _line + var src/esi: (addr handle word) <- get line, data + var out-ah/edi: (addr handle call-path-element) <- copy _out + var out/eax: (addr call-path-element) <- lookup *out-ah + var dest/edi: (addr handle word) <- get out, word + copy-object src, dest +} + +fn find-in-call-paths call-paths: (addr handle call-path), needle: (addr handle call-path-element) -> _/eax: boolean { + var curr-ah/esi: (addr handle call-path) <- copy call-paths + $find-in-call-path:loop: { + var curr/eax: (addr call-path) <- lookup *curr-ah + compare curr, 0 + break-if-= + { + var curr-data/eax: (addr handle call-path-element) <- get curr, data + var match?/eax: boolean <- call-path-element-match? curr-data, needle + compare match?, 0/false + { + break-if-= + return 1/true + } + } + curr-ah <- get curr, next + loop + } + return 0/false +} + +fn call-path-element-match? _x: (addr handle call-path-element), _y: (addr handle call-path-element) -> _/eax: boolean { + var x-ah/eax: (addr handle call-path-element) <- copy _x + var x-a/eax: (addr call-path-element) <- lookup *x-ah + var x/esi: (addr call-path-element) <- copy x-a + var y-ah/eax: (addr handle call-path-element) <- copy _y + var y-a/eax: (addr call-path-element) <- lookup *y-ah + var y/edi: (addr call-path-element) <- copy y-a + compare x, y + { + break-if-!= + return 1/true + } + compare x, 0 + { + break-if-!= + return 0/false + } + compare y, 0 + { + break-if-!= + return 0/false + } + # compare word addresses, not contents + var x-data-ah/ecx: (addr handle word) <- get x, word + var x-data-a/eax: (addr word) <- lookup *x-data-ah + var x-data/ecx: int <- copy x-data-a + var y-data-ah/eax: (addr handle word) <- get y, word + var y-data-a/eax: (addr word) <- lookup *y-data-ah + var y-data/eax: int <- copy y-data-a +#? print-string 0, "match? " +#? print-int32-hex 0, x-data +#? print-string 0, " vs " +#? print-int32-hex 0, y-data +#? print-string 0, "\n" + compare x-data, y-data + { + break-if-= + return 0/false + } + var x-next/ecx: (addr handle call-path-element) <- get x, next + var y-next/eax: (addr handle call-path-element) <- get y, next + var result/eax: boolean <- call-path-element-match? x-next, y-next + return result +} + +# order is irrelevant +fn insert-in-call-path list: (addr handle call-path), new: (addr handle call-path-element) { + var new-path-storage: (handle call-path) + var new-path-ah/edi: (addr handle call-path) <- address new-path-storage + allocate new-path-ah + var new-path/eax: (addr call-path) <- lookup *new-path-ah + var next/ecx: (addr handle call-path) <- get new-path, next + copy-object list, next + var dest/ecx: (addr handle call-path-element) <- get new-path, data + deep-copy-call-path-element new, dest + copy-object new-path-ah, list +} + +# assumes dest is initially clear +fn deep-copy-call-path-element _src: (addr handle call-path-element), _dest: (addr handle call-path-element) { + var src/esi: (addr handle call-path-element) <- copy _src + # if src is null, return + var _src-addr/eax: (addr call-path-element) <- lookup *src + compare _src-addr, 0 + break-if-= + # allocate + var src-addr/esi: (addr call-path-element) <- copy _src-addr + var dest/eax: (addr handle call-path-element) <- copy _dest + allocate dest + # copy data + var dest-addr/eax: (addr call-path-element) <- lookup *dest + { + var dest-data-addr/ecx: (addr handle word) <- get dest-addr, word + var src-data-addr/eax: (addr handle word) <- get src-addr, word + copy-object src-data-addr, dest-data-addr + } + # recurse + var src-next/esi: (addr handle call-path-element) <- get src-addr, next + var dest-next/eax: (addr handle call-path-element) <- get dest-addr, next + deep-copy-call-path-element src-next, dest-next +} + +fn delete-in-call-path list: (addr handle call-path), needle: (addr handle call-path-element) { + var curr-ah/esi: (addr handle call-path) <- copy list + $delete-in-call-path:loop: { + var _curr/eax: (addr call-path) <- lookup *curr-ah + var curr/ecx: (addr call-path) <- copy _curr + compare curr, 0 + break-if-= + { + var curr-data/eax: (addr handle call-path-element) <- get curr, data + var match?/eax: boolean <- call-path-element-match? curr-data, needle + compare match?, 0/false + { + break-if-= + var next-ah/ecx: (addr handle call-path) <- get curr, next + copy-object next-ah, curr-ah + loop $delete-in-call-path:loop + } + } + curr-ah <- get curr, next + loop + } +} + +fn increment-final-element list: (addr handle call-path-element) { + var final-ah/eax: (addr handle call-path-element) <- copy list + var final/eax: (addr call-path-element) <- lookup *final-ah + var val-ah/ecx: (addr handle word) <- get final, word + var val/eax: (addr word) <- lookup *val-ah + var new-ah/edx: (addr handle word) <- get val, next + var target/eax: (addr word) <- lookup *new-ah + compare target, 0 + break-if-= + copy-object new-ah, val-ah +} + +fn decrement-final-element list: (addr handle call-path-element) { + var final-ah/eax: (addr handle call-path-element) <- copy list + var final/eax: (addr call-path-element) <- lookup *final-ah + var val-ah/ecx: (addr handle word) <- get final, word + var val/eax: (addr word) <- lookup *val-ah +#? print-string 0, "replacing " +#? { +#? var foo/eax: int <- copy val +#? print-int32-hex 0, foo +#? } + var new-ah/edx: (addr handle word) <- get val, prev + var target/eax: (addr word) <- lookup *new-ah + compare target, 0 + break-if-= + # val = val->prev +#? print-string 0, " with " +#? { +#? var foo/eax: int <- copy target +#? print-int32-hex 0, foo +#? } +#? print-string 0, "\n" + copy-object new-ah, val-ah +} + +fn move-final-element-to-start-of-line list: (addr handle call-path-element) { + var final-ah/eax: (addr handle call-path-element) <- copy list + var final/eax: (addr call-path-element) <- lookup *final-ah + var val-ah/ecx: (addr handle word) <- get final, word + var val/eax: (addr word) <- lookup *val-ah + var new-ah/edx: (addr handle word) <- get val, prev + var target/eax: (addr word) <- lookup *new-ah + compare target, 0 + break-if-= + copy-object new-ah, val-ah + move-final-element-to-start-of-line list +} + +fn move-final-element-to-end-of-line list: (addr handle call-path-element) { + var final-ah/eax: (addr handle call-path-element) <- copy list + var final/eax: (addr call-path-element) <- lookup *final-ah + var val-ah/ecx: (addr handle word) <- get final, word + var val/eax: (addr word) <- lookup *val-ah + var new-ah/edx: (addr handle word) <- get val, next + var target/eax: (addr word) <- lookup *new-ah + compare target, 0 + break-if-= + copy-object new-ah, val-ah + move-final-element-to-end-of-line list +} + +fn push-to-call-path-element list: (addr handle call-path-element), new: (addr handle word) { + var new-element-storage: (handle call-path-element) + var new-element-ah/edi: (addr handle call-path-element) <- address new-element-storage + allocate new-element-ah + var new-element/eax: (addr call-path-element) <- lookup *new-element-ah + # save word + var dest/ecx: (addr handle word) <- get new-element, word + copy-object new, dest + # save next + var dest2/ecx: (addr handle call-path-element) <- get new-element, next + copy-object list, dest2 + # return + copy-object new-element-ah, list +} + +fn drop-from-call-path-element _list: (addr handle call-path-element) { + var list-ah/esi: (addr handle call-path-element) <- copy _list + var list/eax: (addr call-path-element) <- lookup *list-ah + var next/eax: (addr handle call-path-element) <- get list, next + copy-object next, _list +} + +fn drop-nested-calls _list: (addr handle call-path-element) { + var list-ah/esi: (addr handle call-path-element) <- copy _list + var list/eax: (addr call-path-element) <- lookup *list-ah + var next-ah/edi: (addr handle call-path-element) <- get list, next + var next/eax: (addr call-path-element) <- lookup *next-ah + compare next, 0 + break-if-= + copy-object next-ah, _list + drop-nested-calls _list +} + +fn dump-call-path-element screen: (addr screen), _x-ah: (addr handle call-path-element) { + var x-ah/ecx: (addr handle call-path-element) <- copy _x-ah + var _x/eax: (addr call-path-element) <- lookup *x-ah + var x/esi: (addr call-path-element) <- copy _x + var word-ah/eax: (addr handle word) <- get x, word + var word/eax: (addr word) <- lookup *word-ah + print-word screen, word + var next-ah/ecx: (addr handle call-path-element) <- get x, next + var next/eax: (addr call-path-element) <- lookup *next-ah + compare next, 0 + { + break-if-= + print-string screen, " " + dump-call-path-element screen, next-ah + return + } + print-string screen, "\n" +} + +fn dump-call-paths screen: (addr screen), _x-ah: (addr handle call-path) { + var x-ah/ecx: (addr handle call-path) <- copy _x-ah + var x/eax: (addr call-path) <- lookup *x-ah + compare x, 0 + break-if-= + var src/ecx: (addr handle call-path-element) <- get x, data + dump-call-path-element screen, src + var next-ah/ecx: (addr handle call-path) <- get x, next + var next/eax: (addr call-path) <- lookup *next-ah + compare next, 0 + { + break-if-= + dump-call-paths screen, next-ah + } +} + +fn function-width _self: (addr function) -> _/eax: int { + var self/esi: (addr function) <- copy _self + var args/ecx: (addr handle word) <- get self, args + var arg-width/eax: int <- word-list-length args + var result/edi: int <- copy arg-width + result <- add 4 # function-header-indent + body-indent + var body-ah/eax: (addr handle line) <- get self, body + var body-width/eax: int <- body-width body-ah + body-width <- add 1 # right margin + body-width <- add 2 # body-indent for "≡ " + compare result, body-width + { + break-if->= + result <- copy body-width + } + return result +} + +fn body-width lines: (addr handle line) -> _/eax: int { + var curr-ah/esi: (addr handle line) <- copy lines + var result/edi: int <- copy 0 + { + var curr/eax: (addr line) <- lookup *curr-ah + compare curr, 0 + break-if-= + { + var words/ecx: (addr handle word) <- get curr, data + var curr-len/eax: int <- word-list-length words + compare curr-len, result + break-if-<= + result <- copy curr-len + } + curr-ah <- get curr, next + loop + } + return result +} + +fn function-height _self: (addr function) -> _/eax: int { + var self/esi: (addr function) <- copy _self + var body-ah/eax: (addr handle line) <- get self, body + var result/eax: int <- line-list-length body-ah + result <- increment # for function header + return result +} + +fn line-list-length lines: (addr handle line) -> _/eax: int { + var curr-ah/esi: (addr handle line) <- copy lines + var result/edi: int <- copy 0 + { + var curr/eax: (addr line) <- lookup *curr-ah + compare curr, 0 + break-if-= + curr-ah <- get curr, next + result <- increment + loop + } + return result +} |