about summary refs log tree commit diff stats
path: root/shell/print.mu
diff options
context:
space:
mode:
Diffstat (limited to 'shell/print.mu')
-rw-r--r--shell/print.mu260
1 files changed, 260 insertions, 0 deletions
diff --git a/shell/print.mu b/shell/print.mu
new file mode 100644
index 00000000..32f5e725
--- /dev/null
+++ b/shell/print.mu
@@ -0,0 +1,260 @@
+fn print-cell _in: (addr handle cell), out: (addr stream byte), trace: (addr trace) {
+  trace-text trace, "print", "print-cell"
+  trace-lower trace
+  var in/eax: (addr handle cell) <- copy _in
+  var in-addr/eax: (addr cell) <- lookup *in
+  {
+    var is-nil?/eax: boolean <- is-nil? in-addr
+    compare is-nil?, 0/false
+    break-if-=
+    write out, "()"
+    trace-higher trace
+    return
+  }
+  var in-type/ecx: (addr int) <- get in-addr, type
+  compare *in-type, 0/pair
+  {
+    break-if-!=
+    print-list in-addr, out, trace
+    trace-higher trace
+    return
+  }
+  compare *in-type, 1/number
+  {
+    break-if-!=
+    print-number in-addr, out, trace
+    trace-higher trace
+    return
+  }
+  compare *in-type, 2/symbol
+  {
+    break-if-!=
+    print-symbol in-addr, out, trace
+    trace-higher trace
+    return
+  }
+}
+
+fn print-symbol _in: (addr cell), out: (addr stream byte), trace: (addr trace) {
+  trace-text trace, "print", "symbol"
+  var in/esi: (addr cell) <- copy _in
+  var data-ah/eax: (addr handle stream byte) <- get in, text-data
+  var _data/eax: (addr stream byte) <- lookup *data-ah
+  var data/esi: (addr stream byte) <- copy _data
+  rewind-stream data
+  write-stream out, data
+  # trace
+  rewind-stream data
+  var stream-storage: (stream byte 0x40)
+  var stream/ecx: (addr stream byte) <- address stream-storage
+  write stream, "=> symbol "
+  write-stream stream, data
+  trace trace, "print", stream
+}
+
+fn print-number _in: (addr cell), out: (addr stream byte), trace: (addr trace) {
+  var in/esi: (addr cell) <- copy _in
+  var val/eax: (addr float) <- get in, number-data
+  write-float-decimal-approximate out, *val, 3/precision
+  # trace
+  var stream-storage: (stream byte 0x40)
+  var stream/ecx: (addr stream byte) <- address stream-storage
+  write stream, "=> number "
+  write-float-decimal-approximate stream, *val, 3/precision
+  trace trace, "print", stream
+}
+
+fn print-list _in: (addr cell), out: (addr stream byte), trace: (addr trace) {
+  var curr/esi: (addr cell) <- copy _in
+  write out, "("
+  $print-list:loop: {
+    var left/ecx: (addr handle cell) <- get curr, left
+    {
+      var left-addr/eax: (addr cell) <- lookup *left
+      var left-is-nil?/eax: boolean <- is-nil? left-addr
+      compare left-is-nil?, 0/false
+      {
+        break-if-=
+        trace-text trace, "print", "left is null"
+        break $print-list:loop
+      }
+    }
+    print-cell left, out, trace
+    var right/ecx: (addr handle cell) <- get curr, right
+    var right-addr/eax: (addr cell) <- lookup *right
+    {
+      compare right-addr, 0
+      break-if-!=
+      abort "null encountered"
+    }
+    {
+      var right-is-nil?/eax: boolean <- is-nil? right-addr
+      compare right-is-nil?, 0/false
+      {
+        break-if-=
+        trace-text trace, "print", "right is null"
+        break $print-list:loop
+      }
+    }
+    write out, " "
+    var right-type-addr/edx: (addr int) <- get right-addr, type
+    {
+      compare *right-type-addr, 0/pair
+      break-if-=
+      write out, ". "
+      print-cell right, out, trace
+      break $print-list:loop
+    }
+    curr <- copy right-addr
+    loop
+  }
+  write out, ")"
+}
+
+# Most lisps intern nil, but we don't really have globals yet, so we'll be
+# less efficient for now.
+fn is-nil? _in: (addr cell) -> _/eax: boolean {
+  var in/esi: (addr cell) <- copy _in
+  # if type != pair, return false
+  var type/eax: (addr int) <- get in, type
+  compare *type, 0/pair
+  {
+    break-if-=
+    return 0/false
+  }
+  # if left != null, return false
+  var left-ah/eax: (addr handle cell) <- get in, left
+  var left/eax: (addr cell) <- lookup *left-ah
+  compare left, 0
+  {
+    break-if-=
+    return 0/false
+  }
+  # if right != null, return false
+  var right-ah/eax: (addr handle cell) <- get in, right
+  var right/eax: (addr cell) <- lookup *right-ah
+  compare right, 0
+  {
+    break-if-=
+    return 0/false
+  }
+  return 1/true
+}
+
+fn test-print-cell-zero {
+  var num-storage: (handle cell)
+  var num/esi: (addr handle cell) <- address num-storage
+  new-integer num, 0
+  var out-storage: (stream byte 0x40)
+  var out/edi: (addr stream byte) <- address out-storage
+  print-cell num, out, 0/no-trace
+  check-stream-equal out, "0", "F - test-print-cell-zero"
+}
+
+fn test-print-cell-integer {
+  var num-storage: (handle cell)
+  var num/esi: (addr handle cell) <- address num-storage
+  new-integer num, 1
+  var out-storage: (stream byte 0x40)
+  var out/edi: (addr stream byte) <- address out-storage
+  print-cell num, out, 0/no-trace
+  check-stream-equal out, "1", "F - test-print-cell-integer"
+}
+
+fn test-print-cell-integer-2 {
+  var num-storage: (handle cell)
+  var num/esi: (addr handle cell) <- address num-storage
+  new-integer num, 0x30
+  var out-storage: (stream byte 0x40)
+  var out/edi: (addr stream byte) <- address out-storage
+  print-cell num, out, 0/no-trace
+  check-stream-equal out, "48", "F - test-print-cell-integer-2"
+}
+
+fn test-print-cell-fraction {
+  var num-storage: (handle cell)
+  var num/esi: (addr handle cell) <- address num-storage
+  var val/xmm0: float <- rational 1, 2
+  new-float num, val
+  var out-storage: (stream byte 0x40)
+  var out/edi: (addr stream byte) <- address out-storage
+  print-cell num, out, 0/no-trace
+  check-stream-equal out, "0.5", "F - test-print-cell-fraction"
+}
+
+fn test-print-cell-symbol {
+  var sym-storage: (handle cell)
+  var sym/esi: (addr handle cell) <- address sym-storage
+  new-symbol sym, "abc"
+  var out-storage: (stream byte 0x40)
+  var out/edi: (addr stream byte) <- address out-storage
+  print-cell sym, out, 0/no-trace
+  check-stream-equal out, "abc", "F - test-print-cell-symbol"
+}
+
+fn test-print-cell-nil-list {
+  var nil-storage: (handle cell)
+  var nil/esi: (addr handle cell) <- address nil-storage
+  allocate-pair nil
+  var out-storage: (stream byte 0x40)
+  var out/edi: (addr stream byte) <- address out-storage
+  print-cell nil, out, 0/no-trace
+  check-stream-equal out, "()", "F - test-print-cell-nil-list"
+}
+
+fn test-print-cell-singleton-list {
+  # list
+  var left-storage: (handle cell)
+  var left/ecx: (addr handle cell) <- address left-storage
+  new-symbol left, "abc"
+  var nil-storage: (handle cell)
+  var nil/edx: (addr handle cell) <- address nil-storage
+  allocate-pair nil
+  var list-storage: (handle cell)
+  var list/esi: (addr handle cell) <- address list-storage
+  new-pair list, *left, *nil
+  #
+  var out-storage: (stream byte 0x40)
+  var out/edi: (addr stream byte) <- address out-storage
+  print-cell list, out, 0/no-trace
+  check-stream-equal out, "(abc)", "F - test-print-cell-singleton-list"
+}
+
+fn test-print-cell-list {
+  # list = cons "abc", nil
+  var left-storage: (handle cell)
+  var left/ecx: (addr handle cell) <- address left-storage
+  new-symbol left, "abc"
+  var nil-storage: (handle cell)
+  var nil/edx: (addr handle cell) <- address nil-storage
+  allocate-pair nil
+  var list-storage: (handle cell)
+  var list/esi: (addr handle cell) <- address list-storage
+  new-pair list, *left, *nil
+  # list = cons 64, list
+  new-integer left, 0x40
+  new-pair list, *left, *list
+  #
+  var out-storage: (stream byte 0x40)
+  var out/edi: (addr stream byte) <- address out-storage
+  print-cell list, out, 0/no-trace
+  check-stream-equal out, "(64 abc)", "F - test-print-cell-list"
+}
+
+fn test-print-dotted-list {
+  # list = cons 64, "abc"
+  var left-storage: (handle cell)
+  var left/ecx: (addr handle cell) <- address left-storage
+  new-symbol left, "abc"
+  var right-storage: (handle cell)
+  var right/edx: (addr handle cell) <- address right-storage
+  new-integer right, 0x40
+  var list-storage: (handle cell)
+  var list/esi: (addr handle cell) <- address list-storage
+  new-pair list, *left, *right
+  #
+  var out-storage: (stream byte 0x40)
+  var out/edi: (addr stream byte) <- address out-storage
+  print-cell list, out, 0/no-trace
+  check-stream-equal out, "(abc . 64)", "F - test-print-dotted-list"
+}