From d75b71297426ee2d63d5630d1ef9469de48aca84 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Thu, 1 Oct 2020 20:40:22 -0700 Subject: 6923 --- prototypes/tile/1.mu | 47 ------ prototypes/tile/10.mu | 341 -------------------------------------------- prototypes/tile/11.mu | 353 ---------------------------------------------- prototypes/tile/2.mu | 84 ----------- prototypes/tile/3.mu | 76 ---------- prototypes/tile/4.mu | 56 -------- prototypes/tile/5.mu | 145 ------------------- prototypes/tile/6.mu | 184 ------------------------ prototypes/tile/7.mu | 198 -------------------------- prototypes/tile/8.mu | 228 ------------------------------ prototypes/tile/9.mu | 307 ---------------------------------------- prototypes/tile/README.md | 13 -- 12 files changed, 2032 deletions(-) delete mode 100644 prototypes/tile/1.mu delete mode 100644 prototypes/tile/10.mu delete mode 100644 prototypes/tile/11.mu delete mode 100644 prototypes/tile/2.mu delete mode 100644 prototypes/tile/3.mu delete mode 100644 prototypes/tile/4.mu delete mode 100644 prototypes/tile/5.mu delete mode 100644 prototypes/tile/6.mu delete mode 100644 prototypes/tile/7.mu delete mode 100644 prototypes/tile/8.mu delete mode 100644 prototypes/tile/9.mu delete mode 100644 prototypes/tile/README.md (limited to 'prototypes/tile') diff --git a/prototypes/tile/1.mu b/prototypes/tile/1.mu deleted file mode 100644 index 4d0a7969..00000000 --- a/prototypes/tile/1.mu +++ /dev/null @@ -1,47 +0,0 @@ -# little example program: animate a line in text-mode -# -# To run (on Linux and x86): -# $ git clone https://github.com/akkartik/mu -# $ cd mu -# $ ./translate_mu prototypes/tile/1.mu -# $ ./a.elf -# You should see a line drawn on a blank screen. Press a key. You should see -# the line seem to fall down the screen. Press a second key to quit. -# https://archive.org/details/akkartik-2min-2020-07-01 - -fn main -> exit-status/ebx: int { - clear-screen 0 - move-cursor 0, 5, 5 - print-string 0, "_________" - enable-keyboard-immediate-mode - var dummy/eax: grapheme <- read-key-from-real-keyboard - var row/eax: int <- copy 5 - { - compare row, 0xe # 15 - break-if-= - animate row - row <- increment - sleep 0 0x5f5e100 # 100ms - loop - } - var dummy/eax: grapheme <- read-key-from-real-keyboard - enable-keyboard-type-mode - clear-screen 0 - exit-status <- copy 0 -} - -fn animate row: int { - var col/eax: int <- copy 5 - { - compare col, 0xe - break-if-= - move-cursor 0, row, col - print-string 0, " " - increment row - move-cursor 0, row, col - print-string 0, "_" - decrement row - col <- increment - loop - } -} diff --git a/prototypes/tile/10.mu b/prototypes/tile/10.mu deleted file mode 100644 index 6f971b1c..00000000 --- a/prototypes/tile/10.mu +++ /dev/null @@ -1,341 +0,0 @@ -# Moving around within a tree and creating children. -# -# To run (on Linux and x86): -# $ git clone https://github.com/akkartik/mu -# $ cd mu -# $ ./translate_mu prototypes/tile/10.mu -# $ ./a.elf -# -# Press 'c' to create new children for the root node, and keys to move: -# 'h': parent -# 'l': first child -# 'j': next sibling -# 'k': prev sibling - -# To run unit tests: -# $ ./a.elf test -fn main args-on-stack: (addr array addr array byte) -> exit-status/ebx: int { - var args/eax: (addr array addr array byte) <- copy args-on-stack - var tmp/ecx: int <- length args - $main-body: { - # if (len(args) > 1 && args[1] == "test") run-tests() - compare tmp, 1 - { - break-if-<= - # if (args[1] == "test") run-tests() - var tmp2/ecx: (addr addr array byte) <- index args, 1 - var tmp3/eax: boolean <- string-equal? *tmp2, "test" - compare tmp3, 0 - { - break-if-= - run-tests - exit-status <- copy 0 # TODO: get at Num-test-failures somehow - } - break $main-body - } - # otherwise operate interactively - exit-status <- interactive - } -} - -# - interactive loop - -type cell { - val: int # single chars only for now - parent: (handle cell) - first-child: (handle cell) - next-sibling: (handle cell) - prev-sibling: (handle cell) -} - -fn interactive -> exit-status/ebx: int { - var root-handle: (handle cell) - var root/esi: (addr handle cell) <- address root-handle - allocate root - var cursor-handle: (handle cell) - var cursor/edi: (addr handle cell) <- address cursor-handle - copy-handle root-handle, cursor - enable-keyboard-immediate-mode - var _root-addr/eax: (addr cell) <- lookup *root - var root-addr/ecx: (addr cell) <- copy _root-addr - var cursor-addr/eax: (addr cell) <- lookup *cursor - render root-addr, cursor-addr -$main:loop: { - # process key - { - var c/eax: grapheme <- read-key-from-real-keyboard - compare c, 4 # ctrl-d - break-if-= $main:loop - process c, root, cursor - } - # render tree - var _root-addr/eax: (addr cell) <- lookup root-handle - root-addr <- copy _root-addr - var cursor-addr/eax: (addr cell) <- lookup *cursor - render root-addr, cursor-addr - loop - } - clear-screen 0 - enable-keyboard-type-mode - exit-status <- copy 0 -} - -####################################################### -# Tree mutations -####################################################### - -fn process c: grapheme, root: (addr handle cell), cursor: (addr handle cell) { -$process:body: { - # if c == 'h' move cursor to its parent if possible - { - compare c, 0x68 # 'h' - break-if-!= - move-to-parent cursor - } - # if c == 'l' move cursor to its first child if possible - { - compare c, 0x6c # 'l' - break-if-!= - move-to-child cursor - } - # if c == 'j' move cursor to its next sibling if possible - { - compare c, 0x6a # 'j' - break-if-!= - move-to-next-sibling cursor - } - # if c == 'k' move cursor to its prev sibling if possible - { - compare c, 0x6b # 'k' - break-if-!= - move-to-prev-sibling cursor - } - # if c == 'c' create a new child at the cursor - { - compare c, 0x63 # 'c' - break-if-!= - var cursor2/eax: (addr handle cell) <- copy cursor - create-child *cursor2 - } -} -} - -fn move-to-parent cursor: (addr handle cell) { - var cursor2/eax: (addr handle cell) <- copy cursor - var cursor3/eax: (addr cell) <- lookup *cursor2 - var parent/ecx: (addr handle cell) <- get cursor3, parent - { - var tmp/eax: (addr cell) <- lookup *parent - compare tmp, 0 - break-if-= - copy-handle *parent, cursor - } -} - -fn move-to-child cursor: (addr handle cell) { - var cursor2/eax: (addr handle cell) <- copy cursor - var cursor3/eax: (addr cell) <- lookup *cursor2 - var child/ecx: (addr handle cell) <- get cursor3, first-child - { - var tmp/eax: (addr cell) <- lookup *child - compare tmp, 0 - break-if-= - copy-handle *child, cursor - } -} - -fn move-to-next-sibling cursor: (addr handle cell) { - var cursor2/eax: (addr handle cell) <- copy cursor - var cursor3/eax: (addr cell) <- lookup *cursor2 - var sib/ecx: (addr handle cell) <- get cursor3, next-sibling - { - var tmp/eax: (addr cell) <- lookup *sib - compare tmp, 0 - break-if-= - copy-handle *sib, cursor - } -} - -fn move-to-prev-sibling cursor: (addr handle cell) { - var cursor2/eax: (addr handle cell) <- copy cursor - var cursor3/eax: (addr cell) <- lookup *cursor2 - var sib/ecx: (addr handle cell) <- get cursor3, prev-sibling - { - var tmp/eax: (addr cell) <- lookup *sib - compare tmp, 0 - break-if-= - copy-handle *sib, cursor - } -} - -fn create-child node: (handle cell) { - var n/eax: (addr cell) <- lookup node - var child/esi: (addr handle cell) <- get n, first-child - var prev/edx: (addr handle cell) <- copy 0 - { - var tmp/eax: (addr cell) <- lookup *child - compare tmp, 0 - break-if-= - prev <- copy child - child <- get tmp, next-sibling - loop - } - allocate child - var child2/eax: (addr cell) <- lookup *child - var dest/ecx: (addr handle cell) <- get child2, prev-sibling - # child->prev-sibling = prev - { - compare prev, 0 - break-if-= - copy-handle *prev, dest - } - # child->parent = node - dest <- get child2, parent - copy-handle node, dest -} - -####################################################### -# Tree drawing -####################################################### - -fn render root: (addr cell), cursor: (addr cell) { - clear-screen 0 - var depth/eax: int <- tree-depth root - var viewport-width/ecx: int <- copy 0x65 # col2 - viewport-width <- subtract 5 # col1 - var column-width/eax: int <- try-divide viewport-width, depth - render-tree root, column-width, 5, 5, 0x20, 0x65, cursor -} - -fn render-tree c: (addr cell), column-width: int, row-min: int, col-min: int, row-max: int, col-max: int, cursor: (addr cell) { -$render-tree:body: { - var root-max/ecx: int <- copy col-min - root-max <- add column-width - draw-box row-min, col-min, row-max, root-max - var c2/edx: (addr cell) <- copy c - { - compare c2, cursor - break-if-!= - draw-hatching row-min, col-min, row-max, root-max - } - # if single child, render it (slightly shorter than the parent) - var nchild/eax: int <- num-children c - { - compare nchild, 1 - break-if-> - var child/edx: (addr handle cell) <- get c2, first-child - var child-addr/eax: (addr cell) <- lookup *child - { - compare child-addr, 0 - break-if-= - increment row-min - decrement row-max - render-tree child-addr, column-width, row-min, root-max, row-max, col-max, cursor - } - break $render-tree:body - } - # otherwise divide vertical space up equally among children - var column-height/ebx: int <- copy row-max - column-height <- subtract row-min - var child-height/eax: int <- try-divide column-height, nchild - var child-height2/ebx: int <- copy child-height - var curr/edx: (addr handle cell) <- get c2, first-child - var curr-addr/eax: (addr cell) <- lookup *curr - var rmin/esi: int <- copy row-min - var rmax/edi: int <- copy row-min - rmax <- add child-height2 - { - compare curr-addr, 0 - break-if-= - render-tree curr-addr, column-width, rmin, root-max, rmax, col-max, cursor - curr <- get curr-addr, next-sibling - curr-addr <- lookup *curr - rmin <- add child-height2 - rmax <- add child-height2 - loop - } -} -} - -fn num-children node-on-stack: (addr cell) -> result/eax: int { - var tmp-result/edi: int <- copy 0 - var node/eax: (addr cell) <- copy node-on-stack - var child/ecx: (addr handle cell) <- get node, first-child - var child-addr/eax: (addr cell) <- lookup *child - { - compare child-addr, 0 - break-if-= - tmp-result <- increment - child <- get child-addr, next-sibling - child-addr <- lookup *child - loop - } - result <- copy tmp-result -} - -fn tree-depth node-on-stack: (addr cell) -> result/eax: int { - var tmp-result/edi: int <- copy 0 - var node/eax: (addr cell) <- copy node-on-stack - var child/ecx: (addr handle cell) <- get node, first-child - var child-addr/eax: (addr cell) <- lookup *child - { - compare child-addr, 0 - break-if-= - { - var tmp/eax: int <- tree-depth child-addr - compare tmp, tmp-result - break-if-<= - tmp-result <- copy tmp - } - child <- get child-addr, next-sibling - child-addr <- lookup *child - loop - } - result <- copy tmp-result - result <- increment -} - -fn draw-box row1: int, col1: int, row2: int, col2: int { - draw-horizontal-line row1, col1, col2 - draw-vertical-line row1, row2, col1 - draw-horizontal-line row2, col1, col2 - draw-vertical-line row1, row2, col2 -} - -fn draw-hatching row1: int, col1: int, row2: int, col2: int { - var c/eax: int <- copy col1 - var r1/ecx: int <- copy row1 - r1 <- increment - c <- add 2 - { - compare c, col2 - break-if->= - draw-vertical-line r1, row2, c - c <- add 2 - loop - } -} - -fn draw-horizontal-line row: int, col1: int, col2: int { - var col/eax: int <- copy col1 - move-cursor 0, row, col - { - compare col, col2 - break-if->= - print-string 0, "-" - col <- increment - loop - } -} - -fn draw-vertical-line row1: int, row2: int, col: int { - var row/eax: int <- copy row1 - { - compare row, row2 - break-if->= - move-cursor 0, row, col - print-string 0, "|" - row <- increment - loop - } -} diff --git a/prototypes/tile/11.mu b/prototypes/tile/11.mu deleted file mode 100644 index 82de9fda..00000000 --- a/prototypes/tile/11.mu +++ /dev/null @@ -1,353 +0,0 @@ -# Moving around within a tree and creating children. -# -# To run (on Linux and x86): -# $ git clone https://github.com/akkartik/mu -# $ cd mu -# $ ./translate_mu prototypes/tile/10.mu -# $ ./a.elf -# -# Press 'c' to create new children for the root node, and keys to move: -# 'h': parent -# 'l': first child -# 'j': next sibling -# 'k': prev sibling - -# To run unit tests: -# $ ./a.elf test -fn main args-on-stack: (addr array addr array byte) -> exit-status/ebx: int { - var args/eax: (addr array addr array byte) <- copy args-on-stack - var tmp/ecx: int <- length args - $main-body: { - # if (len(args) > 1 && args[1] == "test") run-tests() - compare tmp, 1 - { - break-if-<= - # if (args[1] == "test") run-tests() - var tmp2/ecx: (addr addr array byte) <- index args, 1 - var tmp3/eax: boolean <- string-equal? *tmp2, "test" - compare tmp3, 0 - { - break-if-= - run-tests - exit-status <- copy 0 # TODO: get at Num-test-failures somehow - } - break $main-body - } - # otherwise operate interactively - exit-status <- interactive - } -} - -# - interactive loop - -type cell { - val: int # single chars only for now - parent: (handle cell) - first-child: (handle cell) - next-sibling: (handle cell) - prev-sibling: (handle cell) -} - -fn interactive -> exit-status/ebx: int { - var root-handle: (handle cell) - var root/esi: (addr handle cell) <- address root-handle - allocate root - var cursor-handle: (handle cell) - var cursor/edi: (addr handle cell) <- address cursor-handle - copy-handle root-handle, cursor - enable-keyboard-immediate-mode - var _root-addr/eax: (addr cell) <- lookup *root - var root-addr/ecx: (addr cell) <- copy _root-addr - var cursor-addr/eax: (addr cell) <- lookup *cursor - render root-addr, cursor-addr -$main:loop: { - # process key - { - var c/eax: grapheme <- read-key-from-real-keyboard - compare c, 4 # ctrl-d - break-if-= $main:loop - process c, root, cursor - } - # render tree - var _root-addr/eax: (addr cell) <- lookup root-handle - var root-addr/ecx: (addr cell) <- copy _root-addr - var cursor-addr/eax: (addr cell) <- lookup *cursor - render root-addr, cursor-addr - loop - } - clear-screen 0 - enable-keyboard-type-mode - exit-status <- copy 0 -} - -####################################################### -# Tree mutations -####################################################### - -fn process c: grapheme, root: (addr handle cell), cursor: (addr handle cell) { -$process:body: { - # if c == 'h' move cursor to its parent if possible - { - compare c, 0x68 # 'h' - break-if-!= - move-to-parent cursor - } - # if c == 'l' move cursor to its first child if possible - { - compare c, 0x6c # 'l' - break-if-!= - move-to-child cursor - } - # if c == 'j' move cursor to its next sibling if possible - { - compare c, 0x6a # 'j' - break-if-!= - move-to-next-sibling cursor - } - # if c == 'k' move cursor to its prev sibling if possible - { - compare c, 0x6b # 'k' - break-if-!= - move-to-prev-sibling cursor - } - # if c == 'c' create a new child at the cursor - { - compare c, 0x63 # 'c' - break-if-!= - var cursor2/eax: (addr handle cell) <- copy cursor - create-child *cursor2 - } -} -} - -fn move-to-parent cursor: (addr handle cell) { - var cursor2/eax: (addr handle cell) <- copy cursor - var cursor3/eax: (addr cell) <- lookup *cursor2 - var parent/ecx: (addr handle cell) <- get cursor3, parent - { - var tmp/eax: (addr cell) <- lookup *parent - compare tmp, 0 - break-if-= - copy-handle *parent, cursor - } -} - -fn move-to-child cursor: (addr handle cell) { - var cursor2/eax: (addr handle cell) <- copy cursor - var cursor3/eax: (addr cell) <- lookup *cursor2 - var child/ecx: (addr handle cell) <- get cursor3, first-child - { - var tmp/eax: (addr cell) <- lookup *child - compare tmp, 0 - break-if-= - copy-handle *child, cursor - } -} - -fn move-to-next-sibling cursor: (addr handle cell) { - var cursor2/eax: (addr handle cell) <- copy cursor - var cursor3/eax: (addr cell) <- lookup *cursor2 - var sib/ecx: (addr handle cell) <- get cursor3, next-sibling - { - var tmp/eax: (addr cell) <- lookup *sib - compare tmp, 0 - break-if-= - copy-handle *sib, cursor - } -} - -fn move-to-prev-sibling cursor: (addr handle cell) { - var cursor2/eax: (addr handle cell) <- copy cursor - var cursor3/eax: (addr cell) <- lookup *cursor2 - var sib/ecx: (addr handle cell) <- get cursor3, prev-sibling - { - var tmp/eax: (addr cell) <- lookup *sib - compare tmp, 0 - break-if-= - copy-handle *sib, cursor - } -} - -fn create-child node: (handle cell) { - var n/eax: (addr cell) <- lookup node - var child/esi: (addr handle cell) <- get n, first-child - var prev/edx: (addr handle cell) <- copy 0 - { - var tmp/eax: (addr cell) <- lookup *child - compare tmp, 0 - break-if-= - prev <- copy child - child <- get tmp, next-sibling - loop - } - allocate child - var child2/eax: (addr cell) <- lookup *child - var dest/ecx: (addr handle cell) <- get child2, prev-sibling - # child->prev-sibling = prev - { - compare prev, 0 - break-if-= - copy-handle *prev, dest - } - # child->parent = node - dest <- get child2, parent - copy-handle node, dest -} - -####################################################### -# Tree drawing -####################################################### - -fn render root: (addr cell), cursor: (addr cell) { - clear-screen 0 - var depth/eax: int <- tree-depth root - var viewport-width/ecx: int <- copy 0x65 # col2 - viewport-width <- subtract 5 # col1 - var column-width/eax: int <- try-divide viewport-width, depth - render-tree root, column-width, 5, 5, 0x20, 0x65, cursor -} - -fn render-tree c: (addr cell), column-width: int, row-min: int, col-min: int, row-max: int, col-max: int, cursor: (addr cell) { -$render-tree:body: { - var root-max/ecx: int <- copy col-min - root-max <- add column-width - draw-box row-min, col-min, row-max, root-max - move-cursor 0, row-min, col-min - var top-left/eax: code-point <- copy 0x250c - print-code-point 0, top-left - move-cursor 0, row-min, root-max - var top-right/eax: code-point <- copy 0x2510 - print-code-point 0, top-right - move-cursor 0, row-max, col-min - var bot-left/eax: code-point <- copy 0x2514 - print-code-point 0, bot-left - move-cursor 0, row-max, root-max - var bot-right/eax: code-point <- copy 0x2518 - print-code-point 0, bot-right - var c2/edx: (addr cell) <- copy c - { - compare c2, cursor - break-if-!= - draw-hatching row-min, col-min, row-max, root-max - } - # if single child, render it (slightly shorter than the parent) - var nchild/eax: int <- num-children c - { - compare nchild, 1 - break-if-> - var child/edx: (addr handle cell) <- get c2, first-child - var child-addr/eax: (addr cell) <- lookup *child - { - compare child-addr, 0 - break-if-= - increment row-min - decrement row-max - render-tree child-addr, column-width, row-min, root-max, row-max, col-max, cursor - } - break $render-tree:body - } - # otherwise divide vertical space up equally among children - var column-height/ebx: int <- copy row-max - column-height <- subtract row-min - var child-height/eax: int <- try-divide column-height, nchild - var child-height2/ebx: int <- copy child-height - var curr/edx: (addr handle cell) <- get c2, first-child - var curr-addr/eax: (addr cell) <- lookup *curr - var rmin/esi: int <- copy row-min - var rmax/edi: int <- copy row-min - rmax <- add child-height2 - { - compare curr-addr, 0 - break-if-= - render-tree curr-addr, column-width, rmin, root-max, rmax, col-max, cursor - curr <- get curr-addr, next-sibling - curr-addr <- lookup *curr - rmin <- add child-height2 - rmax <- add child-height2 - loop - } -} -} - -fn num-children node-on-stack: (addr cell) -> result/eax: int { - var tmp-result/edi: int <- copy 0 - var node/eax: (addr cell) <- copy node-on-stack - var child/ecx: (addr handle cell) <- get node, first-child - var child-addr/eax: (addr cell) <- lookup *child - { - compare child-addr, 0 - break-if-= - tmp-result <- increment - child <- get child-addr, next-sibling - child-addr <- lookup *child - loop - } - result <- copy tmp-result -} - -fn tree-depth node-on-stack: (addr cell) -> result/eax: int { - var tmp-result/edi: int <- copy 0 - var node/eax: (addr cell) <- copy node-on-stack - var child/ecx: (addr handle cell) <- get node, first-child - var child-addr/eax: (addr cell) <- lookup *child - { - compare child-addr, 0 - break-if-= - { - var tmp/eax: int <- tree-depth child-addr - compare tmp, tmp-result - break-if-<= - tmp-result <- copy tmp - } - child <- get child-addr, next-sibling - child-addr <- lookup *child - loop - } - result <- copy tmp-result - result <- increment -} - -fn draw-box row1: int, col1: int, row2: int, col2: int { - draw-horizontal-line row1, col1, col2 - draw-vertical-line row1, row2, col1 - draw-horizontal-line row2, col1, col2 - draw-vertical-line row1, row2, col2 -} - -fn draw-hatching row1: int, col1: int, row2: int, col2: int { - var c/eax: int <- copy col1 - var r1/ecx: int <- copy row1 - r1 <- increment - c <- add 2 - { - compare c, col2 - break-if->= - draw-vertical-line r1, row2, c - c <- add 2 - loop - } -} - -fn draw-horizontal-line row: int, col1: int, col2: int { - var col/eax: int <- copy col1 - move-cursor 0, row, col - { - compare col, col2 - break-if->= - print-code-point 0, 0x2500 - col <- increment - loop - } -} - -fn draw-vertical-line row1: int, row2: int, col: int { - var row/eax: int <- copy row1 - { - compare row, row2 - break-if->= - move-cursor 0, row, col - print-code-point 0, 0x2502 - row <- increment - loop - } -} diff --git a/prototypes/tile/2.mu b/prototypes/tile/2.mu deleted file mode 100644 index 6339d61e..00000000 --- a/prototypes/tile/2.mu +++ /dev/null @@ -1,84 +0,0 @@ -# load test: animate a whole lot of text -# -# Requires a large file called "x" containing just ascii characters. One way -# to generate it: -# cat /dev/urandom |base64 - |head -n 1000 > x -# then merge pairs of lines. -# -# This prototype assumes it's in a window 185 characters wide. - -fn main -> exit-status/ebx: int { - var num-lines/ecx: int <- copy 0x10 - clear-screen 0 - # open a file - var f: (addr buffered-file) - { - var f-handle: (handle buffered-file) - var f-in/eax: (addr handle buffered-file) <- address f-handle - open "x", 0, f-in # for reading - var f-out/eax: (addr buffered-file) <- lookup f-handle - copy-to f, f-out - } - # main loop - var row/eax: int <- copy 1 - { - compare row, 0x10 # 16 - break-if-> - render f, row, num-lines - row <- increment -#? sleep 0 0x5f5e100 # 100ms - loop - } - # wait for a key - { - enable-keyboard-immediate-mode - var dummy/eax: grapheme <- read-key-from-real-keyboard - enable-keyboard-type-mode - } - # clean up - clear-screen 0 - exit-status <- copy 0 -} - -fn render f: (addr buffered-file), start-row: int, num-rows: int { - var num-cols/ecx: int <- copy 0xb9 # 185 - # if necessary, clear the row above -$render:clear-loop: { - compare start-row, 1 - break-if-<= - decrement start-row - var col/eax: int <- copy 1 - move-cursor 0, start-row, col - { - compare col, num-cols - break-if-> - print-string 0, " " - col <- increment - loop - } - increment start-row - } - # render rest of screen below - var row/edx: int <- copy start-row - var col/ebx: int <- copy 1 - move-cursor 0, row, col -$render:render-loop: { - compare row, num-rows - break-if->= - var c/eax: byte <- read-byte-buffered f - compare c, 0xffffffff # EOF marker - break-if-= - compare c, 0xa # newline - { - break-if-!= - row <- increment - col <- copy 0 - move-cursor 0, row, col - loop $render:render-loop - } - var g/eax: grapheme <- copy c - print-grapheme 0, g - col <- increment - loop - } -} diff --git a/prototypes/tile/3.mu b/prototypes/tile/3.mu deleted file mode 100644 index 94c9cc8c..00000000 --- a/prototypes/tile/3.mu +++ /dev/null @@ -1,76 +0,0 @@ -# benchmark: how fast can we print characters to screen? -# -# Requires a large file called "x" containing just ascii characters. One way -# to generate it: -# cat /dev/urandom |base64 - |head -n 10000 > x -# then merge pairs of lines. - -fn main -> exit-status/ebx: int { - var num-lines/ecx: int <- copy 0x64 # 100 - clear-screen 0 - # open a file - var f: (addr buffered-file) - { - var f-handle: (handle buffered-file) - var f-in/eax: (addr handle buffered-file) <- address f-handle - open "x", 0, f-in # for reading - var f-out/eax: (addr buffered-file) <- lookup f-handle - copy-to f, f-out - } - # initial time - var t1_/eax: int <- time - var t1/edx: int <- copy t1_ - # main loop - var iter/eax: int <- copy 1 - { - compare iter, 0x640 # 1600 - break-if-> - render f, num-lines - iter <- increment - loop - } - # final time - var t2_/eax: int <- time - var t2/ebx: int <- copy t2_ - # time taken - var t3/esi: int <- copy t2 - t3 <- subtract t1 - # clean up - clear-screen 0 - # results - print-int32-hex 0, t1 - print-string 0, "\n" - print-int32-hex 0, t2 - print-string 0, "\n" - print-int32-hex 0, t3 - print-string 0, "\n" - # - exit-status <- copy 0 -} - -fn render f: (addr buffered-file), num-rows: int { - var num-cols/ecx: int <- copy 0x64 # 100 - # render screen - var row/edx: int <- copy 1 - var col/ebx: int <- copy 1 - move-cursor 0, row, col -$render:render-loop: { - compare row, num-rows - break-if->= - var c/eax: byte <- read-byte-buffered f - compare c, 0xffffffff # EOF marker - break-if-= - compare c, 0xa # newline - { - break-if-!= - row <- increment - col <- copy 0 - move-cursor 0, row, col - loop $render:render-loop - } - var g/eax: grapheme <- copy c - print-grapheme 0, g - col <- increment - loop - } -} diff --git a/prototypes/tile/4.mu b/prototypes/tile/4.mu deleted file mode 100644 index 6e2a57b7..00000000 --- a/prototypes/tile/4.mu +++ /dev/null @@ -1,56 +0,0 @@ -# animate a large box -# -# To run (on Linux and x86): -# $ git clone https://github.com/akkartik/mu -# $ cd mu -# $ ./translate_mu prototypes/tile/4.mu -# $ ./a.elf - -fn main -> exit-status/ebx: int { - clear-screen 0 - enable-keyboard-immediate-mode - var dummy/eax: grapheme <- read-key-from-real-keyboard - draw-box 5, 5, 0x23, 0x23 # 35, 35 - sleep 0 0x5f5e100 # 100ms - sleep 0 0x5f5e100 # 100ms - draw-box 5, 5, 0x23, 0x69 # 35, 105 - sleep 0 0x5f5e100 # 100ms - sleep 0 0x5f5e100 # 100ms - draw-box 5, 5, 0x23, 0xaf # 35, 175 - var dummy/eax: grapheme <- read-key-from-real-keyboard - enable-keyboard-type-mode - clear-screen 0 - exit-status <- copy 0 -} - -fn draw-box row1: int, col1: int, row2: int, col2: int { - clear-screen 0 - draw-horizontal-line row1, col1, col2 - draw-vertical-line row1, row2, col1 - draw-horizontal-line row2, col1, col2 - draw-vertical-line row1, row2, col2 -} - -fn draw-horizontal-line row: int, col1: int, col2: int { - var col/eax: int <- copy col1 - move-cursor 0, row, col - { - compare col, col2 - break-if->= - print-string 0, "-" - col <- increment - loop - } -} - -fn draw-vertical-line row1: int, row2: int, col: int { - var row/eax: int <- copy row1 - { - compare row, row2 - break-if->= - move-cursor 0, row, col - print-string 0, "|" - row <- increment - loop - } -} diff --git a/prototypes/tile/5.mu b/prototypes/tile/5.mu deleted file mode 100644 index 58d94636..00000000 --- a/prototypes/tile/5.mu +++ /dev/null @@ -1,145 +0,0 @@ -# rendering a tree with a single child -# -# To run (on Linux and x86): -# $ git clone https://github.com/akkartik/mu -# $ cd mu -# $ ./translate_mu prototypes/tile/5.mu -# $ ./a.elf -# -# You should see a single rectangle representing a singleton tree node. -# Press a key. You should see the tree grow a single child. -# It seems useful as a visual idiom to represent nodes with a single child as -# slightly larger than the child. -# Once we get to multiple children we'll start tiling more regularly. - -type cell { - val: int # single chars only for now - parent: (handle cell) - first-child: (handle cell) - next-sibling: (handle cell) - prev-sibling: (handle cell) -} - -fn main -> exit-status/ebx: int { - var root-handle: (handle cell) - var root/esi: (addr handle cell) <- address root-handle - allocate root - var cursor/edi: (addr handle cell) <- copy root - enable-keyboard-immediate-mode - var root-addr/eax: (addr cell) <- lookup *root - render root-addr -$main:loop: { - # process key - { - var c/eax: grapheme <- read-key-from-real-keyboard - compare c, 4 # ctrl-d - break-if-= $main:loop - process c, root, cursor - } - # render tree - root-addr <- lookup root-handle - render root-addr - loop - } - clear-screen 0 - enable-keyboard-type-mode - exit-status <- copy 0 -} - -####################################################### -# Tree mutations -####################################################### - -fn process c: grapheme, root: (addr handle cell), cursor: (addr handle cell) { - var c1/eax: (addr handle cell) <- copy cursor - var c2/eax: (addr cell) <- lookup *c1 - create-child c2 -} - -fn create-child node: (addr cell) { - var n/ecx: (addr cell) <- copy node - var first-child/esi: (addr handle cell) <- get n, first-child - allocate first-child -} - -####################################################### -# Tree drawing -####################################################### - -fn render root: (addr cell) { - clear-screen 0 - var depth/eax: int <- tree-depth root - var viewport-width/ecx: int <- copy 0x64 # col2 - viewport-width <- subtract 5 # col1 - var column-width/eax: int <- try-divide viewport-width, depth - render-tree root, column-width, 5, 5, 0x20, 0x64 -} - -fn render-tree c: (addr cell), column-width: int, row-min: int, col-min: int, row-max: int, col-max: int { - var root-max/ecx: int <- copy col-min - root-max <- add column-width - draw-box row-min, col-min, row-max, root-max - var c2/eax: (addr cell) <- copy c - var child/eax: (addr handle cell) <- get c2, first-child - var child-addr/eax: (addr cell) <- lookup *child - { - compare child-addr, 0 - break-if-= - increment row-min - decrement row-max - render-tree child-addr, column-width, row-min, root-max, row-max, col-max - } -} - -fn tree-depth node-on-stack: (addr cell) -> result/eax: int { - var tmp-result/edi: int <- copy 0 - var node/eax: (addr cell) <- copy node-on-stack - var child/ecx: (addr handle cell) <- get node, first-child - var child-addr/eax: (addr cell) <- lookup *child - { - compare child-addr, 0 - break-if-= - { - var tmp/eax: int <- tree-depth child-addr - compare tmp, tmp-result - break-if-<= - tmp-result <- copy tmp - } - child <- get child-addr, next-sibling - child-addr <- lookup *child - loop - } - result <- copy tmp-result - result <- increment -} - -fn draw-box row1: int, col1: int, row2: int, col2: int { - draw-horizontal-line row1, col1, col2 - draw-vertical-line row1, row2, col1 - draw-horizontal-line row2, col1, col2 - draw-vertical-line row1, row2, col2 -} - -fn draw-horizontal-line row: int, col1: int, col2: int { - var col/eax: int <- copy col1 - move-cursor 0, row, col - { - compare col, col2 - break-if->= - print-string 0, "-" - col <- increment - loop - } -} - -fn draw-vertical-line row1: int, row2: int, col: int { - var row/eax: int <- copy row1 - { - compare row, row2 - break-if->= - move-cursor 0, row, col - print-string 0, "|" - row <- increment - loop - } -} diff --git a/prototypes/tile/6.mu b/prototypes/tile/6.mu deleted file mode 100644 index be95dead..00000000 --- a/prototypes/tile/6.mu +++ /dev/null @@ -1,184 +0,0 @@ -# rendering trees of arbitrary depth, with each node having a single child -# -# To run (on Linux and x86): -# $ git clone https://github.com/akkartik/mu -# $ cd mu -# $ ./translate_mu prototypes/tile/6.mu -# $ ./a.elf -# -# Every time you press a key, a deeper tree is rendered. Press ctrl-c to exit. -# It seems useful as a visual idiom to represent nodes with a single child as -# slightly larger than the child. -# Once we get to multiple children we'll start tiling more regularly. - -# We also have tests now: -# $ ./a.elf test -fn main args-on-stack: (addr array addr array byte) -> exit-status/ebx: int { - var args/eax: (addr array addr array byte) <- copy args-on-stack - var tmp/ecx: int <- length args - $main-body: { - # if (len(args) > 1 && args[1] == "test") run-tests() - compare tmp, 1 - { - break-if-<= - # if (args[1] == "test") run-tests() - var tmp2/ecx: (addr addr array byte) <- index args, 1 - var tmp3/eax: boolean <- string-equal? *tmp2, "test" - compare tmp3, 0 - { - break-if-= - run-tests - exit-status <- copy 0 # TODO: get at Num-test-failures somehow - } - break $main-body - } - # otherwise operate interactively - exit-status <- interactive - } -} - -# - interactive loop - -type cell { - val: int # single chars only for now - parent: (handle cell) - first-child: (handle cell) - next-sibling: (handle cell) - prev-sibling: (handle cell) -} - -fn interactive -> exit-status/ebx: int { - var root-handle: (handle cell) - var root/esi: (addr handle cell) <- address root-handle - allocate root - var cursor/edi: (addr handle cell) <- copy root - enable-keyboard-immediate-mode - var root-addr/eax: (addr cell) <- lookup *root - render root-addr -$main:loop: { - # process key - { - var c/eax: grapheme <- read-key-from-real-keyboard - compare c, 4 # ctrl-d - break-if-= $main:loop - process c, root, cursor - } - # render tree - root-addr <- lookup root-handle - render root-addr - loop - } - clear-screen 0 - enable-keyboard-type-mode - exit-status <- copy 0 -} - -####################################################### -# Tree mutations -####################################################### - -fn process c: grapheme, root: (addr handle cell), cursor: (addr handle cell) { - # increase depth by 1 - var c1/ecx: (addr handle cell) <- copy cursor - var c2/eax: (addr cell) <- lookup *c1 - var c3/edx: (addr cell) <- copy c2 - { - print-string 0, "iter\n" - var tmp/ebx: (addr handle cell) <- get c3, first-child - var tmp2/eax: (addr cell) <- lookup *tmp - compare tmp2, 0 - break-if-= - c1 <- copy tmp - c3 <- copy tmp2 - loop - } - create-child c3 -} - -fn create-child node: (addr cell) { - var n/ecx: (addr cell) <- copy node - var first-child/esi: (addr handle cell) <- get n, first-child - allocate first-child -} - -####################################################### -# Tree drawing -####################################################### - -fn render root: (addr cell) { - clear-screen 0 - var depth/eax: int <- tree-depth root - var viewport-width/ecx: int <- copy 0x64 # col2 - viewport-width <- subtract 5 # col1 - var column-width/eax: int <- try-divide viewport-width, depth - render-tree root, column-width, 5, 5, 0x20, 0x64 -} - -fn render-tree c: (addr cell), column-width: int, row-min: int, col-min: int, row-max: int, col-max: int { - var root-max/ecx: int <- copy col-min - root-max <- add column-width - draw-box row-min, col-min, row-max, root-max - var c2/eax: (addr cell) <- copy c - var child/eax: (addr handle cell) <- get c2, first-child - var child-addr/eax: (addr cell) <- lookup *child - { - compare child-addr, 0 - break-if-= - increment row-min - decrement row-max - render-tree child-addr, column-width, row-min, root-max, row-max, col-max - } -} - -fn tree-depth node-on-stack: (addr cell) -> result/eax: int { - var tmp-result/edi: int <- copy 0 - var node/eax: (addr cell) <- copy node-on-stack - var child/ecx: (addr handle cell) <- get node, first-child - var child-addr/eax: (addr cell) <- lookup *child - { - compare child-addr, 0 - break-if-= - { - var tmp/eax: int <- tree-depth child-addr - compare tmp, tmp-result - break-if-<= - tmp-result <- copy tmp - } - child <- get child-addr, next-sibling - child-addr <- lookup *child - loop - } - result <- copy tmp-result - result <- increment -} - -fn draw-box row1: int, col1: int, row2: int, col2: int { - draw-horizontal-line row1, col1, col2 - draw-vertical-line row1, row2, col1 - draw-horizontal-line row2, col1, col2 - draw-vertical-line row1, row2, col2 -} - -fn draw-horizontal-line row: int, col1: int, col2: int { - var col/eax: int <- copy col1 - move-cursor 0, row, col - { - compare col, col2 - break-if->= - print-string 0, "-" - col <- increment - loop - } -} - -fn draw-vertical-line row1: int, row2: int, col: int { - var row/eax: int <- copy row1 - { - compare row, row2 - break-if->= - move-cursor 0, row, col - print-string 0, "|" - row <- increment - loop - } -} diff --git a/prototypes/tile/7.mu b/prototypes/tile/7.mu deleted file mode 100644 index e2e7aff0..00000000 --- a/prototypes/tile/7.mu +++ /dev/null @@ -1,198 +0,0 @@ -# rendering trees of arbitrary depth -# -# To run (on Linux and x86): -# $ git clone https://github.com/akkartik/mu -# $ cd mu -# $ ./translate_mu prototypes/tile/7.mu -# $ ./a.elf -# -# Every time you press a key, the root node gains another child. Press ctrl-c -# to exit. -# -# The rendering is still simple-minded. Children and siblings render in the -# same direction. And this interacts poorly with the depth computation, which -# only considers children. So unlike the previous prototype which splits the -# same screen width between more and more boxes, here the boxes grow to the -# right. - -# To run unit tests: -# $ ./a.elf test -fn main args-on-stack: (addr array addr array byte) -> exit-status/ebx: int { - var args/eax: (addr array addr array byte) <- copy args-on-stack - var tmp/ecx: int <- length args - $main-body: { - # if (len(args) > 1 && args[1] == "test") run-tests() - compare tmp, 1 - { - break-if-<= - # if (args[1] == "test") run-tests() - var tmp2/ecx: (addr addr array byte) <- index args, 1 - var tmp3/eax: boolean <- string-equal? *tmp2, "test" - compare tmp3, 0 - { - break-if-= - run-tests - exit-status <- copy 0 # TODO: get at Num-test-failures somehow - } - break $main-body - } - # otherwise operate interactively - exit-status <- interactive - } -} - -# - interactive loop - -type cell { - val: int # single chars only for now - parent: (handle cell) - first-child: (handle cell) - next-sibling: (handle cell) - prev-sibling: (handle cell) -} - -fn interactive -> exit-status/ebx: int { - var root-handle: (handle cell) - var root/esi: (addr handle cell) <- address root-handle - allocate root - var cursor/edi: (addr handle cell) <- copy root - enable-keyboard-immediate-mode - var root-addr/eax: (addr cell) <- lookup *root - render root-addr -$main:loop: { - # process key - { - var c/eax: grapheme <- read-key-from-real-keyboard - compare c, 4 # ctrl-d - break-if-= $main:loop - process c, root, cursor - } - # render tree - root-addr <- lookup root-handle - render root-addr - loop - } - clear-screen 0 - enable-keyboard-type-mode - exit-status <- copy 0 -} - -####################################################### -# Tree mutations -####################################################### - -fn process c: grapheme, root: (addr handle cell), cursor: (addr handle cell) { - var c1/ecx: (addr handle cell) <- copy cursor - var c2/eax: (addr cell) <- lookup *c1 - create-child c2 -} - -fn create-child node: (addr cell) { - var n/ecx: (addr cell) <- copy node - var child/esi: (addr handle cell) <- get n, first-child - { - var tmp/eax: (addr cell) <- lookup *child - compare tmp, 0 - break-if-= - child <- get tmp, next-sibling - loop - } - allocate child -} - -####################################################### -# Tree drawing -####################################################### - -fn render root: (addr cell) { - clear-screen 0 - var depth/eax: int <- tree-depth root - var viewport-width/ecx: int <- copy 0x64 # col2 - viewport-width <- subtract 5 # col1 - var column-width/eax: int <- try-divide viewport-width, depth - render-tree root, column-width, 5, 5, 0x20, 0x64 -} - -fn render-tree c: (addr cell), column-width: int, row-min: int, col-min: int, row-max: int, col-max: int { - var root-max/ecx: int <- copy col-min - root-max <- add column-width - draw-box row-min, col-min, row-max, root-max - var c2/eax: (addr cell) <- copy c - # render child if possible - { - var child/edx: (addr handle cell) <- get c2, first-child - var child-addr/eax: (addr cell) <- lookup *child - { - compare child-addr, 0 - break-if-= - increment row-min - decrement row-max - render-tree child-addr, column-width, row-min, root-max, row-max, col-max - } - } - # otherwise render sibling if possible (in the same column) - { - var sib/edx: (addr handle cell) <- get c2, next-sibling - var sib-addr/eax: (addr cell) <- lookup *sib - { - compare sib-addr, 0 - break-if-= - increment row-min - decrement row-max - render-tree sib-addr, column-width, row-min, root-max, row-max, col-max - } - } -} - -fn tree-depth node-on-stack: (addr cell) -> result/eax: int { - var tmp-result/edi: int <- copy 0 - var node/eax: (addr cell) <- copy node-on-stack - var child/ecx: (addr handle cell) <- get node, first-child - var child-addr/eax: (addr cell) <- lookup *child - { - compare child-addr, 0 - break-if-= - { - var tmp/eax: int <- tree-depth child-addr - compare tmp, tmp-result - break-if-<= - tmp-result <- copy tmp - } - child <- get child-addr, next-sibling - child-addr <- lookup *child - loop - } - result <- copy tmp-result - result <- increment -} - -fn draw-box row1: int, col1: int, row2: int, col2: int { - draw-horizontal-line row1, col1, col2 - draw-vertical-line row1, row2, col1 - draw-horizontal-line row2, col1, col2 - draw-vertical-line row1, row2, col2 -} - -fn draw-horizontal-line row: int, col1: int, col2: int { - var col/eax: int <- copy col1 - move-cursor 0, row, col - { - compare col, col2 - break-if->= - print-string 0, "-" - col <- increment - loop - } -} - -fn draw-vertical-line row1: int, row2: int, col: int { - var row/eax: int <- copy row1 - { - compare row, row2 - break-if->= - move-cursor 0, row, col - print-string 0, "|" - row <- increment - loop - } -} diff --git a/prototypes/tile/8.mu b/prototypes/tile/8.mu deleted file mode 100644 index 526df803..00000000 --- a/prototypes/tile/8.mu +++ /dev/null @@ -1,228 +0,0 @@ -# rendering trees of arbitrary depth -# -# To run (on Linux and x86): -# $ git clone https://github.com/akkartik/mu -# $ cd mu -# $ ./translate_mu prototypes/tile/8.mu -# $ ./a.elf -# -# Every time you press a key, the root node gains another child. Press ctrl-c -# to exit. -# -# The rendering is still simple-minded. Children and siblings render in the -# same direction. And this interacts poorly with the depth computation, which -# only considers children. So unlike the previous prototype which splits the -# same screen width between more and more boxes, here the boxes grow to the -# right. - -# To run unit tests: -# $ ./a.elf test -fn main args-on-stack: (addr array addr array byte) -> exit-status/ebx: int { - var args/eax: (addr array addr array byte) <- copy args-on-stack - var tmp/ecx: int <- length args - $main-body: { - # if (len(args) > 1 && args[1] == "test") run-tests() - compare tmp, 1 - { - break-if-<= - # if (args[1] == "test") run-tests() - var tmp2/ecx: (addr addr array byte) <- index args, 1 - var tmp3/eax: boolean <- string-equal? *tmp2, "test" - compare tmp3, 0 - { - break-if-= - run-tests - exit-status <- copy 0 # TODO: get at Num-test-failures somehow - } - break $main-body - } - # otherwise operate interactively - exit-status <- interactive - } -} - -# - interactive loop - -type cell { - val: int # single chars only for now - parent: (handle cell) - first-child: (handle cell) - next-sibling: (handle cell) - prev-sibling: (handle cell) -} - -fn interactive -> exit-status/ebx: int { - var root-handle: (handle cell) - var root/esi: (addr handle cell) <- address root-handle - allocate root - var cursor/edi: (addr handle cell) <- copy root - enable-keyboard-immediate-mode - var root-addr/eax: (addr cell) <- lookup *root - render root-addr -$main:loop: { - # process key - { - var c/eax: grapheme <- read-key-from-real-keyboard - compare c, 4 # ctrl-d - break-if-= $main:loop - process c, root, cursor - } - # render tree - root-addr <- lookup root-handle - render root-addr - loop - } - clear-screen 0 - enable-keyboard-type-mode - exit-status <- copy 0 -} - -####################################################### -# Tree mutations -####################################################### - -fn process c: grapheme, root: (addr handle cell), cursor: (addr handle cell) { - var c1/ecx: (addr handle cell) <- copy cursor - var c2/eax: (addr cell) <- lookup *c1 - create-child c2 -} - -fn create-child node: (addr cell) { - var n/ecx: (addr cell) <- copy node - var child/esi: (addr handle cell) <- get n, first-child - { - var tmp/eax: (addr cell) <- lookup *child - compare tmp, 0 - break-if-= - child <- get tmp, next-sibling - loop - } - allocate child -} - -####################################################### -# Tree drawing -####################################################### - -fn render root: (addr cell) { - clear-screen 0 - var depth/eax: int <- tree-depth root - var viewport-width/ecx: int <- copy 0x64 # col2 - viewport-width <- subtract 5 # col1 - var column-width/eax: int <- try-divide viewport-width, depth - render-tree root, column-width, 5, 5, 0x20, 0x64 -} - -fn render-tree c: (addr cell), column-width: int, row-min: int, col-min: int, row-max: int, col-max: int { -$render-tree:body: { - var root-max/ecx: int <- copy col-min - root-max <- add column-width - draw-box row-min, col-min, row-max, root-max - var c2/edx: (addr cell) <- copy c - # if single child, render it (slightly shorter than the parent) - var nchild/eax: int <- num-children c - { - compare nchild, 1 - break-if-> - var child/edx: (addr handle cell) <- get c2, first-child - var child-addr/eax: (addr cell) <- lookup *child - { - compare child-addr, 0 - break-if-= - increment row-min - decrement row-max - render-tree child-addr, column-width, row-min, root-max, row-max, col-max - } - break $render-tree:body - } - # otherwise divide vertical space up equally among children - var column-height/ebx: int <- copy row-max - column-height <- subtract row-min - var child-height/eax: int <- try-divide column-height, nchild - var child-height2/ebx: int <- copy child-height - var curr/edx: (addr handle cell) <- get c2, first-child - var curr-addr/eax: (addr cell) <- lookup *curr - var rmin/esi: int <- copy row-min - var rmax/edi: int <- copy row-min - rmax <- add child-height2 - { - compare curr-addr, 0 - break-if-= - render-tree curr-addr, column-width, rmin, root-max, rmax, col-max - curr <- get curr-addr, next-sibling - curr-addr <- lookup *curr - rmin <- add child-height2 - rmax <- add child-height2 - loop - } -} -} - -fn num-children node-on-stack: (addr cell) -> result/eax: int { - var tmp-result/edi: int <- copy 0 - var node/eax: (addr cell) <- copy node-on-stack - var child/ecx: (addr handle cell) <- get node, first-child - var child-addr/eax: (addr cell) <- lookup *child - { - compare child-addr, 0 - break-if-= - tmp-result <- increment - child <- get child-addr, next-sibling - child-addr <- lookup *child - loop - } - result <- copy tmp-result -} - -fn tree-depth node-on-stack: (addr cell) -> result/eax: int { - var tmp-result/edi: int <- copy 0 - var node/eax: (addr cell) <- copy node-on-stack - var child/ecx: (addr handle cell) <- get node, first-child - var child-addr/eax: (addr cell) <- lookup *child - { - compare child-addr, 0 - break-if-= - { - var tmp/eax: int <- tree-depth child-addr - compare tmp, tmp-result - break-if-<= - tmp-result <- copy tmp - } - child <- get child-addr, next-sibling - child-addr <- lookup *child - loop - } - result <- copy tmp-result - result <- increment -} - -fn draw-box row1: int, col1: int, row2: int, col2: int { - draw-horizontal-line row1, col1, col2 - draw-vertical-line row1, row2, col1 - draw-horizontal-line row2, col1, col2 - draw-vertical-line row1, row2, col2 -} - -fn draw-horizontal-line row: int, col1: int, col2: int { - var col/eax: int <- copy col1 - move-cursor 0, row, col - { - compare col, col2 - break-if->= - print-string 0, "-" - col <- increment - loop - } -} - -fn draw-vertical-line row1: int, row2: int, col: int { - var row/eax: int <- copy row1 - { - compare row, row2 - break-if->= - move-cursor 0, row, col - print-string 0, "|" - row <- increment - loop - } -} diff --git a/prototypes/tile/9.mu b/prototypes/tile/9.mu deleted file mode 100644 index ab143e25..00000000 --- a/prototypes/tile/9.mu +++ /dev/null @@ -1,307 +0,0 @@ -# moving around within a tree, though movement isn't visible yet so we can't -# be sure it's working. -# -# To run (on Linux and x86): -# $ git clone https://github.com/akkartik/mu -# $ cd mu -# $ ./translate_mu prototypes/tile/9.mu -# $ ./a.elf -# -# Press 'c' to create new children for the root node. - -# To run unit tests: -# $ ./a.elf test -fn main args-on-stack: (addr array addr array byte) -> exit-status/ebx: int { - var args/eax: (addr array addr array byte) <- copy args-on-stack - var tmp/ecx: int <- length args - $main-body: { - # if (len(args) > 1 && args[1] == "test") run-tests() - compare tmp, 1 - { - break-if-<= - # if (args[1] == "test") run-tests() - var tmp2/ecx: (addr addr array byte) <- index args, 1 - var tmp3/eax: boolean <- string-equal? *tmp2, "test" - compare tmp3, 0 - { - break-if-= - run-tests - exit-status <- copy 0 # TODO: get at Num-test-failures somehow - } - break $main-body - } - # otherwise operate interactively - exit-status <- interactive - } -} - -# - interactive loop - -type cell { - val: int # single chars only for now - parent: (handle cell) - first-child: (handle cell) - next-sibling: (handle cell) - prev-sibling: (handle cell) -} - -fn interactive -> exit-status/ebx: int { - var root-handle: (handle cell) - var root/esi: (addr handle cell) <- address root-handle - allocate root - var cursor-handle: (handle cell) - var cursor/edi: (addr handle cell) <- address cursor-handle - copy-handle root-handle, cursor - enable-keyboard-immediate-mode - var _root-addr/eax: (addr cell) <- lookup *root - var root-addr/ecx: (addr cell) <- copy _root-addr - var cursor-addr/eax: (addr cell) <- lookup *cursor - render root-addr, cursor-addr -$main:loop: { - # process key - { - var c/eax: grapheme <- read-key-from-real-keyboard - compare c, 4 # ctrl-d - break-if-= $main:loop - process c, root, cursor - } - # render tree - var _root-addr/eax: (addr cell) <- lookup root-handle - root-addr <- copy _root-addr - var cursor-addr/eax: (addr cell) <- lookup *cursor - render root-addr, cursor-addr - loop - } - clear-screen 0 - enable-keyboard-type-mode - exit-status <- copy 0 -} - -####################################################### -# Tree mutations -####################################################### - -fn process c: grapheme, root: (addr handle cell), cursor: (addr handle cell) { -$process:body: { - # if c == 'h' move cursor to its parent if possible - { - compare c, 0x68 # 'h' - break-if-!= - move-to-parent cursor - } - # if c == 'l' move cursor to its first child if possible - { - compare c, 0x6c # 'l' - break-if-!= - move-to-child cursor - } - # if c == 'j' move cursor to its next sibling if possible - { - compare c, 0x6a # 'j' - break-if-!= - move-to-next-sibling cursor - } - # if c == 'k' move cursor to its prev sibling if possible - { - compare c, 0x6b # 'k' - break-if-!= - move-to-prev-sibling cursor - } - # if c == 'c' create a new child at the cursor - { - compare c, 0x63 # 'c' - break-if-!= - var cursor1/ecx: (addr handle cell) <- copy cursor - var cursor2/eax: (addr cell) <- lookup *cursor1 - create-child cursor2 - } -} -} - -fn move-to-parent cursor: (addr handle cell) { - var cursor2/eax: (addr handle cell) <- copy cursor - var cursor3/eax: (addr cell) <- lookup *cursor2 - var parent/ecx: (addr handle cell) <- get cursor3, parent - { - var tmp/eax: (addr cell) <- lookup *parent - compare tmp, 0 - break-if-= - copy-handle *parent, cursor - } -} - -fn move-to-child cursor: (addr handle cell) { - var cursor2/eax: (addr handle cell) <- copy cursor - var cursor3/eax: (addr cell) <- lookup *cursor2 - var child/ecx: (addr handle cell) <- get cursor3, first-child - { - var tmp/eax: (addr cell) <- lookup *child - compare tmp, 0 - break-if-= - copy-handle *child, cursor - } -} - -fn move-to-next-sibling cursor: (addr handle cell) { - var cursor2/eax: (addr handle cell) <- copy cursor - var cursor3/eax: (addr cell) <- lookup *cursor2 - var sib/ecx: (addr handle cell) <- get cursor3, next-sibling - { - var tmp/eax: (addr cell) <- lookup *sib - compare tmp, 0 - break-if-= - copy-handle *sib, cursor - } -} - -fn move-to-prev-sibling cursor: (addr handle cell) { - var cursor2/eax: (addr handle cell) <- copy cursor - var cursor3/eax: (addr cell) <- lookup *cursor2 - var sib/ecx: (addr handle cell) <- get cursor3, prev-sibling - { - var tmp/eax: (addr cell) <- lookup *sib - compare tmp, 0 - break-if-= - copy-handle *sib, cursor - } -} - -fn create-child node: (addr cell) { - var n/ecx: (addr cell) <- copy node - var child/esi: (addr handle cell) <- get n, first-child - { - var tmp/eax: (addr cell) <- lookup *child - compare tmp, 0 - break-if-= - child <- get tmp, next-sibling - loop - } - allocate child -} - -####################################################### -# Tree drawing -####################################################### - -fn render root: (addr cell), cursor: (addr cell) { - clear-screen 0 - var depth/eax: int <- tree-depth root - var viewport-width/ecx: int <- copy 0x64 # col2 - viewport-width <- subtract 5 # col1 - var column-width/eax: int <- try-divide viewport-width, depth - render-tree root, column-width, 5, 5, 0x20, 0x64, cursor -} - -fn render-tree c: (addr cell), column-width: int, row-min: int, col-min: int, row-max: int, col-max: int, cursor: (addr cell) { -$render-tree:body: { - var root-max/ecx: int <- copy col-min - root-max <- add column-width - draw-box row-min, col-min, row-max, root-max - var c2/edx: (addr cell) <- copy c - # if single child, render it (slightly shorter than the parent) - var nchild/eax: int <- num-children c - { - compare nchild, 1 - break-if-> - var child/edx: (addr handle cell) <- get c2, first-child - var child-addr/eax: (addr cell) <- lookup *child - { - compare child-addr, 0 - break-if-= - increment row-min - decrement row-max - render-tree child-addr, column-width, row-min, root-max, row-max, col-max, cursor - } - break $render-tree:body - } - # otherwise divide vertical space up equally among children - var column-height/ebx: int <- copy row-max - column-height <- subtract row-min - var child-height/eax: int <- try-divide column-height, nchild - var child-height2/ebx: int <- copy child-height - var curr/edx: (addr handle cell) <- get c2, first-child - var curr-addr/eax: (addr cell) <- lookup *curr - var rmin/esi: int <- copy row-min - var rmax/edi: int <- copy row-min - rmax <- add child-height2 - { - compare curr-addr, 0 - break-if-= - render-tree curr-addr, column-width, rmin, root-max, rmax, col-max, cursor - curr <- get curr-addr, next-sibling - curr-addr <- lookup *curr - rmin <- add child-height2 - rmax <- add child-height2 - loop - } -} -} - -fn num-children node-on-stack: (addr cell) -> result/eax: int { - var tmp-result/edi: int <- copy 0 - var node/eax: (addr cell) <- copy node-on-stack - var child/ecx: (addr handle cell) <- get node, first-child - var child-addr/eax: (addr cell) <- lookup *child - { - compare child-addr, 0 - break-if-= - tmp-result <- increment - child <- get child-addr, next-sibling - child-addr <- lookup *child - loop - } - result <- copy tmp-result -} - -fn tree-depth node-on-stack: (addr cell) -> result/eax: int { - var tmp-result/edi: int <- copy 0 - var node/eax: (addr cell) <- copy node-on-stack - var child/ecx: (addr handle cell) <- get node, first-child - var child-addr/eax: (addr cell) <- lookup *child - { - compare child-addr, 0 - break-if-= - { - var tmp/eax: int <- tree-depth child-addr - compare tmp, tmp-result - break-if-<= - tmp-result <- copy tmp - } - child <- get child-addr, next-sibling - child-addr <- lookup *child - loop - } - result <- copy tmp-result - result <- increment -} - -fn draw-box row1: int, col1: int, row2: int, col2: int { - draw-horizontal-line row1, col1, col2 - draw-vertical-line row1, row2, col1 - draw-horizontal-line row2, col1, col2 - draw-vertical-line row1, row2, col2 -} - -fn draw-horizontal-line row: int, col1: int, col2: int { - var col/eax: int <- copy col1 - move-cursor 0, row, col - { - compare col, col2 - break-if->= - print-string 0, "-" - col <- increment - loop - } -} - -fn draw-vertical-line row1: int, row2: int, col: int { - var row/eax: int <- copy row1 - { - compare row, row2 - break-if->= - move-cursor 0, row, col - print-string 0, "|" - row <- increment - loop - } -} diff --git a/prototypes/tile/README.md b/prototypes/tile/README.md deleted file mode 100644 index 2fbe3b6c..00000000 --- a/prototypes/tile/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Drawing tiles on screen - -This directory contains a series of prototypes. For more details on the -organization of this directory and building, see [the parent directory](..). - -Once you've followed the instructions for building a prototype, run most of -them like this: - -``` -$ ./a.elf -``` - -See the code of individual prototypes for further instructions. -- cgit 1.4.1-2-gfad0