diff --git a/src/backend/escodegen/generator.wisp b/src/backend/escodegen/generator.wisp index 7a0a1657..17435ac5 100644 --- a/src/backend/escodegen/generator.wisp +++ b/src/backend/escodegen/generator.wisp @@ -35,9 +35,10 @@ :sourceMapWithCode true})] ;; Workaround the fact that escodegen does not yet includes source - (.setSourceContent (:map output) - (:source-uri options) - (:source options)) + (if (:map output) + (.setSourceContent (:map output) + (:source-uri options) + (:source options))) {:code (if (:no-map options) (:code output) diff --git a/src/compiler.wisp b/src/compiler.wisp index 850a5866..8ebd1474 100644 --- a/src/compiler.wisp +++ b/src/compiler.wisp @@ -1,10 +1,12 @@ (ns wisp.compiler (:require [wisp.analyzer :refer [analyze]] + [wisp.expander :refer [install-macro!]] [wisp.reader :refer [read* read push-back-reader]] [wisp.string :refer [replace]] - [wisp.sequence :refer [map reduce conj cons vec first rest empty? count]] - [wisp.runtime :refer [error? =]] - [wisp.ast :refer [name symbol pr-str]] + [wisp.sequence :refer [map reduce conj cons vec first second rest + empty? count nth drop list]] + [wisp.runtime :refer [error? string? dictionary? =]] + [wisp.ast :refer [name meta with-meta symbol pr-str]] [wisp.backend.escodegen.generator :refer [generate] :rename {generate generate-js}] @@ -108,3 +110,62 @@ (if (:error output) (throw (:error output)) (eval (:code output))))) + + + +;; defmacro + +(defn with-doc + [doc & body] + (if (string? doc) + `[~doc ~@body] + `[" " ~doc ~@body])) + + +(defn with-metadata + [doc metadata & body] + (if (dictionary? metadata) + `[~doc ~metadata ~@body] + `[~doc {} ~metadata ~@body])) + + +(defn parse-defmacro + [forms] + (let [body (apply with-metadata (apply with-doc forms)) + params (nth body 2) + include-form (= (first params) '&form) + include-env (= (second params) '&env)] + {:doc (first body) + :metadata (second body) + :params params + :body (drop 3 body) + :include-form include-form + :inclued-env include-env})) + +(def define-macro + (fn [&form &env id & body] + (let [node (parse-defmacro body) + doc (:doc node) + params (:params node) + metadata (:metadata node) + body (:body node) + ns-id (name (:name (:ns &env))) + macro-id (str ns-id "$" (name id)) + + macro `(do + (defn ~id + ~doc + ~metadata + ~params + ~@body) + (set! (aget this ~macro-id) ~id) + ~id) + + ast (analyze macro) + code (:code (generate {:no-map true} ast))] + (do + (install-macro! id (eval code)) + macro)))) +(install-macro! 'define-macro (with-meta define-macro {:implicit [:&form :&env]})) + + diff --git a/src/expander.wisp b/src/expander.wisp index ac842f31..e660a9bc 100644 --- a/src/expander.wisp +++ b/src/expander.wisp @@ -21,7 +21,6 @@ "Applies macro registered with given `name` to a given `form`" [expander form env] (let [metadata (or (meta form) {}) - parmas (rest form) implicit (map #(cond (= :&form %) form (= :&env %) env :else %)