From 8bb22dcb0a3819c1cc22299aec8126a701a3267d Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Thu, 11 Feb 2021 21:11:41 -0800 Subject: 7725 - baremetal/shell: start on evaluator --- baremetal/shell/eval.mu | 36 +++++++++++ baremetal/shell/value-stack.mu | 138 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 174 insertions(+) create mode 100644 baremetal/shell/eval.mu create mode 100644 baremetal/shell/value-stack.mu (limited to 'baremetal/shell') diff --git a/baremetal/shell/eval.mu b/baremetal/shell/eval.mu new file mode 100644 index 00000000..2506bd22 --- /dev/null +++ b/baremetal/shell/eval.mu @@ -0,0 +1,36 @@ +# evaluator for the Mu shell language +# inputs: +# a list of lines, each a list of words, each an editable gap-buffer +# end: a word to stop at +# output: +# a stack of values to render that summarizes the result of evaluation until 'end' + +# Key features of the language: +# { and } for grouping words +# break and loop for control flow within groups +# -> for conditionally skipping the next word or group + +# Example: Pushing numbers from 1 to n on the stack (single-line body with +# conditionals and loops) +# +# 3 =n +# { n 1 < -> break n n 1- =n loop } +# stack: +# 3 1 false 3 3 2 3 1 +# 3 3 3 2 +# 3 + +# Rules beyond simple postfix: +# If the final word is `->`, clear stack +# If the final word is `break`, pop top of stack +# +# `{` and `}` don't affect evaluation +# If the final word is `{` or `}`, clear stack +# +# If `->` in middle and top of stack is falsy, skip next word or group +# +# If `break` in middle executes, skip to next containing `}` +# If no containing `}`, clear stack (incomplete) +# +# If `loop` in middle executes, skip to previous containing `{` +# If no containing `}`, clear stack (error) diff --git a/baremetal/shell/value-stack.mu b/baremetal/shell/value-stack.mu new file mode 100644 index 00000000..c456f2e5 --- /dev/null +++ b/baremetal/shell/value-stack.mu @@ -0,0 +1,138 @@ +type value-stack { + data: (handle array value) + top: int +} + +fn initialize-value-stack _self: (addr value-stack), n: int { + var self/esi: (addr value-stack) <- copy _self + var d/edi: (addr handle array value) <- get self, data + populate d, n + var top/eax: (addr int) <- get self, top + copy-to *top, 0 +} + +fn clear-value-stack _self: (addr value-stack) { + var self/esi: (addr value-stack) <- copy _self + var top/eax: (addr int) <- get self, top + copy-to *top, 0 +} + +fn push-number-to-value-stack _self: (addr value-stack), _val: float { + var self/esi: (addr value-stack) <- copy _self + var top-addr/ecx: (addr int) <- get self, top + var data-ah/edx: (addr handle array value) <- get self, data + var data/eax: (addr array value) <- lookup *data-ah + var top/edx: int <- copy *top-addr + var dest-offset/edx: (offset value) <- compute-offset data, top + var dest-addr/edx: (addr value) <- index data, dest-offset + var dest-addr2/eax: (addr float) <- get dest-addr, number-data + var val/xmm0: float <- copy _val + copy-to *dest-addr2, val + increment *top-addr + var type-addr/eax: (addr int) <- get dest-addr, type + copy-to *type-addr, 0/number +} + +fn push-string-to-value-stack _self: (addr value-stack), val: (handle array byte) { + var self/esi: (addr value-stack) <- copy _self + var top-addr/ecx: (addr int) <- get self, top + var data-ah/edx: (addr handle array value) <- get self, data + var data/eax: (addr array value) <- lookup *data-ah + var top/edx: int <- copy *top-addr + var dest-offset/edx: (offset value) <- compute-offset data, top + var dest-addr/edx: (addr value) <- index data, dest-offset + var dest-addr2/eax: (addr handle array byte) <- get dest-addr, text-data + copy-handle val, dest-addr2 + var dest-addr3/eax: (addr int) <- get dest-addr, type + copy-to *dest-addr3, 1/string + increment *top-addr +} + +fn push-array-to-value-stack _self: (addr value-stack), val: (handle array value) { + var self/esi: (addr value-stack) <- copy _self + var top-addr/ecx: (addr int) <- get self, top + var data-ah/edx: (addr handle array value) <- get self, data + var data/eax: (addr array value) <- lookup *data-ah + var top/edx: int <- copy *top-addr + var dest-offset/edx: (offset value) <- compute-offset data, top + var dest-addr/edx: (addr value) <- index data, dest-offset + var dest-addr2/eax: (addr handle array value) <- get dest-addr, array-data + copy-handle val, dest-addr2 + # update type + var dest-addr3/eax: (addr int) <- get dest-addr, type + copy-to *dest-addr3, 2/array + increment *top-addr +} + +fn push-value-stack _self: (addr value-stack), val: (addr value) { + var self/esi: (addr value-stack) <- copy _self + var top-addr/ecx: (addr int) <- get self, top + var data-ah/edx: (addr handle array value) <- get self, data + var data/eax: (addr array value) <- lookup *data-ah + var top/edx: int <- copy *top-addr + var dest-offset/edx: (offset value) <- compute-offset data, top + var dest-addr/edx: (addr value) <- index data, dest-offset + copy-object val, dest-addr + increment *top-addr +} + +fn pop-number-from-value-stack _self: (addr value-stack) -> _/xmm0: float { + var self/esi: (addr value-stack) <- copy _self + var top-addr/ecx: (addr int) <- get self, top + { + compare *top-addr, 0 + break-if-> + var minus-one/eax: int <- copy -1 + var minus-one-f/xmm0: float <- convert minus-one + return minus-one-f + } + decrement *top-addr + var data-ah/edx: (addr handle array value) <- get self, data + var data/eax: (addr array value) <- lookup *data-ah + var top/edx: int <- copy *top-addr + var dest-offset/edx: (offset value) <- compute-offset data, top + var result-addr/eax: (addr value) <- index data, dest-offset + var result-addr2/eax: (addr float) <- get result-addr, number-data + return *result-addr2 +} + +fn value-stack-empty? _self: (addr value-stack) -> _/eax: boolean { + var self/esi: (addr value-stack) <- copy _self + var top/eax: (addr int) <- get self, top + compare *top, 0 + { + break-if-!= + return 1/true + } + return 0/false +} + +fn value-stack-length _self: (addr value-stack) -> _/eax: int { + var self/esi: (addr value-stack) <- copy _self + var top-addr/eax: (addr int) <- get self, top + return *top-addr +} + +fn save-lines in-h: (handle array (handle array byte)), _out-ah: (addr handle array value) { + var _in/eax: (addr array (handle array byte)) <- lookup in-h + var in/esi: (addr array (handle array byte)) <- copy _in + var len/ecx: int <- length in + var out-ah/edi: (addr handle array value) <- copy _out-ah + populate out-ah, len + var out/eax: (addr array value) <- lookup *out-ah + # copy in into out + var i/ebx: int <- copy 0 + { + compare i, len + break-if->= + var src/ecx: (addr handle array byte) <- index in, i + var dest-offset/edx: (offset value) <- compute-offset out, i + var dest-val/edx: (addr value) <- index out, dest-offset + var dest/eax: (addr handle array byte) <- get dest-val, text-data + copy-object src, dest + var type/edx: (addr int) <- get dest-val, type + copy-to *type, 1/string + i <- increment + loop + } +} -- cgit 1.4.1-2-gfad0