Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 934 lines (827 sloc) 39.271 kB
3d5ee87 @hraberg special forms in their own file
authored
1 (ns deuce.emacs-lisp
fc84525 @hraberg Keywordify and format ns declarations
authored
2 (:require [clojure.core :as c]
f1adbd0 @hraberg Logging
authored
3 [clojure.string :as s]
4 [clojure.pprint :as pp]
e7d1492 @ljos use Cons in emacs_lisp
ljos authored
5 [clojure.walk :as w]
54db75d @hraberg Passing tests with new cons and error
authored
6 [deuce.emacs-lisp.cons :as cons])
f1adbd0 @hraberg Logging
authored
7 (:use [taoensso.timbre :as timbre
54db75d @hraberg Passing tests with new cons and error
authored
8 :only (trace debug info warn error fatal spy)])
18f7d1e @hraberg Retaining metadata during various transformations so the generated Cl…
authored
9 (:import [clojure.lang Var ExceptionInfo IMeta]
7fe9976 @hraberg Welcome to GNU Emacs
authored
10 [java.io Writer]
11 [java.lang.reflect Method])
54db75d @hraberg Passing tests with new cons and error
authored
12 (:refer-clojure :exclude [defmacro and or cond let while eval set compile]))
49cd7af @hraberg More realistic parsing of cons pairs and characters
authored
13
f1adbd0 @hraberg Logging
authored
14 (timbre/set-config! [:prefix-fn]
15 (fn [{:keys [level timestamp hostname ns]}]
16 (str timestamp " " (-> level name s/upper-case) " [" ns "]")))
17 (timbre/set-config! [:timestamp-pattern] "HH:mm:ss,SSS")
18
6fe545e @hraberg Deuce buffer appender for the debug log
authored
19 (timbre/set-level! :debug)
20 (timbre/set-config! [:appenders :standard-out :min-level] :error)
5794e4b @hraberg Keyword lookup of Buffer field to avoid reflection warning
authored
21 (set! *warn-on-reflection* true)
f1adbd0 @hraberg Logging
authored
22
3260524 @hraberg A first attempt to establish a master namespace for all Emacs Lisp
authored
23 (create-ns 'deuce.emacs)
a833db0 @hraberg Adding in the vars as well (all nil for now)
authored
24 (create-ns 'deuce.emacs-lisp.globals)
3d5ee87 @hraberg special forms in their own file
authored
25
0ad6fc1 @hraberg Finally getting rid of eval for set/set-default
authored
26 (declare clojure-special-forms throw throw* defvar el->clj eval emacs-lisp-backquote defvar-helper*)
43aef8b @hraberg Cleaning out old stuff not used anymore
authored
27
7fe9976 @hraberg Welcome to GNU Emacs
authored
28 (defn vector-reader [v]
3367e66 @hraberg Cons cells needs to be able to contain unquotes, a mess to handle thi…
authored
29 (object-array (vec v)))
7fe9976 @hraberg Welcome to GNU Emacs
authored
30
31 (defn symbol-reader [s]
32 (symbol nil s))
33
43aef8b @hraberg Cleaning out old stuff not used anymore
authored
34 (defn sym [s]
fb1f31a @hraberg Changes to how classpath loadpath work a bit. Stubbing out define-com…
authored
35 (c/cond
18f7d1e @hraberg Retaining metadata during various transformations so the generated Cl…
authored
36 (true? s)'#el/sym "true"
37 (nil? s) '#el/sym "nil"
38 :else (symbol nil (name s))))
43aef8b @hraberg Cleaning out old stuff not used anymore
authored
39
18f7d1e @hraberg Retaining metadata during various transformations so the generated Cl…
authored
40 ; "reused" from data.clj
43aef8b @hraberg Cleaning out old stuff not used anymore
authored
41 (defn not-null? [object]
42 (when-not (c/or (nil? object) (c/= () object) (false? object))
43 object))
44
45 (defn global [s]
46 (ns-resolve 'deuce.emacs-lisp.globals (sym s)))
47
48 (defn fun [s]
991265d @hraberg New define-key and finally, lookup-key. Some issues around certain pr…
authored
49 (condp some [s]
50 fn? s
51 var? (fun @s)
52 symbol? (c/let [f (ns-resolve 'deuce.emacs (sym s))]
18f7d1e @hraberg Retaining metadata during various transformations so the generated Cl…
authored
53 ;; Not sure we want alias handling leaking down to here.
54 ;; On the other hand, 24.3 uses defalias + lambda as primary macros.
55 ;; Hack to protect against backquote alias, needs proper fix.
56 (if-let [alias (c/and (not= '#el/sym "\\`" s)
57 (-> f meta :alias))]
58 (if (symbol? alias) ;; See binding/mode-specific-command-prefix
59 (fun alias)
60 alias)
61 f))
991265d @hraberg New define-key and finally, lookup-key. Some issues around certain pr…
authored
62 (every-pred seq? (comp '#{lambda keymap} first)) s ;; symbol-function should really be permissive about this.
63 (throw* 'invalid-function (list s))))
43aef8b @hraberg Cleaning out old stuff not used anymore
authored
64
65 (defn maybe-sym [x]
66 (if (symbol? x) (sym x) x))
67
9f8d999 @hraberg In flight work
authored
68 (defn emacs-lisp-error [tag value]
69 (proxy [ExceptionInfo] [(str tag) {:tag tag :value value}]
70 (getMessage [] (str this))
71 (toString []
72 (str (cons (:tag (.data ^ExceptionInfo this))
73 (c/let [d (:value (.-data ^ExceptionInfo this))]
18f7d1e @hraberg Retaining metadata during various transformations so the generated Cl…
authored
74 (if (seq? d) d [d])))))))
9f8d999 @hraberg In flight work
authored
75
76 (defn throw* [tag value]
77 (throw (emacs-lisp-error tag value)))
905383b @hraberg New but not plugged in dynamic var logic. 1.5 RC16 seems to be picky …
authored
78
31be044 @hraberg Don't nest delayed evals
authored
79 (defn scope [&env]
80 (c/set (remove #(re-find #"__\d+" (name %)) (keys &env))))
81
905383b @hraberg New but not plugged in dynamic var logic. 1.5 RC16 seems to be picky …
authored
82 (def ^:dynamic *dynamic-vars* {})
83
c627c82 @hraberg The Funk Phenomena of Buffer Local Variables
authored
84 (def symbol-plists (atom {}))
85
2eb28ea @hraberg Comment reminding of buffer local variables
authored
86 ;; There's also an obsolete (as of Emacs 22.2) concept of frame locals.
87 ;; See deuce.emacs.data/make-variable-frame-local and deuce.emacs.frame/modify-frame-parameters
c627c82 @hraberg The Funk Phenomena of Buffer Local Variables
authored
88 ;; This is the set of variables which can potentially be buffer local, values are stored in local-var-alist on Buffer.
89 ;; It's initialized by deuce.emacs.buffer/init-buffer-locals
90 (def buffer-locals (atom #{}))
91
92 (defn el-var-buffer-local [needs-to-exist? name]
93 (when-let [buffer ((fun 'current-buffer))]
5794e4b @hraberg Keyword lookup of Buffer field to avoid reflection warning
authored
94 (c/let [buffer-local (@(:local-var-alist buffer) name)]
18f7d1e @hraberg Retaining metadata during various transformations so the generated Cl…
authored
95 (if-not needs-to-exist?
96 (c/or buffer-local
97 (when (contains? @buffer-locals name)
98 (c/let [v (Var/create)]
99 (swap! (:local-var-alist buffer) assoc name v)
100 v)))
101 (when (c/and buffer-local (bound? buffer-local)) buffer-local)))))
4dab6a3 @hraberg Adding nop buffer local hook in the var logic
authored
102
9f8d999 @hraberg In flight work
authored
103 (defn el-var [name]
c627c82 @hraberg The Funk Phenomena of Buffer Local Variables
authored
104 ((some-fn *dynamic-vars* (partial el-var-buffer-local true) global) name))
9f8d999 @hraberg In flight work
authored
105
106 (defn el-var-get* [name]
107 (c/let [name (sym name)]
18f7d1e @hraberg Retaining metadata during various transformations so the generated Cl…
authored
108 (if-let [v (el-var name)]
109 @v
110 (throw* 'void-variable (list name)))))
9f8d999 @hraberg In flight work
authored
111
905383b @hraberg New but not plugged in dynamic var logic. 1.5 RC16 seems to be picky …
authored
112 (c/defmacro el-var-get [name]
7fe9976 @hraberg Welcome to GNU Emacs
authored
113 (c/let [name (sym name)]
18f7d1e @hraberg Retaining metadata during various transformations so the generated Cl…
authored
114 (if (c/and (symbol? name) (name &env))
115 `(if (var? ~name)
116 (if (bound? ~name) @~name
117 (throw* '~'void-variable (list '~name)))
118 ~name)
119 `(el-var-get* '~name))))
905383b @hraberg New but not plugged in dynamic var logic. 1.5 RC16 seems to be picky …
authored
120
0ad6fc1 @hraberg Finally getting rid of eval for set/set-default
authored
121 (defn el-var-set-default* [name value]
122 (if-let [v (global name)]
123 (alter-var-root v (constantly value))
124 @(global (defvar-helper* 'deuce.emacs-lisp.globals name value))))
125
868bbff @hraberg Proper / in symbols, setq-default, last modified check for el vs gene…
authored
126 (c/defmacro el-var-set-default [name value]
7fe9976 @hraberg Welcome to GNU Emacs
authored
127 (c/let [name (sym name)]
18f7d1e @hraberg Retaining metadata during various transformations so the generated Cl…
authored
128 `(el-var-set-default* '~name ~value)))
0ad6fc1 @hraberg Finally getting rid of eval for set/set-default
authored
129
130 (defn el-var-set* [name-or-var value]
131 (if-let [^Var v (c/or (c/and (var? name-or-var) name-or-var)
132 ((some-fn *dynamic-vars* (partial el-var-buffer-local false)) name-or-var))]
133 (if (c/or (c/and (.hasRoot v) (not (.getThreadBinding v))) (not (bound? v)))
134 (alter-var-root v (constantly value))
135 (var-set v value))
136 (el-var-set-default* name-or-var value)))
868bbff @hraberg Proper / in symbols, setq-default, last modified check for el vs gene…
authored
137
905383b @hraberg New but not plugged in dynamic var logic. 1.5 RC16 seems to be picky …
authored
138 (c/defmacro el-var-set [name value]
7fe9976 @hraberg Welcome to GNU Emacs
authored
139 (c/let [name (sym name)]
18f7d1e @hraberg Retaining metadata during various transformations so the generated Cl…
authored
140 `(el-var-set* ~(if (c/and (symbol? name) (name &env))
141 `~name
142 `'~name)
143 ~value)))
47bc439 @hraberg New evaluation model, take 1. Generates .clj that compiles to .class …
authored
144
816700e @hraberg Supporting the lexical argument to eval. Turning eval into fn as lots…
authored
145 (defn dynamic-binding? []
146 (not (el-var-get lexical-binding)))
147
47bc439 @hraberg New evaluation model, take 1. Generates .clj that compiles to .class …
authored
148 (c/defmacro with-local-el-vars [name-vals-vec & body]
816700e @hraberg Supporting the lexical argument to eval. Turning eval into fn as lots…
authored
149 (c/let [vars (vec (map sym (take-nth 2 name-vals-vec)))
5e96fe5 @hraberg Only create one Var per dynamic var
authored
150 vals (vec (take-nth 2 (rest name-vals-vec)))]
18f7d1e @hraberg Retaining metadata during various transformations so the generated Cl…
authored
151 `(c/let [vars# (hash-map ~@(interleave (map #(list 'quote %) vars)
152 (map #(do `(c/or (*dynamic-vars* '~%) (global '~%)
153 (.setDynamic (Var/create)))) vars)))]
154 (with-bindings (zipmap (map vars# '~vars) ~vals)
155 (binding [*dynamic-vars* (if (dynamic-binding?) (merge *dynamic-vars* vars#) {})]
156 (c/let [{:syms ~vars} vars#]
157 ~@body))))))
47bc439 @hraberg New evaluation model, take 1. Generates .clj that compiles to .class …
authored
158
c6e09d3 @hraberg Slightly changed load model, trying to delay evaluation/compilation o…
authored
159 (def ^:dynamic *disallow-undefined* #{})
160
69e1e79 @hraberg Lots of new files loading. Debating the time for macro autoloads..
authored
161 ;; build cached invoker to use once target is resolved?
d0957fd @hraberg Back to pcase
authored
162 (defn delayed-eval* [expr]
163 (binding [*disallow-undefined* (conj *disallow-undefined* (first expr))]
164 (eval expr)))
165
c6e09d3 @hraberg Slightly changed load model, trying to delay evaluation/compilation o…
authored
166 (c/defmacro delayed-eval [expr]
d0957fd @hraberg Back to pcase
authored
167 `(delayed-eval* '~expr))
c6e09d3 @hraberg Slightly changed load model, trying to delay evaluation/compilation o…
authored
168
b03fe19 @hraberg Moving the parser back to produce literal Emacs Lisp syntax quote forms
authored
169 (defn expand-dotted-lists [x]
170 (if (c/or (cons/dotted-list? x) (cons/dotted-pair? x))
18f7d1e @hraberg Retaining metadata during various transformations so the generated Cl…
authored
171 (apply cons/list x)
172 x))
b03fe19 @hraberg Moving the parser back to produce literal Emacs Lisp syntax quote forms
authored
173
50838a1 @hraberg append is just such an awesome little fn
authored
174 ;; Break this up and explain what the different branches are doing and why.
47bc439 @hraberg New evaluation model, take 1. Generates .clj that compiles to .class …
authored
175 (defn el->clj [x]
18f7d1e @hraberg Retaining metadata during various transformations so the generated Cl…
authored
176 (cond-> (condp some [x]
177 #{()} nil
178 seq? (c/let [[fst & rst] x]
179 (if (c/and (symbol? fst)
180 (not= 'progn fst)
181 (-> (fun fst) meta :macro))
182 (if (c/or (clojure-special-forms fst) ('#{let lambda} fst)) ;; defun defvar ?
183 (if (= 'quote fst)
184 (if-let [s (c/and (symbol? (first rst)) (not (next rst)) (first rst))]
185 (list 'quote (if (= "deuce.emacs" (namespace s)) (sym s) s))
186 (if (= '(()) rst) () x))
187 (apply cons/list (c/cons (symbol "deuce.emacs-lisp" (name fst)) rst)))
188 (apply cons/list x))
189 (if (#{`el-var-get `el-var-set `el-var-set-default `delayed-eval
190 '#el/sym "\\," '#el/sym "\\,@"} fst)
191 x
192 (if (= '#el/sym "\\`" fst)
193 (emacs-lisp-backquote x) ;; See below, we dont want to duplicate this if not necessary.
194 (if (c/and (symbol? fst)
195 (not (namespace fst))
196 (not (fun fst)))
197 (if (*disallow-undefined* fst)
1fb7caa @hraberg Improved Emacs Lisp pprint output, but doesn't work fully, so not swi…
authored
198 (do (debug fst "RECURSIVE UNDEFINED DISALLOWED")
199 `(throw* '~'void-function '~fst))
18f7d1e @hraberg Retaining metadata during various transformations so the generated Cl…
authored
200 (do (debug fst "NOT DEFINED")
201 (list `delayed-eval x)))
202
203 (expand-dotted-lists (c/cons
204 (if (seq? fst) (el->clj fst) fst)
205 (map el->clj rst))))))))
206 symbol? (if (namespace x)
207 (if (-> (resolve x) meta :macro) (resolve x) x)
208 (if (#{'#el/sym "\\," '#el/sym "\\,@" '.} x)
209 x
210 (list `el-var-get x)))
211 x)
212 (instance? IMeta x) (some-> (with-meta (meta x)))))
0d185a8 @hraberg Lexical varibles in let/let* coexisting with dynamic globals. Support…
authored
213
47bc439 @hraberg New evaluation model, take 1. Generates .clj that compiles to .class …
authored
214 (defn ^Throwable cause [^Throwable e]
f1adbd0 @hraberg Logging
authored
215 (if-let [e (.getCause e)]
216 (recur e)
217 e))
218
e016c6d @hraberg Syntax quote as macro and monkey patched pprint to generate nicer Clo…
authored
219 (def ^Method clojure-syntax-quote
220 (doto
221 (.getDeclaredMethod clojure.lang.LispReader$SyntaxQuoteReader
222 "syntaxQuote"
223 (into-array [Object]))
224 (.setAccessible true)))
225
f1d0725 @hraberg Defining apply-partially ourselves instead of dealing with subr.el's …
authored
226 (defn syntax-quote* [form]
9b45b25 @hraberg Various bits and pieces. Mega bug in lambda with outer scope shadowin…
authored
227 (.invoke clojure-syntax-quote nil (into-array [form])))
e016c6d @hraberg Syntax quote as macro and monkey patched pprint to generate nicer Clo…
authored
228
01790c5 @hraberg Emacs Lisp can unquote splice an atom at the last position of a list.…
authored
229 ;; Emacs Lisp allows an atom to be spliced if it is in the last position, like this:
230 ;; (let ((upat 'x) (sym 'x))
231 ;; `(match ,sym ,@upat))
232 ;; => (match x . x)
8559ec8 @hraberg Corner case with unquote-splicing when single element
authored
233 ;; Doesn't handle this wonderful case:
234 ;; `,@2 => 2
01790c5 @hraberg Emacs Lisp can unquote splice an atom at the last position of a list.…
authored
235 (defn maybe-splice-dotted-list [x]
236 (if ((some-fn seq? nil?) x) x `(. ~x)))
237
9b45b25 @hraberg Various bits and pieces. Mega bug in lambda with outer scope shadowin…
authored
238 ;; There's a version of this already defined as macro in backquote.el, use it / override it?
239 ;; What's their relationship?
b03fe19 @hraberg Moving the parser back to produce literal Emacs Lisp syntax quote forms
authored
240 (defn emacs-lisp-backquote [form]
9b45b25 @hraberg Various bits and pieces. Mega bug in lambda with outer scope shadowin…
authored
241 (w/postwalk
242 #(c/cond
18f7d1e @hraberg Retaining metadata during various transformations so the generated Cl…
authored
243 (c/and (seq? %) (seq? (last %)) (= `unquote-splicing (first (last %))))
244 (if (butlast %)
245 (concat (butlast %) `((unquote-splicing (maybe-splice-dotted-list ~(second (last %))))))
246 (second (last %)))
01790c5 @hraberg Emacs Lisp can unquote splice an atom at the last position of a list.…
authored
247
18f7d1e @hraberg Retaining metadata during various transformations so the generated Cl…
authored
248 (c/and (seq? %) (= '#el/sym "\\`" (first %)))
249 (el->clj (syntax-quote* (second %)))
01790c5 @hraberg Emacs Lisp can unquote splice an atom at the last position of a list.…
authored
250
18f7d1e @hraberg Retaining metadata during various transformations so the generated Cl…
authored
251 (= '#el/sym "\\," %) `unquote
252 (= '#el/sym "\\,@" %) `unquote-splicing
253 :else %) form))
b03fe19 @hraberg Moving the parser back to produce literal Emacs Lisp syntax quote forms
authored
254
0c6b787 @hraberg More Refactoring
authored
255 (defn compile [emacs-lisp]
5cf9716 @hraberg Breaking Build. Actually evaluating the Emacs Lisp loaded more proper…
authored
256 (try
b92d265 @hraberg Some crazy but not totally wrong keymap building
authored
257 (when emacs-lisp (c/eval (if (meta emacs-lisp) (with-meta emacs-lisp nil) emacs-lisp)))
1b72cfe @hraberg ExceptionInfo is internal to EmacsLisp, so not 'our problem'. Drainag…
authored
258 (catch ExceptionInfo e
259 (throw e))
5cf9716 @hraberg Breaking Build. Actually evaluating the Emacs Lisp loaded more proper…
authored
260 (catch RuntimeException e
c6e09d3 @hraberg Slightly changed load model, trying to delay evaluation/compilation o…
authored
261 (do
9f8d999 @hraberg In flight work
authored
262 (error (-> e cause .getMessage) (with-out-str (pp/pprint emacs-lisp)))
c6e09d3 @hraberg Slightly changed load model, trying to delay evaluation/compilation o…
authored
263 (throw e)))))
9f8d999 @hraberg In flight work
authored
264
fb1f31a @hraberg Changes to how classpath loadpath work a bit. Stubbing out define-com…
authored
265 ;; Defined in eval.clj
816700e @hraberg Supporting the lexical argument to eval. Turning eval into fn as lots…
authored
266 (defn eval [body & [lexical]]
29aa9d7 @hraberg Simple dist script to create the uberjar. dynapath to add .deuce.d to…
authored
267 (binding [*ns* (the-ns 'deuce.emacs)
268 *compile-files* false]
816700e @hraberg Supporting the lexical argument to eval. Turning eval into fn as lots…
authored
269 (with-bindings (if lexical {(global 'lexical-binding) true} {})
9f8d999 @hraberg In flight work
authored
270 (maybe-sym (compile (el->clj body))))))
ebc0478 @hraberg Adding meta data to Emacs Lisp so you M-. to it from Clojure. Fightin…
authored
271
b018b12 @hraberg The eternal battle against autoload
authored
272 (defn parse-doc-string [[doc & rst :as body]]
273 (if (string? doc)
eefd5a4 @hraberg Trying to get one of the Zile tests to pass, but breaks other things.
authored
274 [doc rst]
b018b12 @hraberg The eternal battle against autoload
authored
275 [nil body]))
276
18f7d1e @hraberg Retaining metadata during various transformations so the generated Cl…
authored
277 (defn meta-walk [inner outer form]
278 (cond-> (w/walk inner outer form)
279 (instance? IMeta form) (with-meta (meta form))))
280
281 (defn normalize-form-for-macro
282 ([form] (normalize-form-for-macro identity form))
283 ([f form]
284 (meta-walk (partial normalize-form-for-macro f) identity (f form))))
285
dfdb77a @hraberg Storing away the interactive directive in the meta data
authored
286 (defn def-helper-process-var* [f needs-intern? name doc interactive emacs-lisp? el-arglist]
7a7d5d8 @hraberg Move defn/defmacro out of let so we get better classnames and stacktr…
authored
287 (c/let [m (merge {:doc doc}
53f9a4d @hraberg Adding interactive forms to all built ins that are commands
authored
288 (when interactive {:interactive (second interactive)})
7a7d5d8 @hraberg Move defn/defmacro out of let so we get better classnames and stacktr…
authored
289 (when emacs-lisp?
290 {:el-arglist el-arglist
291 :el-file (when-let [file (el-var 'load-file-name)]
292 @file)}))]
18f7d1e @hraberg Retaining metadata during various transformations so the generated Cl…
authored
293 (if (var? f)
294 (do
295 (alter-meta! f merge m)
296 (alter-var-root f (constantly (with-meta @f (meta f))))
297 (when needs-intern?
298 (intern 'deuce.emacs (with-meta name (dissoc (meta f) :name)) @f)
299 (ns-unmap 'deuce.emacs needs-intern?)))
300 (with-meta f m))))
7a7d5d8 @hraberg Move defn/defmacro out of let so we get better classnames and stacktr…
authored
301
302 (c/defmacro def-helper* [what name arglist & body]
b018b12 @hraberg The eternal battle against autoload
authored
303 (c/let [[docstring body] (parse-doc-string body)
7fe9976 @hraberg Welcome to GNU Emacs
authored
304 name (sym name)
3367e66 @hraberg Cons cells needs to be able to contain unquotes, a mess to handle thi…
authored
305 el-arglist arglist
57b0cf5 @hraberg char to int for arithmetic, using atom instead of metadata for plists…
authored
306 rest-arg (maybe-sym (second (drop-while (complement '#{&rest}) arglist)))
7fe9976 @hraberg Welcome to GNU Emacs
authored
307 [arg & args :as arglist] (map sym (replace '{&rest &} arglist))
7489ba7 @hraberg splitting out - but not using - interactive in defun
authored
308 [arglist &optional optional-args] (if (= '&optional arg)
309 [() arg args]
762a41f @hraberg minibuffer promt
authored
310 (partition-by '#{&optional} arglist))
7489ba7 @hraberg splitting out - but not using - interactive in defun
authored
311 arglist (concat arglist (when &optional ['& (vec optional-args)]))
255b3bc @hraberg Passing build reflecting that subr.el cannot yet be properly loaded.
authored
312 [[interactive] body] (split-with #(c/and (seq? %)
69ffa5d @hraberg Moving closer to splitting out the primitives
authored
313 (= 'interactive (first %))) body)
296df3a @hraberg Making lambda use def helper so it can support proper args
authored
314 emacs-lisp? (= (the-ns 'deuce.emacs) *ns*)
b6fd4a7 @hraberg Various small bits
authored
315 macro? (= `c/defmacro what)
78509b0 @hraberg Expermients with scope, solves some issues, create others. Not clean
authored
316 doc (apply str docstring)
85336b2 @hraberg More refactoring
authored
317 arglist (w/postwalk maybe-sym arglist)
868bbff @hraberg Proper / in symbols, setq-default, last modified check for el vs gene…
authored
318 the-args (remove '#{&} (flatten arglist))
7a7d5d8 @hraberg Move defn/defmacro out of let so we get better classnames and stacktr…
authored
319 needs-intern? (when (c/and (re-find #"/" (c/name name)) (not= '/ name))
eefd5a4 @hraberg Trying to get one of the Zile tests to pass, but breaks other things.
authored
320 (sym (s/replace (c/name name) "/" "SLASH")))
321 not-implemented? (c/or (= [docstring] body) (empty? body))]
18f7d1e @hraberg Retaining metadata during various transformations so the generated Cl…
authored
322 `(def-helper-process-var*
323 (~what ~(if needs-intern? needs-intern? name) ~(vec arglist)
324 ~(when not-implemented?
325 `(binding [*ns* (the-ns 'clojure.core)]
326 (warn ~(c/name name) "NOT IMPLEMENTED")))
327 ~(if emacs-lisp?
328 `(c/let ~(if rest-arg
329 `[~rest-arg (if-let [r# ~rest-arg] (apply cons/list r#) nil)]
330 [])
331 (c/let [result# (with-local-el-vars ~(vec (mapcat #(c/list % %) the-args))
332 (progn ~@body))]
333 ;; There's something wrong with the returned forms, hence the prewalk
334 (if ~macro?
335 (normalize-form-for-macro (el->clj result#))
336 result#)))
337 `(do ~@body)))
338 '~needs-intern? '~name ~doc '~interactive '~emacs-lisp? '~el-arglist)))
699e06c @hraberg Emacs Lisp Macros, take 1
authored
339
14008e9 @hraberg More exact version of override
authored
340 (def override? '#{apply-partially})
341
699e06c @hraberg Emacs Lisp Macros, take 1
authored
342 (c/defmacro defun
343 "Define NAME as a function.
344 The definition is (lambda ARGLIST [DOCSTRING] BODY...).
345 See also the function `interactive'."
346 {:arglists '([NAME ARGLIST [DOCSTRING] BODY...])}
347 [name arglist & body]
7fe9976 @hraberg Welcome to GNU Emacs
authored
348 (c/let [name (sym name)]
18f7d1e @hraberg Retaining metadata during various transformations so the generated Cl…
authored
349 `(do ~(when-not (override? name)
350 `(def-helper* defn ~name ~arglist ~@body))
351 '~name)))
296df3a @hraberg Making lambda use def helper so it can support proper args
authored
352
fb1f31a @hraberg Changes to how classpath loadpath work a bit. Stubbing out define-com…
authored
353 ;; Defined in subr.el
296df3a @hraberg Making lambda use def helper so it can support proper args
authored
354 (c/defmacro lambda
355 "Return a lambda expression.
356 A call of the form (lambda ARGS DOCSTRING INTERACTIVE BODY) is
357 self-quoting; the result of evaluating the lambda expression is the
358 expression itself. The lambda expression may then be treated as a
359 function, i.e., stored as the function value of a symbol, passed to
360 `funcall' or `mapcar', etc.
361
362 ARGS should take the same form as an argument list for a `defun'.
363 DOCSTRING is an optional documentation string.
364 If present, it should describe how to call the function.
365 But documentation strings are usually not useful in nameless functions.
366 INTERACTIVE should be a call to the function `interactive', which see.
367 It may also be omitted.
368 BODY should be a list of Lisp expressions."
369 {:arglists '([ARGS [DOCSTRING] [INTERACTIVE] BODY])}
370 [& cdr]
9f8d999 @hraberg In flight work
authored
371 (c/let [[args & body] cdr
eefd5a4 @hraberg Trying to get one of the Zile tests to pass, but breaks other things.
authored
372 [docstring _] (parse-doc-string body)
9f8d999 @hraberg In flight work
authored
373 doc (apply str docstring)
31be044 @hraberg Don't nest delayed evals
authored
374 vars (scope &env)
9b45b25 @hraberg Various bits and pieces. Mega bug in lambda with outer scope shadowin…
authored
375 vars (vec (remove (c/set args) vars))]
18f7d1e @hraberg Retaining metadata during various transformations so the generated Cl…
authored
376 ;; This is wrong as it won't share updates between original definition and the lambda var.
377 ;; Yet to see if this ends up being a real issue. A few days later: Indeed it is!
378 `(c/let [closure# (zipmap '~vars
379 (map #(c/let [^Var v# (if (dynamic-binding?) ;; Temporary hack.
380 (if (var? %) % (Var/create %))
381 (Var/create (if (var? %) (deref %) %)))]
382 (.setDynamic v#))
383 ~vars))]
384 (with-meta
385 (def-helper* fn lambda ~args
386 (binding [*dynamic-vars* (if (dynamic-binding?)
387 (merge *dynamic-vars* closure#) {})]
388 (c/let [{:syms ~vars} closure#]
389 (progn ~@body)))) {:doc ~doc}))))
3d5ee87 @hraberg special forms in their own file
authored
390
fb1f31a @hraberg Changes to how classpath loadpath work a bit. Stubbing out define-com…
authored
391 ;; Defined in subr.el
f1d0725 @hraberg Defining apply-partially ourselves instead of dealing with subr.el's …
authored
392 (defn apply-partially
393 "Return a function that is a partial application of FUN to ARGS.
394 ARGS is a list of the first N arguments to pass to FUN.
395 The result is a new function which does the same as FUN, except that
396 the first N arguments are fixed at the values with which this function
397 was called."
398 [fun & args]
399 (fn partial [& new-args]
400 (apply (deuce.emacs-lisp/fun fun) (concat args new-args))))
401
fb1f31a @hraberg Changes to how classpath loadpath work a bit. Stubbing out define-com…
authored
402 ;; Defined in cl-macs.el. Optimizes existing fns which complicates things a lot.
403 (c/defmacro define-compiler-macro
18f7d1e @hraberg Retaining metadata during various transformations so the generated Cl…
authored
404 "Define a compiler-only macro.
fb1f31a @hraberg Changes to how classpath loadpath work a bit. Stubbing out define-com…
authored
405 This is like `defmacro', but macro expansion occurs only if the call to
406 FUNC is compiled (i.e., not interpreted). Compiler macros should be used
407 for optimizing the way calls to FUNC are compiled; the form returned by
408 BODY should do the same thing as a call to the normal function called
409 FUNC, though possibly more efficiently. Note that, like regular macros,
410 compiler macros are expanded repeatedly until no further expansions are
411 possible. Unlike regular macros, BODY can decide to \"punt\" and leave the
412 original function call alone by declaring an initial `&whole foo' parameter
413 and then returning foo."
414 {:arglists '([FUNC ARGS &rest BODY])}
415 [func args & body])
416
3d5ee87 @hraberg special forms in their own file
authored
417 (c/defmacro unwind-protect
418 "Do BODYFORM, protecting with UNWINDFORMS.
419 If BODYFORM completes normally, its value is returned
420 after executing the UNWINDFORMS.
421 If BODYFORM exits nonlocally, the UNWINDFORMS are executed anyway."
a921960 @hraberg adding arglists to special forms
authored
422 {:arglists '([BODYFORM UNWINDFORMS...])}
b586e4c @hraberg a first stab at the Emacs Lisp special forms
authored
423 [bodyform & unwindforms]
1990ddf @hraberg Missing back tick
authored
424 `(try
47bc439 @hraberg New evaluation model, take 1. Generates .clj that compiles to .class …
authored
425 ~(el->clj bodyform)
426 (finally (progn ~@unwindforms))))
3d5ee87 @hraberg special forms in their own file
authored
427
428 (c/defmacro condition-case
429 "Regain control when an error is signaled.
430 Executes BODYFORM and returns its value if no error happens.
431 Each element of HANDLERS looks like (CONDITION-NAME BODY...)
4beb057 @hraberg Regenerated all stubs for 24.1. Removed ert, as its now included in E…
authored
432 where the BODY is made of Lisp expressions.
433
434 A handler is applicable to an error
435 if CONDITION-NAME is one of the error's condition names.
436 If an error happens, the first applicable handler is run.
437
438 The car of a handler may be a list of condition names instead of a
439 single condition name; then it handles all of them. If the special
440 condition name `debug' is present in this list, it allows another
441 condition in the list to run the debugger if `debug-on-error' and the
442 other usual mechanisms says it should (otherwise, `condition-case'
443 suppresses the debugger).
444
445 When a handler handles an error, control returns to the `condition-case'
446 and it executes the handler's BODY...
447 with VAR bound to (ERROR-SYMBOL . SIGNAL-DATA) from the error.
448 (If VAR is nil, the handler can't access that information.)
449 Then the value of the last BODY form is returned from the `condition-case'
450 expression.
451
452 See also the function `signal' for more info."
a921960 @hraberg adding arglists to special forms
authored
453 {:arglists '([VAR BODYFORM &rest HANDLERS])}
b586e4c @hraberg a first stab at the Emacs Lisp special forms
authored
454 [var bodyform & handlers]
47bc439 @hraberg New evaluation model, take 1. Generates .clj that compiles to .class …
authored
455 (c/let [var (if (= () var) nil var)]
18f7d1e @hraberg Retaining metadata during various transformations so the generated Cl…
authored
456 `(try
457 ~(el->clj bodyform)
458 (catch ExceptionInfo e#
459 (c/let [~(if var var (gensym "_")) (cons/pair (:tag (ex-data e#))
460 (:value (ex-data e#)))]
461 (case (:tag (ex-data e#))
462 ~@(apply concat (for [[c & h] handlers
463 :let [c (if (seq? c) c [c])]]
464 (apply concat (for [c c] `[~(sym c) (progn ~@h)]))))
465 (throw e#)))))))
3d5ee87 @hraberg special forms in their own file
authored
466
467 (c/defmacro cond
468 "Try each clause until one succeeds.
469 Each clause looks like (CONDITION BODY...). CONDITION is evaluated
470 and, if the value is non-nil, this clause succeeds:
471 then the expressions in BODY are evaluated and the last one's
472 value is the value of the cond-form.
473 If no clause succeeds, cond returns nil.
474 If a clause has one element, as in (CONDITION),
475 CONDITION's value if non-nil is returned from the cond-form."
a921960 @hraberg adding arglists to special forms
authored
476 {:arglists '([CLAUSES...])}
b586e4c @hraberg a first stab at the Emacs Lisp special forms
authored
477 [& clauses]
efba37a @hraberg Backtick to the future
authored
478 `(c/cond
479 ~@(->> clauses
47bc439 @hraberg New evaluation model, take 1. Generates .clj that compiles to .class …
authored
480 (map #(do [`(not-null? ~(el->clj (first %)))
f55777b @hraberg Major bug in cond, didn't support nil as actual expression to evaluat…
authored
481 (if (= 1 (count %)) (el->clj (first %)) `(progn ~@(rest %)))]))
efba37a @hraberg Backtick to the future
authored
482 (apply concat))))
ffa5266 @hraberg Start of Loadup!
authored
483
868bbff @hraberg Proper / in symbols, setq-default, last modified check for el vs gene…
authored
484 (c/defmacro setq-helper* [default? sym-vals]
7fe9976 @hraberg Welcome to GNU Emacs
authored
485 (c/let [emacs-lisp? (= (the-ns 'deuce.emacs) *ns*)]
18f7d1e @hraberg Retaining metadata during various transformations so the generated Cl…
authored
486 `(c/let
487 ~(reduce into []
488 (for [[s v] (partition 2 2 nil sym-vals)
489 :let [s (sym s)]]
490 [(sym s) (if default?
491 `(el-var-set-default ~s ~(if emacs-lisp? (el->clj v) v))
492 `(el-var-set ~s ~(if emacs-lisp? (el->clj v) v)))]))
493 ~(first (last (partition 2 2 nil sym-vals))))))
7b93e60 @hraberg Another battle against local setq. Explicit use of macroexpand-all I …
authored
494
3d5ee87 @hraberg special forms in their own file
authored
495 (c/defmacro setq
496 "Set each SYM to the value of its VAL.
497 The symbols SYM are variables; they are literal (not evaluated).
498 The values VAL are expressions; they are evaluated.
499 Thus, (setq x (1+ y)) sets `x' to the value of `(1+ y)'.
500 The second VAL is not computed until after the first SYM is set, and so on;
501 each VAL can use the new value of variables set earlier in the `setq'.
502 The return value of the `setq' form is the value of the last VAL."
a921960 @hraberg adding arglists to special forms
authored
503 {:arglists '([[SYM VAL]...])}
b586e4c @hraberg a first stab at the Emacs Lisp special forms
authored
504 [& sym-vals]
d9d73b2 @hraberg Small bits
authored
505 `(setq-helper* false ~sym-vals))
b586e4c @hraberg a first stab at the Emacs Lisp special forms
authored
506
507 (c/defmacro ^:clojure-special-form quote
4beb057 @hraberg Regenerated all stubs for 24.1. Removed ert, as its now included in E…
authored
508 "Return the argument, without evaluating it. `(quote x)' yields `x'.
509 Warning: `quote' does not construct its return value, but just returns
510 the value that was pre-constructed by the Lisp reader (see info node
511 `(elisp)Printed Representation').
512 This means that '(a . b) is not identical to (cons 'a 'b): the former
513 does not cons. Quoting should be reserved for constants that will
514 never be modified by side-effects, unless you like self-modifying code.
515 See the common pitfall in info node `(elisp)Rearrangement' for an example
516 of unexpected results when a quoted object is modified."
a921960 @hraberg adding arglists to special forms
authored
517 {:arglists '([ARG])}
b586e4c @hraberg a first stab at the Emacs Lisp special forms
authored
518 [arg]
519 `(quote ~arg))
3d5ee87 @hraberg special forms in their own file
authored
520
8559ec8 @hraberg Corner case with unquote-splicing when single element
authored
521 ;; Revisit using Atoms, will make closure capture easier. We use the *dynamic-vars* var for dynamic scope anyway.
01790c5 @hraberg Emacs Lisp can unquote splice an atom at the last position of a list.…
authored
522 ;; Bindings refering to other bindings and modifying them don't work properly.
523 ;; The vars must be created here instead of in with-local-el-vars (which might be removed).
825e271 @hraberg let* bindings that use delayed-eval doesn't work, hack for a few know…
authored
524 ;; Everytime you make a 'sane' assumption you're bound to find some Emacs Lisp breaking it:
01790c5 @hraberg Emacs Lisp can unquote splice an atom at the last position of a list.…
authored
525 ;; (let* ((x 2) (y (setq x 4))) (+ x y)) => 8
825e271 @hraberg let* bindings that use delayed-eval doesn't work, hack for a few know…
authored
526 ;; Also: Needs to support delayed-eval referring to earlier bindings on rhs. (currently requires the binding to be in &env).
b8540c6 @hraberg find-file
authored
527 ;; Need to deal with dots in symbols here. desktop.el has things like (let ((q.txt "something..")))
3260524 @hraberg A first attempt to establish a master namespace for all Emacs Lisp
authored
528 (c/defmacro let-helper* [can-refer? varlist & body]
5edfa65 @hraberg Some ugly compensation stuff for nested lets
authored
529 (c/let [varlist (map #(if (symbol? %) [% nil] %) varlist)
4de811c @hraberg Defense against dots in local vars, like q.txt in desktop.el
authored
530 illegal-symbols (into {} (map #(c/let [v (name (first %))]
18f7d1e @hraberg Retaining metadata during various transformations so the generated Cl…
authored
531 (when (re-find #"\." v)
532 [(first %)
533 (sym (s/replace v "." "_dot_"))]))
4de811c @hraberg Defense against dots in local vars, like q.txt in desktop.el
authored
534 varlist))
535 all-vars (map (comp sym first) (w/postwalk-replace illegal-symbols varlist))
47bc439 @hraberg New evaluation model, take 1. Generates .clj that compiles to .class …
authored
536 temps (zipmap all-vars (repeatedly #(gensym "local__")))]
18f7d1e @hraberg Retaining metadata during various transformations so the generated Cl…
authored
537 `(c/let ~(vec (concat
538 (interleave (map (if can-refer? identity temps) all-vars)
539 (map (comp el->clj second) varlist))
540 (when-not can-refer? (interleave all-vars (map temps all-vars)))))
541 (with-local-el-vars ~(interleave all-vars all-vars)
542 (progn ~@(if (seq illegal-symbols) (w/postwalk-replace illegal-symbols body) body))))))
0d185a8 @hraberg Lexical varibles in let/let* coexisting with dynamic globals. Support…
authored
543
3d5ee87 @hraberg special forms in their own file
authored
544 (c/defmacro let
545 "Bind variables according to VARLIST then eval BODY.
546 The value of the last form in BODY is returned.
547 Each element of VARLIST is a symbol (which is bound to nil)
548 or a list (SYMBOL VALUEFORM) (which binds SYMBOL to the value of VALUEFORM).
549 All the VALUEFORMs are evalled before any symbols are bound."
a921960 @hraberg adding arglists to special forms
authored
550 {:arglists '([VARLIST BODY...])}
b586e4c @hraberg a first stab at the Emacs Lisp special forms
authored
551 [varlist & body]
3260524 @hraberg A first attempt to establish a master namespace for all Emacs Lisp
authored
552 `(let-helper* false ~varlist ~@body))
3d5ee87 @hraberg special forms in their own file
authored
553
554 (c/defmacro defconst
555 "Define SYMBOL as a constant variable.
4beb057 @hraberg Regenerated all stubs for 24.1. Removed ert, as its now included in E…
authored
556 This declares that neither programs nor users should ever change the
557 value. This constancy is not actually enforced by Emacs Lisp, but
558 SYMBOL is marked as a special variable so that it is never lexically
559 bound.
560
561 The `defconst' form always sets the value of SYMBOL to the result of
562 evalling INITVALUE. If SYMBOL is buffer-local, its default value is
563 what is set; buffer-local values are not affected. If SYMBOL has a
564 local binding, then this form sets the local binding's value.
565 However, you should normally not make local bindings for variables
566 defined with this form.
567
568 The optional DOCSTRING specifies the variable's documentation string."
a921960 @hraberg adding arglists to special forms
authored
569 {:arglists '([SYMBOL INITVALUE [DOCSTRING]])}
b586e4c @hraberg a first stab at the Emacs Lisp special forms
authored
570 [symbol initvalue & [docstring]]
7fe9976 @hraberg Welcome to GNU Emacs
authored
571 (c/let [symbol (sym symbol)]
699e06c @hraberg Emacs Lisp Macros, take 1
authored
572 `(do
573 (-> (intern (create-ns 'deuce.emacs-lisp.globals)
574 '~symbol
47bc439 @hraberg New evaluation model, take 1. Generates .clj that compiles to .class …
authored
575 ~(el->clj initvalue))
699e06c @hraberg Emacs Lisp Macros, take 1
authored
576 (alter-meta! merge {:doc ~(apply str docstring)}))
577 '~symbol)))
3d5ee87 @hraberg special forms in their own file
authored
578
579 (c/defmacro prog1
580 "Eval FIRST and BODY sequentially; return value from FIRST.
581 The value of FIRST is saved during the evaluation of the remaining args,
582 whose values are discarded."
a921960 @hraberg adding arglists to special forms
authored
583 {:arglists '([FIRST BODY...])}
b586e4c @hraberg a first stab at the Emacs Lisp special forms
authored
584 [first & body]
47bc439 @hraberg New evaluation model, take 1. Generates .clj that compiles to .class …
authored
585 `(c/let [result# ~(el->clj first)]
18f7d1e @hraberg Retaining metadata during various transformations so the generated Cl…
authored
586 (progn ~@body)
587 result#))
b586e4c @hraberg a first stab at the Emacs Lisp special forms
authored
588
589 (c/defmacro prog2
590 "Eval FORM1, FORM2 and BODY sequentially; return value from FORM2.
591 The value of FORM2 is saved during the evaluation of the
592 remaining args, whose values are discarded."
593 {:arglists '([FORM1 FORM2 BODY...])}
594 [form1 form2 & body]
47bc439 @hraberg New evaluation model, take 1. Generates .clj that compiles to .class …
authored
595 `(progn ~form1
596 (prog1 ~form2
597 ~@body)))
3d5ee87 @hraberg special forms in their own file
authored
598
599 (c/defmacro setq-default
600 "Set the default value of variable VAR to VALUE.
601 VAR, the variable name, is literal (not evaluated);
602 VALUE is an expression: it is evaluated and its value returned.
603 The default value of a variable is seen in buffers
4beb057 @hraberg Regenerated all stubs for 24.1. Removed ert, as its now included in E…
authored
604 that do not have their own values for the variable.
605
606 More generally, you can use multiple variables and values, as in
607 (setq-default VAR VALUE VAR VALUE...)
608 This sets each VAR's default value to the corresponding VALUE.
609 The VALUE for the Nth VAR can refer to the new default values
610 of previous VARs."
a921960 @hraberg adding arglists to special forms
authored
611 {:arglists '([[VAR VALUE]...])}
b586e4c @hraberg a first stab at the Emacs Lisp special forms
authored
612 [& var-values]
d9d73b2 @hraberg Small bits
authored
613 `(setq-helper* true ~var-values))
3d5ee87 @hraberg special forms in their own file
authored
614
615 (c/defmacro or
616 "Eval args until one of them yields non-nil, then return that value.
617 The remaining args are not evalled at all.
618 If all args return nil, return nil."
a921960 @hraberg adding arglists to special forms
authored
619 {:arglists '([CONDITIONS...])}
b586e4c @hraberg a first stab at the Emacs Lisp special forms
authored
620 [& conditions]
47bc439 @hraberg New evaluation model, take 1. Generates .clj that compiles to .class …
authored
621 `(c/or ~@(map #(do `(not-null? ~(el->clj %))) conditions)))
3d5ee87 @hraberg special forms in their own file
authored
622
623 (c/defmacro while
624 "If TEST yields non-nil, eval BODY... and repeat.
625 The order of execution is thus TEST, BODY, TEST, BODY and so on
626 until TEST returns nil."
a921960 @hraberg adding arglists to special forms
authored
627 {:arglists '([TEST BODY...])}
b586e4c @hraberg a first stab at the Emacs Lisp special forms
authored
628 [test & body]
47bc439 @hraberg New evaluation model, take 1. Generates .clj that compiles to .class …
authored
629 `(c/while (not-null? ~(el->clj test)) (progn ~@body)))
3d5ee87 @hraberg special forms in their own file
authored
630
631 (c/defmacro defmacro
632 "Define NAME as a macro.
633 The actual definition looks like
634 (macro lambda ARGLIST [DOCSTRING] [DECL] BODY...).
635 When the macro is called, as in (NAME ARGS...),
636 the function (lambda ARGLIST BODY...) is applied to
637 the list ARGS... as it appears in the expression,
4beb057 @hraberg Regenerated all stubs for 24.1. Removed ert, as its now included in E…
authored
638 and the result should be a form to be evaluated instead of the original.
639
640 DECL is a declaration, optional, which can specify how to indent
641 calls to this macro, how Edebug should handle it, and which argument
642 should be treated as documentation. It looks like this:
643 (declare SPECS...)
644 The elements can look like this:
645 (indent INDENT)
646 Set NAME's `lisp-indent-function' property to INDENT.
647
648 (debug DEBUG)
649 Set NAME's `edebug-form-spec' property to DEBUG. (This is
650 equivalent to writing a `def-edebug-spec' for the macro.)
651
652 (doc-string ELT)
653 Set NAME's `doc-string-elt' property to ELT."
a921960 @hraberg adding arglists to special forms
authored
654 {:arglists '([NAME ARGLIST [DOCSTRING] [DECL] BODY...])}
699e06c @hraberg Emacs Lisp Macros, take 1
authored
655 [name arglist & body]
7fe9976 @hraberg Welcome to GNU Emacs
authored
656 (c/let [name (sym name)]
18f7d1e @hraberg Retaining metadata during various transformations so the generated Cl…
authored
657 `(do
658 ~(when-not ((ns-interns 'deuce.emacs-lisp) name)
659 `(def-helper* c/defmacro ~name ~arglist ~@body))
660 '~name)))
3d5ee87 @hraberg special forms in their own file
authored
661
662 (c/defmacro function
663 "Like `quote', but preferred for objects which are functions.
664 In byte compilation, `function' causes its argument to be compiled.
665 `quote' cannot do that."
a921960 @hraberg adding arglists to special forms
authored
666 {:arglists '([ARG])}
b586e4c @hraberg a first stab at the Emacs Lisp special forms
authored
667 [arg]
37782c0 @hraberg Parsing Emacs Lisp characters builds character.
authored
668 (if (c/and (seq? arg) (symbol? (first arg)) (= 'lambda (sym (first arg))))
6e2e93a @hraberg Fix for lambdas inside (function)
authored
669 (el->clj arg)
37782c0 @hraberg Parsing Emacs Lisp characters builds character.
authored
670 `(quote ~arg)))
3d5ee87 @hraberg special forms in their own file
authored
671
672 (c/defmacro and
673 "Eval args until one of them yields nil, then return nil.
674 The remaining args are not evalled at all.
675 If no arg yields nil, return the last arg's value."
a921960 @hraberg adding arglists to special forms
authored
676 {:arglists '([CONDITIONS...])}
b586e4c @hraberg a first stab at the Emacs Lisp special forms
authored
677 [& conditions]
47bc439 @hraberg New evaluation model, take 1. Generates .clj that compiles to .class …
authored
678 `(c/and ~@(map #(do `(not-null? ~(el->clj %))) conditions)))
3d5ee87 @hraberg special forms in their own file
authored
679
680 (c/defmacro progn
681 "Eval BODY forms sequentially and return value of last one."
a921960 @hraberg adding arglists to special forms
authored
682 {:arglists '([BODY...])}
b586e4c @hraberg a first stab at the Emacs Lisp special forms
authored
683 [& body]
47bc439 @hraberg New evaluation model, take 1. Generates .clj that compiles to .class …
authored
684 `(do ~@(map el->clj body)))
3d5ee87 @hraberg special forms in their own file
authored
685
b586e4c @hraberg a first stab at the Emacs Lisp special forms
authored
686 (c/defmacro ^:clojure-special-form let*
3d5ee87 @hraberg special forms in their own file
authored
687 "Bind variables according to VARLIST then eval BODY.
688 The value of the last form in BODY is returned.
689 Each element of VARLIST is a symbol (which is bound to nil)
690 or a list (SYMBOL VALUEFORM) (which binds SYMBOL to the value of VALUEFORM).
691 Each VALUEFORM can refer to the symbols already bound by this VARLIST."
a921960 @hraberg adding arglists to special forms
authored
692 {:arglists '([VARLIST BODY...])}
b586e4c @hraberg a first stab at the Emacs Lisp special forms
authored
693 [varlist & body]
d9d73b2 @hraberg Small bits
authored
694 `(let-helper* true ~varlist ~@body))
3d5ee87 @hraberg special forms in their own file
authored
695
5cf9716 @hraberg Breaking Build. Actually evaluating the Emacs Lisp loaded more proper…
authored
696 (defn defvar-helper* [ns symbol & [initvalue docstring]]
7fe9976 @hraberg Welcome to GNU Emacs
authored
697 (c/let [symbol (sym symbol)
47bc439 @hraberg New evaluation model, take 1. Generates .clj that compiles to .class …
authored
698 ^Var default (global symbol)
b83e685 @hraberg More plist/meta. defvar takes default value if already existing..
authored
699 m (meta default)]
700 (->
47bc439 @hraberg New evaluation model, take 1. Generates .clj that compiles to .class …
authored
701 ^Var (intern (create-ns ns)
702 symbol
703 (c/or (when default
704 (.getRawRoot default))
705 initvalue))
b83e685 @hraberg More plist/meta. defvar takes default value if already existing..
authored
706 .setDynamic
707 (alter-meta! merge (merge m {:doc (apply str docstring)})))
708 symbol))
fcf5181 @hraberg Meta from var to fns now works, problem wasn't were I thought it was.
authored
709
3d5ee87 @hraberg special forms in their own file
authored
710 (c/defmacro defvar
711 "Define SYMBOL as a variable, and return SYMBOL.
4beb057 @hraberg Regenerated all stubs for 24.1. Removed ert, as its now included in E…
authored
712 You are not required to define a variable in order to use it, but
713 defining it lets you supply an initial value and documentation, which
714 can be referred to by the Emacs help facilities and other programming
715 tools. The `defvar' form also declares the variable as \"special\",
716 so that it is always dynamically bound even if `lexical-binding' is t.
717
718 The optional argument INITVALUE is evaluated, and used to set SYMBOL,
719 only if SYMBOL's value is void. If SYMBOL is buffer-local, its
720 default value is what is set; buffer-local values are not affected.
721 If INITVALUE is missing, SYMBOL's value is not set.
722
723 If SYMBOL has a local binding, then this form affects the local
724 binding. This is usually not what you want. Thus, if you need to
725 load a file defining variables, with this form or with `defconst' or
726 `defcustom', you should always load that file _outside_ any bindings
727 for these variables. (`defconst' and `defcustom' behave similarly in
728 this respect.)
729
730 The optional argument DOCSTRING is a documentation string for the
731 variable.
732
733 To define a user option, use `defcustom' instead of `defvar'.
734 The function `user-variable-p' also identifies a variable as a user
735 option if its DOCSTRING starts with *, but this behavior is obsolete."
a921960 @hraberg adding arglists to special forms
authored
736 {:arglists '([SYMBOL &optional INITVALUE DOCSTRING])}
b586e4c @hraberg a first stab at the Emacs Lisp special forms
authored
737 [symbol & [initvalue docstring]]
47bc439 @hraberg New evaluation model, take 1. Generates .clj that compiles to .class …
authored
738 (c/let [emacs-lisp? (= (the-ns 'deuce.emacs) *ns*)]
18f7d1e @hraberg Retaining metadata during various transformations so the generated Cl…
authored
739 `(defvar-helper* 'deuce.emacs-lisp.globals '~(sym symbol)
740 ~(if emacs-lisp? (el->clj initvalue) initvalue) ~docstring)))
b586e4c @hraberg a first stab at the Emacs Lisp special forms
authored
741
8e5ce83 @hraberg Consistentcy
authored
742 ;; defined as fn in eval.clj
16c92de @hraberg A test for catch
authored
743 (c/defmacro ^:clojure-special-form throw
b586e4c @hraberg a first stab at the Emacs Lisp special forms
authored
744 "Throw to the catch for TAG and return VALUE from it.
745 Both TAG and VALUE are evalled."
16c92de @hraberg A test for catch
authored
746 {:arglists '([TAG VALUE])}
747 [tag value]
9f8d999 @hraberg In flight work
authored
748 `(throw* ~tag ~value))
b586e4c @hraberg a first stab at the Emacs Lisp special forms
authored
749
750 (c/defmacro ^:clojure-special-form catch
3d5ee87 @hraberg special forms in their own file
authored
751 "Eval BODY allowing nonlocal exits using `throw'.
4beb057 @hraberg Regenerated all stubs for 24.1. Removed ert, as its now included in E…
authored
752 TAG is evalled to get the tag to use; it must not be nil.
753
754 Then the BODY is executed.
755 Within BODY, a call to `throw' with the same TAG exits BODY and this `catch'.
756 If no throw happens, `catch' returns the value of the last BODY form.
757 If a throw happens, it specifies the value to return from `catch'."
a921960 @hraberg adding arglists to special forms
authored
758 {:arglists '([TAG BODY...])}
b586e4c @hraberg a first stab at the Emacs Lisp special forms
authored
759 [tag & body]
760 `(try
47bc439 @hraberg New evaluation model, take 1. Generates .clj that compiles to .class …
authored
761 (progn ~@body)
9f8d999 @hraberg In flight work
authored
762 (catch ExceptionInfo e#
763 (if (= ~(el->clj tag) (:tag (ex-data e#)))
764 (:value (ex-data e#))
7d4ccdb @hraberg Slightly cleaaned up version of this pcase/minibuffer hack, using Ema…
authored
765 (throw e#)))
766 (catch Exception e#
767 (c/let [tag# (resolve ~tag)]
18f7d1e @hraberg Retaining metadata during various transformations so the generated Cl…
authored
768 (if (c/and tag# (instance? tag# (cause e#)))
769 e#
770 (throw e#))))))
b586e4c @hraberg a first stab at the Emacs Lisp special forms
authored
771
772 (c/defmacro ^:clojure-special-form if
3d5ee87 @hraberg special forms in their own file
authored
773 "If COND yields non-nil, do THEN, else do ELSE...
774 Returns the value of THEN or the value of the last of the ELSE's.
775 THEN must be one expression, but ELSE... can be zero or more expressions.
776 If COND yields nil, and there are no ELSE's, the value is nil."
a921960 @hraberg adding arglists to special forms
authored
777 {:arglists '([COND THEN ELSE...])}
b586e4c @hraberg a first stab at the Emacs Lisp special forms
authored
778 [cond then & else]
47bc439 @hraberg New evaluation model, take 1. Generates .clj that compiles to .class …
authored
779 `(c/cond (not-null? ~(el->clj cond)) ~(el->clj then)
780 :else (progn ~@else)))
69e7dec @hraberg move all editor/buffer stuff out of the way
authored
781
782 (c/defmacro save-restriction
783 "Execute BODY, saving and restoring current buffer's restrictions.
784 The buffer's restrictions make parts of the beginning and end invisible.
785 (They are set up with `narrow-to-region' and eliminated with `widen'.)
786 This special form, `save-restriction', saves the current buffer's restrictions
787 when it is entered, and restores them when it is exited.
788 So any `narrow-to-region' within BODY lasts only until the end of the form.
789 The old restrictions settings are restored
4beb057 @hraberg Regenerated all stubs for 24.1. Removed ert, as its now included in E…
authored
790 even in case of abnormal exit (throw or error).
791
792 The value returned is the value of the last form in BODY.
793
794 Note: if you are using both `save-excursion' and `save-restriction',
795 use `save-excursion' outermost:
796 (save-excursion (save-restriction ...))"
a921960 @hraberg adding arglists to special forms
authored
797 {:arglists '([&rest BODY])}
f32ee82 @hraberg Removing a few macros that actually are in subr.el. Default bodies th…
authored
798 [& body]
0a9402c @hraberg First passing Zile test. NPE deref in save-excursion and save-restric…
authored
799 `(c/let [current-buffer# ~(with-meta `((fun 'current-buffer)) {:tag 'deuce.emacs.data.Buffer})
800 begv# @(.begv current-buffer#)
801 zv# @(.zv current-buffer#)]
802 (try
803 (progn ~@body)
804 (finally
805 ((fun 'narrow-to-region) begv# zv#)))))
69e7dec @hraberg move all editor/buffer stuff out of the way
authored
806
807 (c/defmacro save-excursion
808 "Save point, mark, and current buffer; execute BODY; restore those things.
809 Executes BODY just like `progn'.
810 The values of point, mark and the current buffer are restored
811 even in case of abnormal exit (throw or error).
4beb057 @hraberg Regenerated all stubs for 24.1. Removed ert, as its now included in E…
authored
812 The state of activation of the mark is also restored.
813
814 This construct does not save `deactivate-mark', and therefore
815 functions that change the buffer will still cause deactivation
816 of the mark at the end of the command. To prevent that, bind
817 `deactivate-mark' with `let'.
818
819 If you only want to save the current buffer but not point nor mark,
820 then just use `save-current-buffer', or even `with-current-buffer'."
f32ee82 @hraberg Removing a few macros that actually are in subr.el. Default bodies th…
authored
821 [& body]
fa55b93 @hraberg Basic buffers
authored
822 `(c/let [current-buffer# ((fun 'current-buffer))
823 point# ((fun 'point))
824 mark# ((fun 'mark-marker))]
18f7d1e @hraberg Retaining metadata during various transformations so the generated Cl…
authored
825 (try
826 (progn ~@body)
827 (finally
828 ((fun 'set-buffer) current-buffer#)
829 ((fun 'goto-char) point#)
0a9402c @hraberg First passing Zile test. NPE deref in save-excursion and save-restric…
authored
830 ((fun 'set-marker) mark# ((fun 'marker-position) mark#) current-buffer#)))))
69e7dec @hraberg move all editor/buffer stuff out of the way
authored
831
832 (c/defmacro interactive
833 "Specify a way of parsing arguments for interactive use of a function.
834 For example, write
835 (defun foo (arg buf) \"Doc string\" (interactive \"P\\nbbuffer: \") .... )
836 to make ARG be the raw prefix argument, and set BUF to an existing buffer,
837 when `foo' is called as a command.
838 The \"call\" to `interactive' is actually a declaration rather than a function;
839 it tells `call-interactively' how to read arguments
840 to pass to the function.
4beb057 @hraberg Regenerated all stubs for 24.1. Removed ert, as its now included in E…
authored
841 When actually called, `interactive' just returns nil.
842
843 Usually the argument of `interactive' is a string containing a code letter
844 followed optionally by a prompt. (Some code letters do not use I/O to get
845 the argument and do not use prompts.) To get several arguments, concatenate
846 the individual strings, separating them by newline characters.
847 Prompts are passed to format, and may use % escapes to print the
848 arguments that have already been read.
849 If the argument is not a string, it is evaluated to get a list of
850 arguments to pass to the function.
851 Just `(interactive)' means pass no args when calling interactively.
852
853 Code letters available are:
854 a -- Function name: symbol with a function definition.
855 b -- Name of existing buffer.
856 B -- Name of buffer, possibly nonexistent.
857 c -- Character (no input method is used).
858 C -- Command name: symbol with interactive function definition.
859 d -- Value of point as number. Does not do I/O.
860 D -- Directory name.
861 e -- Parameterized event (i.e., one that's a list) that invoked this command.
862 If used more than once, the Nth `e' returns the Nth parameterized event.
863 This skips events that are integers or symbols.
864 f -- Existing file name.
865 F -- Possibly nonexistent file name.
866 G -- Possibly nonexistent file name, defaulting to just directory name.
867 i -- Ignored, i.e. always nil. Does not do I/O.
868 k -- Key sequence (downcase the last event if needed to get a definition).
869 K -- Key sequence to be redefined (do not downcase the last event).
870 m -- Value of mark as number. Does not do I/O.
871 M -- Any string. Inherits the current input method.
872 n -- Number read using minibuffer.
873 N -- Numeric prefix arg, or if none, do like code `n'.
874 p -- Prefix arg converted to number. Does not do I/O.
875 P -- Prefix arg in raw form. Does not do I/O.
876 r -- Region: point and mark as 2 numeric args, smallest first. Does no I/O.
877 s -- Any string. Does not inherit the current input method.
878 S -- Any symbol.
879 U -- Mouse up event discarded by a previous k or K argument.
880 v -- Variable name: symbol that is user-variable-p.
881 x -- Lisp expression read but not evaluated.
882 X -- Lisp expression read and evaluated.
883 z -- Coding system.
884 Z -- Coding system, nil if no prefix arg.
885
886 In addition, if the string begins with `*', an error is signaled if
887 the buffer is read-only.
888 If `@' appears at the beginning of the string, and if the key sequence
889 used to invoke the command includes any mouse events, then the window
890 associated with the first of those events is selected before the
891 command is run.
892 If the string begins with `^' and `shift-select-mode' is non-nil,
893 Emacs first calls the function `handle-shift-selection'.
894 You may use `@', `*', and `^' together. They are processed in the
895 order that they appear, before reading any arguments."
a921960 @hraberg adding arglists to special forms
authored
896 {:arglists '([&optional ARGS])}
69e7dec @hraberg move all editor/buffer stuff out of the way
authored
897 [& args])
898
899 (c/defmacro save-current-buffer
900 "Save the current buffer; execute BODY; restore the current buffer.
901 Executes BODY just like `progn'."
a921960 @hraberg adding arglists to special forms
authored
902 {:arglists '([&rest BODY])}
b914552 @hraberg No need for the exclusions. Founce another body-less macro, save-curr…
authored
903 [& body]
fa55b93 @hraberg Basic buffers
authored
904 `(c/let [current-buffer# ((fun 'current-buffer))]
18f7d1e @hraberg Retaining metadata during various transformations so the generated Cl…
authored
905 (try
906 (progn ~@body)
907 (finally
908 ((fun 'set-buffer) current-buffer#)))))
fbb1bed @hraberg Minor optimizations
authored
909
910 (def clojure-special-forms
911 (->> (ns-map 'deuce.emacs-lisp)
912 (filter (comp :clojure-special-form meta val))
913 (into {})))
54db75d @hraberg Passing tests with new cons and error
authored
914
915 (defn check-type [pred x]
fa55b93 @hraberg Basic buffers
authored
916 (if ((fun pred) x)
917 x
85c4cc7 @hraberg Merge branch 'master' into ljos-ConsImpl
authored
918 (deuce.emacs-lisp/throw 'wrong-type-argument (cons/list pred x))))
6be702c @hraberg Moving helper down
authored
919
920 ;; Navgeet's helper macro, will revisit, basically condition-case but for use from Clojure
921 (c/defmacro try-with-tag [& exprs]
922 (c/let [catch-clauses (c/filter #(c/= (first %) 'catch) exprs)
923 finally-clause (c/filter #(c/= (first %) 'finally) exprs)
924 try-exprs (c/remove #(c/or (c/= (first %) 'finally) (c/= (first %) 'catch)) exprs)]
18f7d1e @hraberg Retaining metadata during various transformations so the generated Cl…
authored
925 `(try ~@try-exprs
926 ~@(for [expr catch-clauses]
927 (c/let [[_ tag e & exprs] expr]
928 `(catch ExceptionInfo e#
929 (if (= ~tag (:tag (ex-data e#)))
930 (c/let [~e e#]
931 (do ~@exprs))
932 (throw e#)))))
933 ~@finally-clause)))
Something went wrong with that request. Please try again.