about summary refs log tree commit diff stats
path: root/shell
diff options
context:
space:
mode:
Diffstat (limited to 'shell')
-rw-r--r--shell/parse.mu48
-rw-r--r--shell/print.mu30
-rw-r--r--shell/tokenize.mu203
3 files changed, 255 insertions, 26 deletions
diff --git a/shell/parse.mu b/shell/parse.mu
index 03e0488e..283e1d49 100644
--- a/shell/parse.mu
+++ b/shell/parse.mu
@@ -57,6 +57,54 @@ fn parse-sexpression tokens: (addr stream cell), _out: (addr handle cell), trace
       close-paren?, dot? <- parse-sexpression tokens, right-ah, trace
       return close-paren?, dot?
     }
+    # backquote quote -> parse as list with a special car
+    var backquote-token?/eax: boolean <- backquote-token? curr-token
+    compare backquote-token?, 0/false
+    {
+      break-if-=
+      var out/edi: (addr handle cell) <- copy _out
+      allocate-pair out
+      var out-addr/eax: (addr cell) <- lookup *out
+      var left-ah/edx: (addr handle cell) <- get out-addr, left
+      new-symbol left-ah, "`"
+      var right-ah/edx: (addr handle cell) <- get out-addr, right
+      var close-paren?/eax: boolean <- copy 0/false
+      var dot?/ecx: boolean <- copy 0/false
+      close-paren?, dot? <- parse-sexpression tokens, right-ah, trace
+      return close-paren?, dot?
+    }
+    # unquote -> parse as list with a special car
+    var unquote-token?/eax: boolean <- unquote-token? curr-token
+    compare unquote-token?, 0/false
+    {
+      break-if-=
+      var out/edi: (addr handle cell) <- copy _out
+      allocate-pair out
+      var out-addr/eax: (addr cell) <- lookup *out
+      var left-ah/edx: (addr handle cell) <- get out-addr, left
+      new-symbol left-ah, ","
+      var right-ah/edx: (addr handle cell) <- get out-addr, right
+      var close-paren?/eax: boolean <- copy 0/false
+      var dot?/ecx: boolean <- copy 0/false
+      close-paren?, dot? <- parse-sexpression tokens, right-ah, trace
+      return close-paren?, dot?
+    }
+    # unquote-splice -> parse as list with a special car
+    var unquote-splice-token?/eax: boolean <- unquote-splice-token? curr-token
+    compare unquote-splice-token?, 0/false
+    {
+      break-if-=
+      var out/edi: (addr handle cell) <- copy _out
+      allocate-pair out
+      var out-addr/eax: (addr cell) <- lookup *out
+      var left-ah/edx: (addr handle cell) <- get out-addr, left
+      new-symbol left-ah, ",@"
+      var right-ah/edx: (addr handle cell) <- get out-addr, right
+      var close-paren?/eax: boolean <- copy 0/false
+      var dot?/ecx: boolean <- copy 0/false
+      close-paren?, dot? <- parse-sexpression tokens, right-ah, trace
+      return close-paren?, dot?
+    }
     # dot -> return
     var dot?/eax: boolean <- dot-token? curr-token
     compare dot?, 0/false
