Login
7 branches 0 tags
Ben (X13/Arch) Moved day18 test to ridiculous 46c26df 3 years ago 922 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"]]]