Change quasiquote algorithm
[jackhill/mal.git] / impls / bash / step7_quote.sh
index fce62c0..f6076fc 100755 (executable)
@@ -12,42 +12,47 @@ READ () {
 }
 
 # eval
-IS_PAIR () {
-    if _sequential? "${1}"; then
-        _count "${1}"
-        [[ "${r}" > 0 ]] && return 0
-    fi
-    return 1
+starts_with () {
+    _list? "$1" && _first "$1" && _symbol? "$r" && [ "${ANON[$r]}" = "$2" ]
 }
 
 QUASIQUOTE () {
-    if ! IS_PAIR "${1}"; then
-        _symbol quote
-        _list "${r}" "${1}"
-        return
+    _obj_type "$1"
+    case "$r" in
+        list)
+            if starts_with "$1" unquote; then
+                _nth "$1" 1
+            else
+                qqIter "$1"
+            fi ;;
+        vector)
+            _symbol vec;  local a="$r"
+            qqIter "$1"
+            _list "$a" "$r" ;;
+        symbol|hash_map)
+            _symbol quote
+            _list "$r" "$1" ;;
+        *)
+            r="$1" ;;
+    esac
+}
+
+qqIter () {
+    if _empty? "$1"; then
+        _list
     else
-        _nth "${1}" 0; local a0="${r}"
-        if [[ "${ANON["${a0}"]}" == "unquote" ]]; then
-            _nth "${1}" 1
-            return
-        elif IS_PAIR "${a0}"; then
-            _nth "${a0}" 0; local a00="${r}"
-            if [[ "${ANON["${a00}"]}" == "splice-unquote" ]]; then
-                _symbol concat; local a="${r}"
-                _nth "${a0}" 1; local b="${r}"
-                _rest "${1}"
-                QUASIQUOTE "${r}"; local c="${r}"
-                _list "${a}" "${b}" "${c}"
-                return
-            fi
+        _nth "${1}" 0;        local a0="$r"
+        if starts_with "$a0" splice-unquote; then
+            _symbol concat;   local a="$r"
+            _nth "$a0" 1;     local b="$r"
+        else
+            _symbol cons;     local a="$r"
+            QUASIQUOTE "$a0"; local b="$r"
         fi
+        _rest "$1"
+        qqIter "$r"
+        _list "$a" "$b" "$r"
     fi
-    _symbol cons; local a="${r}"
-    QUASIQUOTE "${a0}"; local b="${r}"
-    _rest "${1}"
-    QUASIQUOTE "${r}"; local c="${r}"
-    _list "${a}" "${b}" "${c}"
-    return
 }
 
 EVAL_AST () {
@@ -115,6 +120,9 @@ EVAL () {
         quote)
               r="${a1}"
               return ;;
+        quasiquoteexpand)
+              QUASIQUOTE "${a1}"
+              return ;;
         quasiquote)
               QUASIQUOTE "${a1}"
               ast="${r}"