diff --git a/apps/README.md b/apps/README.md index 3cffc3fc..d17c0be9 100644 --- a/apps/README.md +++ b/apps/README.md @@ -1,7 +1,8 @@ Some apps written in SubX and Mu. Check out: * `tile`: [A text-mode postfix calculator](https://mastodon.social/@akkartik/104896128141863951) - that updates as you type. + that updates as you type. Prototype. Look at this to see what is currently + possible, not how I recommend building software. tile app diff --git a/apps/tile/rpn.mu b/apps/tile/rpn.mu index 47383642..1d94d69f 100644 --- a/apps/tile/rpn.mu +++ b/apps/tile/rpn.mu @@ -2,21 +2,21 @@ fn evaluate defs: (addr handle function), bindings: (addr table), scratch: (addr var line/eax: (addr line) <- copy scratch var word-ah/eax: (addr handle word) <- get line, data var curr/eax: (addr word) <- lookup *word-ah - var curr-text-storage: (stream byte 0x10) - var curr-text/edi: (addr stream byte) <- address curr-text-storage + var curr-stream-storage: (stream byte 0x10) + var curr-stream/edi: (addr stream byte) <- address curr-stream-storage clear-int-stack out $evaluate:loop: { # precondition (should never hit) compare curr, 0 break-if-= - # update curr-text - emit-word curr, curr-text -#? print-stream-to-real-screen curr-text + # update curr-stream + emit-word curr, curr-stream +#? print-stream-to-real-screen curr-stream #? print-string-to-real-screen "\n" $evaluate:process-word: { - # if curr-text is an operator, perform it + # if curr-stream is an operator, perform it { - var is-add?/eax: boolean <- stream-data-equal? curr-text, "+" + var is-add?/eax: boolean <- stream-data-equal? curr-stream, "+" compare is-add?, 0 break-if-= var _b/eax: int <- pop-int-stack out @@ -27,7 +27,7 @@ fn evaluate defs: (addr handle function), bindings: (addr table), scratch: (addr break $evaluate:process-word } { - var is-sub?/eax: boolean <- stream-data-equal? curr-text, "-" + var is-sub?/eax: boolean <- stream-data-equal? curr-stream, "-" compare is-sub?, 0 break-if-= var _b/eax: int <- pop-int-stack out @@ -38,7 +38,7 @@ fn evaluate defs: (addr handle function), bindings: (addr table), scratch: (addr break $evaluate:process-word } { - var is-mul?/eax: boolean <- stream-data-equal? curr-text, "*" + var is-mul?/eax: boolean <- stream-data-equal? curr-stream, "*" compare is-mul?, 0 break-if-= var _b/eax: int <- pop-int-stack out @@ -48,20 +48,42 @@ fn evaluate defs: (addr handle function), bindings: (addr table), scratch: (addr push-int-stack out, a break $evaluate:process-word } - # if curr-text is a known function name, call it appropriately + # if curr-stream is a known function name, call it appropriately { var callee-h: (handle function) var callee-ah/eax: (addr handle function) <- address callee-h - find-function defs, curr-text, callee-ah + find-function defs, curr-stream, callee-ah var callee/eax: (addr function) <- lookup *callee-ah compare callee, 0 break-if-= perform-call callee, out, defs break $evaluate:process-word } - # otherwise it's an int + # if it's a name, push its value { - var n/eax: int <- parse-decimal-int-from-stream curr-text + compare bindings, 0 + break-if-= + var tmp: (handle array byte) + var curr-string-ah/edx: (addr handle array byte) <- address tmp + stream-to-string curr-stream, curr-string-ah + var _curr-string/eax: (addr array byte) <- lookup *curr-string-ah + var curr-string/edx: (addr array byte) <- copy _curr-string + var result/eax: int <- copy 0 + var found?/ecx: boolean <- copy 0 # false + result, found? <- lookup-binding bindings, curr-string + compare found?, 0 # false + break-if-= +#? print-string-to-real-screen "value of " +#? print-string-to-real-screen curr-string +#? print-string-to-real-screen " is " +#? print-int32-hex-to-real-screen result +#? print-string-to-real-screen "\n" + push-int-stack out, result + break $evaluate:process-word + } + # otherwise assume it's a literal int and push it + { + var n/eax: int <- parse-decimal-int-from-stream curr-stream push-int-stack out, n } } @@ -102,7 +124,7 @@ fn perform-call _callee: (addr function), caller-stack: (addr int-stack), defs: # create bindings for args var table-storage: table var table/esi: (addr table) <- address table-storage - initialize-table table + initialize-table table, 0x10 # var curr-arg-ah/eax: (addr handle word) <- get callee, args var curr-arg/eax: (addr word) <- lookup *curr-arg-ah @@ -115,7 +137,13 @@ fn perform-call _callee: (addr function), caller-stack: (addr int-stack), defs: # create binding word-to-string curr-arg, curr-key { +#? var tmp/eax: (addr array byte) <- lookup *curr-key +#? print-string-to-real-screen "binding " +#? print-string-to-real-screen tmp +#? print-string-to-real-screen " to " var curr-val/eax: int <- pop-int-stack caller-stack +#? print-int32-decimal-to-real-screen curr-val +#? print-string-to-real-screen "\n" bind-int-in-table table, curr-key, curr-val } # diff --git a/apps/tile/table.mu b/apps/tile/table.mu index 851f891c..53fb5ce7 100644 --- a/apps/tile/table.mu +++ b/apps/tile/table.mu @@ -1,7 +1,7 @@ -fn initialize-table _self: (addr table) { +fn initialize-table _self: (addr table), n: int { var self/esi: (addr table) <- copy _self var data-ah/eax: (addr handle array bind) <- get self, data - populate data-ah, 0x10 + populate data-ah, n } fn bind-int-in-table _self: (addr table), key: (addr handle array byte), val: int { @@ -45,3 +45,38 @@ fn make-binding _self: (addr bind), key: (addr handle array byte), _val: int { var val/ecx: int <- copy _val copy-to *dest3, val } + +# TODO: supporting non-integers +# That'll require radical surgery. +fn lookup-binding _self: (addr table), key: (addr array byte) -> result/eax: int, found?/ecx: boolean { + var self/esi: (addr table) <- copy _self + var data-ah/esi: (addr handle array bind) <- get self, data + var _data/eax: (addr array bind) <- lookup *data-ah + var data/esi: (addr array bind) <- copy _data + var len/edx: int <- length data + var i/ebx: int <- copy 0 + found? <- copy 0 # false + $lookup-binding:loop: { + compare i, len + break-if->= + { + var offset/edx: (offset bind) <- compute-offset data, i + var target-bind/esi: (addr bind) <- index data, offset + var target2/edx: (addr handle array byte) <- get target-bind, key + var target3/eax: (addr array byte) <- lookup *target2 + compare target3, 0 + break-if-= $lookup-binding:loop + var is-match?/eax: boolean <- string-equal? target3, key + compare is-match?, 0 # false + break-if-= + # found + found? <- copy 1 # true + var dest2/eax: (addr value) <- get target-bind, value + var dest3/eax: (addr int) <- get dest2, scalar-data + result <- copy *dest3 + break $lookup-binding:loop + } + i <- increment + loop + } +}