about summary refs log tree commit diff stats
path: root/shell/sandbox.mu
diff options
context:
space:
mode:
Diffstat (limited to 'shell/sandbox.mu')
-rw-r--r--shell/sandbox.mu263
1 files changed, 263 insertions, 0 deletions
diff --git a/shell/sandbox.mu b/shell/sandbox.mu
new file mode 100644
index 00000000..49c2a5f9
--- /dev/null
+++ b/shell/sandbox.mu
@@ -0,0 +1,263 @@
+type sandbox {
+  data: (handle gap-buffer)
+  value: (handle stream byte)
+  trace: (handle trace)
+  cursor-in-trace?: boolean
+}
+
+fn initialize-sandbox _self: (addr sandbox) {
+  var self/esi: (addr sandbox) <- copy _self
+  var data-ah/eax: (addr handle gap-buffer) <- get self, data
+  allocate data-ah
+  var data/eax: (addr gap-buffer) <- lookup *data-ah
+  initialize-gap-buffer data, 0x1000/4KB
+  var value-ah/eax: (addr handle stream byte) <- get self, value
+  populate-stream value-ah, 0x1000/4KB
+  var trace-ah/eax: (addr handle trace) <- get self, trace
+  allocate trace-ah
+  var trace/eax: (addr trace) <- lookup *trace-ah
+  initialize-trace trace, 0x1000/lines, 0x80/visible-lines
+}
+
+## some helpers for tests
+
+fn initialize-sandbox-with _self: (addr sandbox), s: (addr array byte) {
+  var self/esi: (addr sandbox) <- copy _self
+  var data-ah/eax: (addr handle gap-buffer) <- get self, data
+  allocate data-ah
+  var data/eax: (addr gap-buffer) <- lookup *data-ah
+  initialize-gap-buffer-with data, s
+}
+
+fn allocate-sandbox-with _out: (addr handle sandbox), s: (addr array byte) {
+  var out/eax: (addr handle sandbox) <- copy _out
+  allocate out
+  var out-addr/eax: (addr sandbox) <- lookup *out
+  initialize-sandbox-with out-addr, s
+}
+
+##
+
+fn render-sandbox screen: (addr screen), _self: (addr sandbox), xmin: int, ymin: int, xmax: int, ymax: int {
+  clear-screen screen
+  var self/esi: (addr sandbox) <- copy _self
+  # data
+  var data-ah/eax: (addr handle gap-buffer) <- get self, data
+  var _data/eax: (addr gap-buffer) <- lookup *data-ah
+  var data/edx: (addr gap-buffer) <- copy _data
+  var x/eax: int <- copy xmin
+  var y/ecx: int <- copy ymin
+  var cursor-in-sandbox?/ebx: boolean <- copy 0/false
+  {
+    var cursor-in-trace?/eax: (addr boolean) <- get self, cursor-in-trace?
+    compare *cursor-in-trace?, 0/false
+    break-if-!=
+    cursor-in-sandbox? <- copy 1/true
+  }
+  x, y <- render-gap-buffer-wrapping-right-then-down screen, data, x, y, xmax, ymax, cursor-in-sandbox?
+  y <- increment
+  # trace
+  var trace-ah/eax: (addr handle trace) <- get self, trace
+  var _trace/eax: (addr trace) <- lookup *trace-ah
+  var trace/edx: (addr trace) <- copy _trace
+  var cursor-in-trace?/eax: (addr boolean) <- get self, cursor-in-trace?
+  y <- render-trace screen, trace, xmin, y, xmax, ymax, *cursor-in-trace?
+  # value
+  $render-sandbox:value: {
+    var value-ah/eax: (addr handle stream byte) <- get self, value
+    var _value/eax: (addr stream byte) <- lookup *value-ah
+    var value/esi: (addr stream byte) <- copy _value
+    rewind-stream value
+    var done?/eax: boolean <- stream-empty? value
+    compare done?, 0/false
+    break-if-!=
+    var x/eax: int <- copy 0
+    x, y <- draw-text-wrapping-right-then-down screen, "=> ", xmin, y, xmax, ymax, xmin, y, 7/fg, 0/bg
+    var x2/edx: int <- copy x
+    var dummy/eax: int <- draw-stream-rightward screen, value, x2, xmax, y, 7/fg=grey, 0/bg
+  }
+  # render menu
+  var cursor-in-trace?/eax: (addr boolean) <- get self, cursor-in-trace?
+  compare *cursor-in-trace?, 0/false
+  {
+    break-if-=
+    render-trace-menu screen
+    return
+  }
+  render-sandbox-menu screen
+}
+
+fn render-sandbox-menu screen: (addr screen) {
+  var width/eax: int <- copy 0
+  var height/ecx: int <- copy 0
+  width, height <- screen-size screen
+  var y/ecx: int <- copy height
+  y <- decrement
+  set-cursor-position screen, 0/x, y
+  draw-text-rightward-from-cursor screen, " ctrl-s ", width, 0/fg, 7/bg=grey
+  draw-text-rightward-from-cursor screen, " run sandbox  ", width, 7/fg, 0/bg
+  draw-text-rightward-from-cursor screen, " ctrl-d ", width, 0/fg, 7/bg=grey
+  draw-text-rightward-from-cursor screen, " cursor down  ", width, 7/fg, 0/bg
+  draw-text-rightward-from-cursor screen, " ctrl-u ", width, 0/fg, 7/bg=grey
+  draw-text-rightward-from-cursor screen, " cursor up  ", width, 7/fg, 0/bg
+  draw-text-rightward-from-cursor screen, " tab ", width, 0/fg, 9/bg=blue
+  draw-text-rightward-from-cursor screen, " move to trace  ", width, 7/fg, 0/bg
+}
+
+fn edit-sandbox _self: (addr sandbox), key: byte {
+  var self/esi: (addr sandbox) <- copy _self
+  var g/edx: grapheme <- copy key
+  # running code
+  {
+    compare g, 0x12/ctrl-r
+    break-if-!=
+    # ctrl-r: run function outside sandbox
+    # required: fn (addr screen), (addr keyboard)
+    # Mu will pass in the real screen and keyboard.
+    return
+  }
+  {
+    compare g, 0x13/ctrl-s
+    break-if-!=
+    # ctrl-s: run sandbox(es)
+    var data-ah/eax: (addr handle gap-buffer) <- get self, data
+    var _data/eax: (addr gap-buffer) <- lookup *data-ah
+    var data/ecx: (addr gap-buffer) <- copy _data
+    var value-ah/eax: (addr handle stream byte) <- get self, value
+    var _value/eax: (addr stream byte) <- lookup *value-ah
+    var value/edx: (addr stream byte) <- copy _value
+    var trace-ah/eax: (addr handle trace) <- get self, trace
+    var trace/eax: (addr trace) <- lookup *trace-ah
+    clear-trace trace
+    run data, value, trace
+    return
+  }
+  # tab
+  var cursor-in-trace?/eax: (addr boolean) <- get self, cursor-in-trace?
+  {
+    compare g, 9/tab
+    break-if-!=
+    # if cursor in input, switch to trace
+    {
+      compare *cursor-in-trace?, 0/false
+      break-if-!=
+      copy-to *cursor-in-trace?, 1/true
+      return
+    }
+    # if cursor in trace, switch to input
+    copy-to *cursor-in-trace?, 0/false
+    return
+  }
+  # if cursor in trace, send cursor to trace
+  {
+    compare *cursor-in-trace?, 0/false
+    break-if-=
+    var trace-ah/eax: (addr handle trace) <- get self, trace
+    var trace/eax: (addr trace) <- lookup *trace-ah
+    edit-trace trace, g
+    return
+  }
+  # otherwise send cursor to input
+  var data-ah/eax: (addr handle gap-buffer) <- get self, data
+  var data/eax: (addr gap-buffer) <- lookup *data-ah
+  edit-gap-buffer data, g
+  return
+}
+
+fn run in: (addr gap-buffer), out: (addr stream byte), trace: (addr trace) {
+  var read-result-storage: (handle cell)
+  var read-result/esi: (addr handle cell) <- address read-result-storage
+  read-cell in, read-result, trace
+  var error?/eax: boolean <- has-errors? trace
+  {
+    compare error?, 0/false
+    break-if-=
+    return
+  }
+  # TODO: eval
+  clear-stream out
+  print-cell read-result, out, trace
+  mark-lines-dirty trace
+}
+
+fn test-run-integer {
+  var sandbox-storage: sandbox
+  var sandbox/esi: (addr sandbox) <- address sandbox-storage
+  initialize-sandbox sandbox
+  # type "1"
+  edit-sandbox sandbox, 0x31/1
+  # eval
+  edit-sandbox sandbox, 0x13/ctrl-s
+  # setup: screen
+  var screen-on-stack: screen
+  var screen/edi: (addr screen) <- address screen-on-stack
+  initialize-screen screen, 0x80/width, 0x10/height
+  #
+  render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height
+  check-screen-row screen, 0/y, "1    ", "F - test-run-integer/0"
+  check-screen-row screen, 1/y, "...  ", "F - test-run-integer/1"
+  check-screen-row screen, 2/y, "=> 1 ", "F - test-run-integer/2"
+}
+
+fn test-run-error-invalid-integer {
+  var sandbox-storage: sandbox
+  var sandbox/esi: (addr sandbox) <- address sandbox-storage
+  initialize-sandbox sandbox
+  # type "1a"
+  edit-sandbox sandbox, 0x31/1
+  edit-sandbox sandbox, 0x61/a
+  # eval
+  edit-sandbox sandbox, 0x13/ctrl-s
+  # setup: screen
+  var screen-on-stack: screen
+  var screen/edi: (addr screen) <- address screen-on-stack
+  initialize-screen screen, 0x80/width, 0x10/height
+  #
+  render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height
+  check-screen-row screen, 0/y, "1a             ", "F - test-run-error-invalid-integer/0"
+  check-screen-row screen, 1/y, "...            ", "F - test-run-error-invalid-integer/0"
+  check-screen-row screen, 2/y, "invalid number ", "F - test-run-error-invalid-integer/2"
+}
+
+fn test-run-move-cursor-into-trace {
+  var sandbox-storage: sandbox
+  var sandbox/esi: (addr sandbox) <- address sandbox-storage
+  initialize-sandbox sandbox
+  # type "12"
+  edit-sandbox sandbox, 0x31/1
+  edit-sandbox sandbox, 0x32/2
+  # eval
+  edit-sandbox sandbox, 0x13/ctrl-s
+  # setup: screen
+  var screen-on-stack: screen
+  var screen/edi: (addr screen) <- address screen-on-stack
+  initialize-screen screen, 0x80/width, 0x10/height
+  #
+  render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height
+  check-screen-row screen,                                  0/y, "12    ", "F - test-run-move-cursor-into-trace/pre-0"
+  check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "  |   ", "F - test-run-move-cursor-into-trace/pre-0/cursor"
+  check-screen-row screen,                                  1/y, "...   ", "F - test-run-move-cursor-into-trace/pre-1"
+  check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "      ", "F - test-run-move-cursor-into-trace/pre-1/cursor"
+  check-screen-row screen,                                  2/y, "=> 12 ", "F - test-run-move-cursor-into-trace/pre-2"
+  check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "      ", "F - test-run-move-cursor-into-trace/pre-2/cursor"
+  # move cursor into trace
+  edit-sandbox sandbox, 9/tab
+  #
+  render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height
+  check-screen-row screen,                                  0/y, "12    ", "F - test-run-move-cursor-into-trace/trace-0"
+  check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "      ", "F - test-run-move-cursor-into-trace/trace-0/cursor"
+  check-screen-row screen,                                  1/y, "...   ", "F - test-run-move-cursor-into-trace/trace-1"
+  check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "|||   ", "F - test-run-move-cursor-into-trace/trace-1/cursor"
+  check-screen-row screen,                                  2/y, "=> 12 ", "F - test-run-move-cursor-into-trace/trace-2"
+  check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "      ", "F - test-run-move-cursor-into-trace/trace-2/cursor"
+  # move cursor into input
+  edit-sandbox sandbox, 9/tab
+  #
+  render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height
+  check-screen-row screen,                                  0/y, "12    ", "F - test-run-move-cursor-into-trace/input-0"
+  check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "  |   ", "F - test-run-move-cursor-into-trace/input-0/cursor"
+  check-screen-row screen,                                  1/y, "...   ", "F - test-run-move-cursor-into-trace/input-1"
+  check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "      ", "F - test-run-move-cursor-into-trace/input-1/cursor"
+  check-screen-row screen,                                  2/y, "=> 12 ", "F - test-run-move-cursor-into-trace/input-2"
+  check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "      ", "F - test-run-move-cursor-into-trace/input-2/cursor"
+}