Login
7 branches 0 tags
Ben (X13/Arch) Simplified things a little 0643405 9 days ago 1260 Commits
nujel / stdlib / core / quasiquote.nuj
;;; Nujel - Copyright (C) 2020-2021 - Benjamin Vincent Schulenburg
;;; This project uses the MIT license, a copy should be included under /LICENSE
;;;
;;; The Nujel implementation for quasiquote, it is important to note that it is
;;; a macro, not a special form.

(def quasiquote (let*
                  (defn quasiquote-real (l depth)
                        (when-not l (return #nil))
                        (if (pair? l)
                            (if (= (caar l) 'unquote-splicing)
                                (if (zero? depth)
                                    (list 'append
                                          (cadr (car l))
                                          (quasiquote-real (cdr l) depth))
                                    (list 'unquote-splicing
                                          (quasiquote-real (cadr l) (+ -1 depth))))
                                (if (= (car l) 'unquote)
                                    (if (zero? depth)
                                        (cadr l)
                                        (list 'unquote
                                              (quasiquote-real (cadr l) (+ -1 depth))))
                                    (if (= (car l) 'quasiquote)
                                        (quasiquote-real (quasiquote-real (cadr l) (+ 1 depth)) depth)
                                        (if (zero? depth)
                                            (list 'cons
                                                  (quasiquote-real (car l) depth)
                                                  (quasiquote-real (cdr l) depth))
                                            (cons (quasiquote-real (car l) depth)
                                                  (quasiquote-real (cdr l) depth))))))
                            (if (and (zero? depth) (symbol? l))
                                (cons 'quote (cons l #nil))
                                l)))

                  (defmacro quasiquote (l)
                            (quasiquote-real l 0))))

(defn unquote (expr)
      (throw (list :unquote-without-quasiquote "unquote should only occur inside a quasiquote, never evaluated directly")))

(defn unquote-splicing (expr)
      (throw (list :unquote-splicing-without-quasiquote "unquote-splicing should only occur inside a quasiquote, never evaluated directly")))