Coverage report: /home/ellis/comp/core/std/prim.lisp
Kind | Covered | All | % |
expression | 2 | 285 | 0.7 |
branch | 0 | 26 | 0.0 |
Key
Not instrumented
Conditionalized out
Executed
Not executed
Both branches taken
One branch taken
Neither branch taken
1
;;; prim.lisp --- Primitive Macros
9
(eval-when (:compile-toplevel :load-toplevel :execute)
10
(defun g!-symbol-p (s)
11
"Return T if S is a G!-symbol (gensym'd)."
13
(> (length (symbol-name s)) 2)
14
(string= (symbol-name s)
19
(defun o!-symbol-p (s)
20
"Return T if S is a O!-symbol (oneshot)."
22
(> (length (symbol-name s)) 2)
23
(string= (symbol-name s)
28
(defun o!-symbol-to-g!-symbol (s)
29
"Convert O!-symbol S to a G!-symbol."
30
(symb "G!" (subseq (symbol-name s) 2))))
32
(defmacro defmacro/g! (name args &body body)
33
"Define a macro with G!-symbols in ARGS automatically converted to gensyms."
34
(let ((syms (remove-duplicates
35
(remove-if-not #'g!-symbol-p
37
(multiple-value-bind (body declarations docstring)
38
(parse-body body :documentation t)
39
`(defmacro ,name ,args
51
(defmacro defmacro! (name args &body body)
52
"Define a macro with G!-symbols in ARGS converted to gensyms and O!-symbols
53
evaluated once and bound to a G!-symbol for use in BODY."
54
(let* ((os (remove-if-not #'o!-symbol-p (flatten* args)))
55
(gs (mapcar #'o!-symbol-to-g!-symbol os)))
56
(multiple-value-bind (body declarations docstring)
57
(parse-body body :documentation t)
58
`(defmacro/g! ,name ,args
62
`(let ,(mapcar #'list (list ,@gs) (list ,@os))
65
(defmacro defun! (name args &body body)
66
"Define a function with G!-symbols in ARGS automatically converted."
67
(let ((syms (remove-duplicates
68
(remove-if-not #'g!-symbol-p
70
(multiple-value-bind (body declarations docstring)
71
(parse-body body :documentation t)
76
(let ,(mapcar (lambda (s)
77
`(,s (gensym ,(subseq (symbol-name s)
83
(defun unquote-args (lst args)
84
"Makes a list suitable for use inside macros (sort-of), by building a
85
new list quoting every symbol in @arg{lst} other than those in @arg{args}.
86
CAUTION: DO NOT use backquotes!
90
> (unquote-args '(+ x y z) '(x y))
93
> (unquote-args '(let ((x 1)) (+ x 1)) '(x))
94
=> (LIST 'LET (LIST (LIST X '1)) (LIST '+ X '1))
96
(maptree-if #'(lambda (x) (or (symbolp x) (consp x)))
97
#'(lambda (x) (etypecase x
98
(symbol (if (member x args) x `(quote ,x)))
99
(cons (values `(list ,@x) #'(lambda (f x) (cons (first x) (mapcar f (cdr x))))))))
102
(defmacro definline (name lambda-list &body body)
103
"Define an inlined function."
105
(declaim (inline ,name))
106
(defun ,name ,lambda-list ,@body)))
108
(defmacro defnotinline (name lambda-list &body body)
110
(declaim (notinline ,name))
111
(defun ,name ,lambda-list ,@body)))
113
(defmacro with-optimization ((&rest args) &body body)
114
"Create a local environment with optimization declarations ARGS and execute
119
`(with-optimization (:speed 2 :safety 3)
121
;; (LOCALLY (DECLARE (OPTIMIZE (SPEED 2) (SAFETY 3))) (+ 1.0d0 2.0d0))"
124
`(declare (optimize ,@(multiple-value-call #'mapcar #'(lambda (key val) (list (intern (symbol-name key)) val))
125
(loop :for ele :in args
126
:counting t :into cnt
128
:collect ele into key
130
:collect (progn (assert (member ele '(0 1 2 3))) ele) into val
131
:finally (return (values key val))))))
132
(when (and (consp (car body)) (eq (caar body) 'declare))
134
,@(if (and (consp (car body)) (eq (caar body) 'declare)) (cdr body) body)))
136
(defmacro macrofy (lambda-func)
137
"Macrofies a lambda function, for use later inside macros. Returns a
138
macro-function like function which can be called later for use
141
DO NOT USE backquotes in the lambda function!
144
(macroexpand-1 `(macrofy (lambda (x y z) (+ (sin x) y (apply #'cos (list z))))))
146
;; (LIST '+ (LIST 'SIN X) Y (LIST 'APPLY (LIST 'FUNCTION 'COS) (LIST 'LIST Z))))
149
(funcall (macrofy (lambda (x y z) (+ (sin x) y (apply #'cos (list z))))) 'a 'b 'c)
150
;; (+ (SIN A) B (APPLY #'COS (LIST C)))"
151
(destructuring-bind (labd args &rest body) lambda-func
152
(assert (eq labd 'lambda))
153
`(lambda ,args ,@(cdr (unquote-args body args)))))
155
(defmacro with-marking (&rest body)
157
This macro basically declares local-variables globally,
158
while keeping semantics and scope local.
163
(loop :for i := 0 :then (1+ i)
164
:do (mark* ((xi (* 10 2) :type index-type)
165
(sum 0 :type index-type))
166
(incf sum (mark (* 10 2)))
170
;; (LET* ((#:G1083 (* 10 2)) (#:SUM1082 0) (#:XI1081 (* 10 2)))
171
;; (DECLARE (TYPE INDEX-TYPE #:SUM1082)
172
;; (TYPE INDEX-TYPE #:XI1081))
173
;; (LOOP :FOR I := 0 :THEN (1+ I)
174
;; :DO (SYMBOL-MACROLET ((XI #:XI1081) (SUM #:SUM1082))
175
;; (INCF SUM #:G1083)
181
(code (maptree '(:mark* :mark :memo)
185
`(symbol-macrolet (,@(mapcar #'(lambda (decl) (destructuring-bind (ref code &key type) decl
186
(let ((rsym (gensym (symbol-name ref))))
187
(push `(,rsym ,code) decls)
189
(push `(type ,type ,rsym) types))
194
(destructuring-bind (code &key type) (cdr mrk)
195
(let ((rsym (gensym)))
196
(push `(,rsym ,code) decls)
198
(push `(type ,type ,rsym) types))
201
(destructuring-bind (code &key type) (cdr mrk)
202
(let ((memo (find code decls :key #'cadr :test #'tree-equal)))
205
(let ((rsym (gensym)))
206
(push `(,rsym ,code) decls)
208
(push `(type ,type ,rsym) types))
212
,@(when types `((declare ,@types)))
215
(defun defunits-chaining (u units prev)
217
(error "~{ ~a~^ depends on~}"
219
(let ((spec (find u units :key #'car)))
221
(error "Unknown unit ~a" u)
222
(let ((chain (cadr spec)))
232
(defmacro using-gensyms ((decl (&rest syms) &optional gensyms) &rest body)
233
`(let ((,decl (zip-list ',(mapcar #'(lambda (x) (gensym (symbol-name x))) syms) (list ,@syms))))
234
(destructuring-bind (,@syms) (mapcar #'car ,decl)
237
`(with-gensyms (,@gensyms)) `(progn))
240
(defmacro binding-gensyms ((mname &optional (fname (gensym))) &rest body)
242
`(let ((,htbl (make-hash-table)))
243
(labels ((,fname (x) (or (gethash x ,htbl) (setf (gethash x ,htbl) (gensym (symbol-name x))))))
244
(macrolet ((,mname (x) `(,', fname ',x)))