Skip to content

Make define-macro macro that outputs JS functions #102

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions src/backend/escodegen/generator.wisp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
67 changes: 64 additions & 3 deletions src/compiler.wisp
Original file line number Diff line number Diff line change
@@ -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}]
Expand Down Expand Up @@ -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]}))


1 change: 0 additions & 1 deletion src/expander.wisp
Original file line number Diff line number Diff line change
Expand Up @@ -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 %)
Expand Down