diff --git a/shell/print.mu b/shell/print.mu
index b1d0e158..f294449d 100644
--- a/shell/print.mu
+++ b/shell/print.mu
@@ -156,7 +156,8 @@ fn print-pair _in: (addr cell), out: (addr stream byte), trace: (addr trace) {
   # if in starts with a quote, print the quote outside the expression
   var in/esi: (addr cell) <- copy _in
   var left-ah/eax: (addr handle cell) <- get in, left
-  var left/eax: (addr cell) <- lookup *left-ah
+  var _left/eax: (addr cell) <- lookup *left-ah
+  var left/ecx: (addr cell) <- copy _left
   var is-quote?/eax: boolean <- symbol-equal? left, "'"
   compare is-quote?, 0/false
   {
@@ -166,6 +167,33 @@ fn print-pair _in: (addr cell), out: (addr stream byte), trace: (addr trace) {
     print-cell right-ah, out, trace
     return
   }
+  var is-backquote?/eax: boolean <- symbol-equal? left, "`"
+  compare is-backquote?, 0/false
+  {
+    break-if-=
+    write out, "`"
+    var right-ah/eax: (addr handle cell) <- get in, right
+    print-cell right-ah, out, trace
+    return
+  }
+  var is-unquote?/eax: boolean <- symbol-equal? left, ","
+  compare is-unquote?, 0/false
+  {
+    break-if-=
+    write out, ","
+    var right-ah/eax: (addr handle cell) <- get in, right
+    print-cell right-ah, out, trace
+    return
+  }
+  var is-unquote-splice?/eax: boolean <- symbol-equal? left, ",@"
+  compare is-unquote-splice?, 0/false
+  {
+    break-if-=
+    write out, ",@"
+    var right-ah/eax: (addr handle cell) <- get in, right
+    print-cell right-ah, out, trace
+    return
+  }
   #
   var curr/esi: (addr cell) <- copy _in
   write out, "("
diff --git a/shell/tokenize.mu b/shell/tokenize.mu
index d0e278f1..0d6fdd6e 100644
--- a/shell/tokenize.mu
+++ b/shell/tokenize.mu
@@ -33,6 +33,95 @@ fn tokenize in: (addr gap-buffer), out: (addr stream cell), trace: (addr trace)
   trace-higher trace
 }
 
+fn test-tokenize-quote {
+  var in-storage: gap-buffer
+  var in/esi: (addr gap-buffer) <- address in-storage
+  initialize-gap-buffer-with in, "'(a)"
+  #
+  var stream-storage: (stream cell 0x10)
+  var stream/edi: (addr stream cell) <- address stream-storage
+  #
+  tokenize in, stream, 0/no-trace
+  #
+  var curr-token-storage: cell
+  var curr-token/ebx: (addr cell) <- address curr-token-storage
+  read-from-stream stream, curr-token
+  var quote?/eax: boolean <- quote-token? curr-token
+  check quote?, "F - test-tokenize-quote: quote"
+  read-from-stream stream, curr-token
+  var open-paren?/eax: boolean <- open-paren-token? curr-token
+  check open-paren?, "F - test-tokenize-quote: open paren"
+  read-from-stream stream, curr-token  # skip a
+  read-from-stream stream, curr-token
+  var close-paren?/eax: boolean <- close-paren-token? curr-token
+  check close-paren?, "F - test-tokenize-quote: close paren"
+}
+
+fn test-tokenize-backquote {
+  var in-storage: gap-buffer
+  var in/esi: (addr gap-buffer) <- address in-storage
+  initialize-gap-buffer-with in, "`(a)"
+  #
+  var stream-storage: (stream cell 0x10)
+  var stream/edi: (addr stream cell) <- address stream-storage
+  #
+  tokenize in, stream, 0/no-trace
+  #
+  var curr-token-storage: cell
+  var curr-token/ebx: (addr cell) <- address curr-token-storage
+  read-from-stream stream, curr-token
+  var backquote?/eax: boolean <- backquote-token? curr-token
+  check backquote?, "F - test-tokenize-backquote: backquote"
+  read-from-stream stream, curr-token
+  var open-paren?/eax: boolean <- open-paren-token? curr-token
+  check open-paren?, "F - test-tokenize-backquote: open paren"
+  read-from-stream stream, curr-token  # skip a
+  read-from-stream stream, curr-token
+  var close-paren?/eax: boolean <- close-paren-token? curr-token
+  check close-paren?, "F - test-tokenize-backquote: close paren"
+}
+
+fn test-tokenize-unquote {
+  var in-storage: gap-buffer
+  var in/esi: (addr gap-buffer) <- address in-storage
+  initialize-gap-buffer-with in, ",(a)"
+  #
+  var stream-storage: (stream cell 0x10)
+  var stream/edi: (addr stream cell) <- address stream-storage
+  #
+  tokenize in, stream, 0/no-trace
+  #
+  var curr-token-storage: cell
+  var curr-token/ebx: (addr cell) <- address curr-token-storage
+  read-from-stream stream, curr-token
+  var unquote?/eax: boolean <- unquote-token? curr-token
+  check unquote?, "F - test-tokenize-unquote: unquote"
+  read-from-stream stream, curr-token
+  var open-paren?/eax: boolean <- open-paren-token? curr-token
+  check open-paren?, "F - test-tokenize-unquote: open paren"
+  read-from-stream stream, curr-token  # skip a
+  read-from-stream stream, curr-token
+  var close-paren?/eax: boolean <- close-paren-token? curr-token
+  check close-paren?, "F - test-tokenize-unquote: close paren"
+}
+
+fn test-tokenize-unquote-splice {
+  var in-storage: gap-buffer
+  var in/esi: (addr gap-buffer) <- address in-storage
+  initialize-gap-buffer-with in, ",@a"
+  #
+  var stream-storage: (stream cell 0x10)
+  var stream/edi: (addr stream cell) <- address stream-storage
+  #
+  tokenize in, stream, 0/no-trace
+  #
+  var curr-token-storage: cell
+  var curr-token/ebx: (addr cell) <- address curr-token-storage
+  read-from-stream stream, curr-token
+  var unquote-splice?/eax: boolean <- unquote-splice-token? curr-token
+  check unquote-splice?, "F - test-tokenize-unquote-splice: unquote-splice"
+}
+
 fn test-tokenize-dotted-list {
   var in-storage: gap-buffer
   var in/esi: (addr gap-buffer) <- address in-storage
@@ -190,6 +279,38 @@ fn next-token in: (addr gap-buffer), _out-cell: (addr cell), trace: (addr trace)
       next-operator-token in, out, trace
       break $next-token:body
     }
+    # quote
+    {
+      compare g, 0x27/single-quote
+      break-if-!=
+      g <- read-from-gap-buffer in  # consume
+      write-grapheme out, g
+      break $next-token:body
+    }
+    # backquote
+    {
+      compare g, 0x60/single-quote
+      break-if-!=
+      g <- read-from-gap-buffer in  # consume
+      write-grapheme out, g
+      break $next-token:body
+    }
+    # unquote
+    {
+      compare g, 0x2c/comma
+      break-if-!=
+      g <- read-from-gap-buffer in  # consume
+      write-grapheme out, g
+      # check for unquote-splice
+      {
+        var g2/eax: grapheme <- peek-from-gap-buffer in
+        compare g2, 0x40/at-sign
+        break-if-!=
+        g2 <- read-from-gap-buffer in
+        write-grapheme out, g2
+      }
+      break $next-token:body
+    }
   }
   trace-higher trace
   var stream-storage: (stream byte 0x40)
