application/octet-stream
•
2.89 KB
•
73 lines
;; Nujel - Copyright (C) 2020-2021 - Benjamin Vincent Schulenburg
;; This project uses the MIT license, a copy should be included under /LICENSE
;;
;; Contains the Nujel macroexpander
;; Expands a do for, leaving out sub-expressions in the middle that are without
;; side effects, which is simplified to mean anything that is not a pair.
[defn macroexpand/do/args [args env]
[if [last? args]
[cons [macroexpand* [car args] env] #nil]
[if [pair? [car args]]
[let* [def ocar [macroexpand* [car args] env]]
[if [pair? ocar]
[cons ocar [macroexpand/do/args [cdr args] env]]
[macroexpand/do/args [cdr args] env]]]
[macroexpand/do/args [cdr args] env]]]]
[defn macroexpand/do [source env]
[def args [macroexpand/do/args source env]]
[if [last? args]
[car args]
[cons 'do args]]]
[defn macroexpand/form [source env op arity implicit-do? no-expand-bitmap]
[def ret [cons op #nil]]
[def l [cdr source]]
[for [i 0 arity]
[set! ret [cons [if [bit-set? no-expand-bitmap i]
[car l]
[macroexpand* [car l] env]]
ret]]
[cdr! l]]
[if implicit-do?
[set! ret [cons [macroexpand/do l env] ret]]
[when l [throw [list :arity-error [cat "form contains more than " arity " arguments"] source [current-lambda]]]]]
[return [nreverse ret]]]
[defn macroexpand/fold [op source env]
[if [cdr source]
[if [cddr source]
[list op
[macroexpand/fold op [except-last-pair source] env]
[macroexpand* [car [last-pair source]] env]]
[list op
[macroexpand* [car source] env]
[macroexpand* [cadr source] env]]]
[list op [macroexpand* [car source] env]]]]
[defn macroexpand* [source env]
"Expand all macros within source"
[def op [if [resolves? [car source] env]
[resolve [car source] env]
[car source]]]
[case [type-of op]
[:nil source]
[:native-function
[case op
[[+ - * / %] [macroexpand/fold op [cdr source]]]
[do [macroexpand/do source env]]
[return [macroexpand/form source env op 1 #f #b0]]
[[try while] [macroexpand/form source env op 1 #t #b0]]
[[def set!] [macroexpand/form source env op 2 #f #b01]]
[if [macroexpand/form source env op 3 #f #b0]]
[[fn* macro*] [macroexpand/form source env op 4 #t #b0111]]
[[let* environment*] [list op [macroexpand/do [cdr source] env]]]
[quote source]
[otherwise [map source [fn [α] [macroexpand* α env]]]]]]
[:macro [macroexpand* [macro-apply op [cdr source]] env]]
[otherwise [map source [fn [α] [macroexpand* α env]]]]]]
[defn macroexpand [source env]
"Macroexpand the forms in source"
[macroexpand* source [or env [current-closure]]]]