rebirth: Make quote form recursive, add quasiquote
This was pretty much a prerequisite for introducing macros (in commits to follow)---the code would otherwise be far too verbose. Note that this does _not_ introduce the shorthand forms ("'", "`", ",", ",@"), as implementing those in a reasonable manner would require preprocesing the AST, which is not what I want to focus on right now. So macros will still be a bit verbose, using the full "(quasiquote ... (unquote-splicing ...))" and such instead of simply "`(... ,@(...))" * build-aux/bootstrap/rebirth.scm (quote-sexp, quasiquote-sexp): Add procedures. (fnmap)[quote]: Use `quote-sexp'. [quasiquote]: Add special form.master
parent
d881345fe6
commit
a839301a12
|
@ -556,6 +556,76 @@
|
|||
"function " id "(" params ")\n{\n" body "\n};")))
|
||||
|
||||
|
||||
;; Quote an expression
|
||||
;;
|
||||
;; If SEXP is a token, produce an ECMAScript Symbol. Otherwise,
|
||||
;; recursively apply to each element in the list.
|
||||
;;
|
||||
;; TODO: This implementation isn't wholly correct---numbers, for example,
|
||||
;; should not be converted to symbols, as they already are one.
|
||||
(define (quote-sexp sexp)
|
||||
(if (token? sexp)
|
||||
(string-append "Symbol.for('" (sexp->es sexp) "')")
|
||||
(string-append
|
||||
"[" (join "," (map quote-sexp sexp)) "]")))
|
||||
|
||||
|
||||
;; Quasiquote an expression
|
||||
;;
|
||||
;; A quasiquoted expression acts just like a quoted expression with one
|
||||
;; notable exception---quoting can be escaped using special forms. For
|
||||
;; example, each of these are equivalent:
|
||||
;;
|
||||
;; (quasiquote (a 1 2 (unquote (eq? 3 4))))
|
||||
;; (list (quote a) 1 2 (eq? 3 4))
|
||||
;; (quasiquote (a (unquote-splicing (list 1 2)) (unquote (eq? 3 4))))
|
||||
;;
|
||||
;; TODO/WARNING: Normally "(quasiquote a (unquote-splicing b))" would
|
||||
;; produce "(a . b)" in a proper Lisp, but we do not yet support proper
|
||||
;; pairs at the time that this procedure was written; all cdrs are assumed
|
||||
;; to be lists. So do not do that---always splice lists.
|
||||
(define (quasiquote-sexp sexp)
|
||||
;; get type of token at car of pair, unless not a pair
|
||||
(define (-sexp-maybe-type sexp)
|
||||
(and (pair? sexp)
|
||||
(token? (car sexp))
|
||||
(token-value (car sexp))))
|
||||
|
||||
;; recursively process the sexp, handling various types of unquoting
|
||||
(define (-quote-maybe sexp delim)
|
||||
(if (pair? sexp)
|
||||
(let* ((item (car sexp))
|
||||
(rest (cdr sexp))
|
||||
(type (-sexp-maybe-type item))
|
||||
(add-delim (not (string=? type "unquote-splicing"))))
|
||||
(string-append
|
||||
(case type
|
||||
;; escape quoting, nest within
|
||||
(("unquote")
|
||||
(string-append (if delim "," "")
|
||||
(sexp->es (cadr item))))
|
||||
|
||||
;; escape quoting, splice list into parent expression
|
||||
;; (lazy kluge warning)
|
||||
(("unquote-splicing")
|
||||
(string-append
|
||||
"]).concat(" (sexp->es (cadr item)) ").concat(["))
|
||||
|
||||
;; anything else, we're still quasiquoting recursively
|
||||
(else (string-append (if delim "," "")
|
||||
(quasiquote-sexp item))))
|
||||
|
||||
;; continue processing this list
|
||||
(-quote-maybe rest add-delim)))
|
||||
""))
|
||||
|
||||
;; tokens fall back to normal quoting
|
||||
(if (token? sexp)
|
||||
(quote-sexp sexp)
|
||||
(string-append
|
||||
"([" (-quote-maybe sexp #f) "])")))
|
||||
|
||||
|
||||
;; Function/procedure aliases and special forms
|
||||
;;
|
||||
;; And here we have what is probably the most grotesque part of this file.
|
||||
|
@ -606,12 +676,10 @@
|
|||
"})(false)")))
|
||||
(("js:break") "__whilebrk=true")
|
||||
|
||||
;; fortunately ES6+ has native symbol support :)
|
||||
;; we don't (yet?) need list quoting in Prebirth
|
||||
(("quote")
|
||||
(if (pair? (cdr args))
|
||||
(error "quoting lists is not yet supported; sorry!")
|
||||
(string-append "Symbol.for('" (sexp->es args) "')")))
|
||||
;; note that the unquote forms are only valid within a quasiquote; see
|
||||
;; that procedure for the handling of those forms
|
||||
(("quote") (quote-sexp (car args)))
|
||||
(("quasiquote") (quasiquote-sexp (car args)))
|
||||
|
||||
(("define") (cdfn t))
|
||||
|
||||
|
|
Loading…
Reference in New Issue