@@ -454,17 +575,27 @@ fn symbol-grapheme? g: grapheme -> _/eax: boolean {
     break-if-!=
     return 0/false
   }
-  compare g, 0x2a/asterisk
+  compare g, 0x60/backquote
   {
     break-if-!=
     return 0/false
   }
-  compare g, 0x2b/plus
+  compare g, 0x2c/comma
   {
     break-if-!=
     return 0/false
   }
-  compare g, 0x2c/comma
+  compare g, 0x40/at-sign
+  {
+    break-if-!=
+    return 0/false
+  }
+  compare g, 0x2a/asterisk
+  {
+    break-if-!=
+    return 0/false
+  }
+  compare g, 0x2b/plus
   {
     break-if-!=
     return 0/false
@@ -510,11 +641,6 @@ fn symbol-grapheme? g: grapheme -> _/eax: boolean {
     return 0/false
   }
   # '?' is a symbol char
-  compare g, 0x40/at-sign
-  {
-    break-if-!=
-    return 0/false
-  }
   compare g, 0x5c/backslash
   {
     break-if-!=
@@ -588,19 +714,29 @@ fn operator-grapheme? g: grapheme -> _/eax: boolean {
   compare g, 0x27/single-quote
   {
     break-if-!=
-    return 1/true
+    return 0/true
   }
-  compare g, 0x2a/asterisk
+  compare g, 0x60/backquote
   {
     break-if-!=
-    return 1/true
+    return 0/false
   }
-  compare g, 0x2b/plus
+  compare g, 0x2c/comma
+  {
+    break-if-!=
+    return 0/false
+  }
+  compare g, 0x40/at-sign
+  {
+    break-if-!=
+    return 0/false
+  }
+  compare g, 0x2a/asterisk
   {
     break-if-!=
     return 1/true
   }
-  compare g, 0x2c/comma
+  compare g, 0x2b/plus
   {
     break-if-!=
     return 1/true
@@ -646,11 +782,6 @@ fn operator-grapheme? g: grapheme -> _/eax: boolean {
     return 1/true
   }
   # '?' is a symbol char
-  compare g, 0x40/at-sign
-  {
-    break-if-!=
-    return 1/true
-  }
   compare g, 0x5c/backslash
   {
     break-if-!=
@@ -707,13 +838,35 @@ fn quote-token? _in: (addr cell) -> _/eax: boolean {
   var in-data-ah/eax: (addr handle stream byte) <- get in, text-data
   var in-data/eax: (addr stream byte) <- lookup *in-data-ah
   rewind-stream in-data
-  var g/eax: grapheme <- read-grapheme in-data
-  compare g, 0x27/single-quote
-  {
-    break-if-!=
-    return 1/true
-  }
-  return 0/false
+  var result/eax: boolean <- stream-data-equal? in-data, "'"
+  return result
+}
+
+fn backquote-token? _in: (addr cell) -> _/eax: boolean {
+  var in/eax: (addr cell) <- copy _in
+  var in-data-ah/eax: (addr handle stream byte) <- get in, text-data
+  var in-data/eax: (addr stream byte) <- lookup *in-data-ah
+  rewind-stream in-data
+  var result/eax: boolean <- stream-data-equal? in-data, "`"
+  return result
+}
+
+fn unquote-token? _in: (addr cell) -> _/eax: boolean {
+  var in/eax: (addr cell) <- copy _in
+  var in-data-ah/eax: (addr handle stream byte) <- get in, text-data
+  var in-data/eax: (addr stream byte) <- lookup *in-data-ah
+  rewind-stream in-data
+  var result/eax: boolean <- stream-data-equal? in-data, ","
+  return result
+}
+
+fn unquote-splice-token? _in: (addr cell) -> _/eax: boolean {
+  var in/eax: (addr cell) <- copy _in
+  var in-data-ah/eax: (addr handle stream byte) <- get in, text-data
+  var in-data/eax: (addr stream byte) <- lookup *in-data-ah
+  rewind-stream in-data
+  var result/eax: boolean <- stream-data-equal? in-data, ",@"
+  return result
 }
 
 fn open-paren-token? _in: (addr cell) -> _/eax: boolean {