set-macros.sl 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. % SET-MACROS.SL - macros for various flavors of assignments
  2. %
  3. % Author: Don Morrison
  4. % Symbolic Computation Group
  5. % Computer Science Dept.
  6. % University of Utah
  7. % Date: Wednesday, 12 May 1982
  8. % Copyright (c) 1981 University of Utah
  9. % <PSL.UTIL>SET-MACROS.SL.2, 12-Oct-82 15:53:58, Edit by BENSON
  10. % Added IGETV to SETF-SAFE list
  11. % Somewhat expanded setf macro. Major difference between this and the builtin
  12. % version is that it always returns the RHS, instead of something
  13. % indeterminant. Note that the setf-safe flag can be used to indicate that
  14. % the assignment function itself returns the "right thing", so setf needn't
  15. % do anything special. Also a lot more functions are represented in this
  16. % version, including c....r (mostly useful for macros) and list/cons (which
  17. % gives a primitive sort of destructuring setf).
  18. (defmacro setf u
  19. (cond
  20. ((atom u) nil)
  21. ((atom (cdr u)) (stderror "Odd number of arguments to setf."))
  22. ((atom (cddr u)) (setf2 (car u) (cadr u)))
  23. (t `(progn ,@(setf1 u)))))
  24. (de setf1 (u)
  25. (cond
  26. ((atom u) nil)
  27. ((atom (cdr u)) (stderror "Odd number of arguments to setf."))
  28. (t (cons (setf2 (car u) (cadr u)) (setf1 (cddr u))))))
  29. (de setf2 (lhs rhs)
  30. (if (atom lhs)
  31. `(setq ,lhs ,rhs)
  32. (cond
  33. ((and (idp (car lhs)) (flagp (car lhs) 'setf-safe))
  34. (expand-setf lhs rhs))
  35. ((atom rhs)
  36. `(progn ,(expand-setf lhs rhs) ,rhs))
  37. (t
  38. `(let ((***SETF-VAR*** ,rhs))
  39. ,(expand-setf lhs '***SETF-VAR***)
  40. ***SETF-VAR***)))))
  41. (de expand-setf (lhs rhs)
  42. (let ((fn (car lhs)) (op))
  43. (cond
  44. ((and (idp fn) (setq op (get fn 'assign-op)))
  45. `(,op ,@(cdr lhs) ,rhs))
  46. ((and (idp fn) (setq op (get fn 'setf-expand)))
  47. (apply op (list lhs rhs)))
  48. ((and (idp fn) (setq op (getd fn)) (eqcar op 'macro))
  49. (expand-setf (apply (cdr op) (list lhs)) rhs))
  50. (t
  51. (expand-setf
  52. (ContinuableError
  53. 99
  54. (BldMsg "%r is not a known form for assignment" `(setf ,lhs ,rhs))
  55. lhs)
  56. rhs)))))
  57. (flag '(getv indx eval value get list cons vector getd igetv) 'setf-safe)
  58. (defmacro-no-displace car-cdr-setf (rplacfn pathfn)
  59. `#'(lambda (lhs rhs) `(,',rplacfn (,',pathfn ,(cadr lhs)) ,rhs)))
  60. (deflist '(
  61. (car rplaca)
  62. (cdr rplacd)
  63. (getv putv)
  64. (igetv iputv)
  65. (indx setindx)
  66. (sub setsub)
  67. (eval set)
  68. (value set)
  69. (get put)
  70. (flagp flag-setf)
  71. (getd getd-setf)
  72. ) 'assign-op)
  73. (remprop 'nth 'assign-op) % Remove default version (which is incorrect anyway)
  74. (deflist `(
  75. (caar ,(car-cdr-setf rplaca car))
  76. (cadr ,(car-cdr-setf rplaca cdr))
  77. (caaar ,(car-cdr-setf rplaca caar))
  78. (cadar ,(car-cdr-setf rplaca cdar))
  79. (caadr ,(car-cdr-setf rplaca cadr))
  80. (caddr ,(car-cdr-setf rplaca cddr))
  81. (caaaar ,(car-cdr-setf rplaca caaar))
  82. (cadaar ,(car-cdr-setf rplaca cdaar))
  83. (caadar ,(car-cdr-setf rplaca cadar))
  84. (caddar ,(car-cdr-setf rplaca cddar))
  85. (caaadr ,(car-cdr-setf rplaca caadr))
  86. (cadadr ,(car-cdr-setf rplaca cdadr))
  87. (caaddr ,(car-cdr-setf rplaca caddr))
  88. (cadddr ,(car-cdr-setf rplaca cdddr))
  89. (cdar ,(car-cdr-setf rplacd car))
  90. (cddr ,(car-cdr-setf rplacd cdr))
  91. (cdaar ,(car-cdr-setf rplacd caar))
  92. (cddar ,(car-cdr-setf rplacd cdar))
  93. (cdadr ,(car-cdr-setf rplacd cadr))
  94. (cdddr ,(car-cdr-setf rplacd cddr))
  95. (cdaaar ,(car-cdr-setf rplacd caaar))
  96. (cddaar ,(car-cdr-setf rplacd cdaar))
  97. (cdadar ,(car-cdr-setf rplacd cadar))
  98. (cdddar ,(car-cdr-setf rplacd cddar))
  99. (cdaadr ,(car-cdr-setf rplacd caadr))
  100. (cddadr ,(car-cdr-setf rplacd cdadr))
  101. (cdaddr ,(car-cdr-setf rplacd caddr))
  102. (cddddr ,(car-cdr-setf rplacd cdddr))
  103. (nth ,#'(lambda (lhs rhs) `(rplaca (pnth ,@(cdr lhs)) ,rhs)))
  104. (pnth ,#'expand-pnth-setf)
  105. (lastcar ,#'(lambda (lhs rhs) `(rplaca (lastpair ,(cadr lhs)) ,rhs)))
  106. (list ,#'list-setf)
  107. (cons ,#'cons-setf)
  108. (vector ,#'vector-setf)
  109. ) 'setf-expand)
  110. (fluid '(*setf-debug))
  111. (de expand-pnth-setf (lhs rhs)
  112. (let ((L (cadr lhs))(n (caddr lhs)))
  113. (cond
  114. ((onep n) `(setf ,L ,rhs))
  115. ((fixp n) `(rplacd (pnth ,L (sub1 ,n)) ,rhs))
  116. (t
  117. (let ((expnsn (errorset `(setf2 ',L ',rhs) *setf-debug *setf-debug)))
  118. (if (atom expnsn)
  119. `(rplacd (pnth ,L (sub1 ,n) ,rhs))
  120. `(let ((***PNTH-SETF-VAR*** ,n))
  121. (if (onep ***PNTH-SETF-VAR***)
  122. ,(car expnsn)
  123. (rplacd (pnth ,L (sub1 ***PNTH-SETF-VAR***)) ,rhs)))))))))
  124. (de flag-setf (nam flg val)
  125. (cond
  126. (val (flag (list nam) flg) t)
  127. (t (remflag (list nam) flg) nil)))
  128. (de getd-setf (trgt src)
  129. (cond
  130. % not correct for the parallel case...
  131. % ((idp src) (copyd trgt src))
  132. ((or (codep src) (eqcar src 'lambda)) % is this kludge worthwhile?
  133. (progn (putd trgt 'expr src) (cons 'expr src)))
  134. ((pairp src)
  135. (progn (putd trgt (car src) (cdr src)) src))
  136. (t
  137. (ContinuableError
  138. 99
  139. (bldmsg "%r is not a funtion spec." src)
  140. src))))
  141. (de list-setf (lhs rhs)
  142. (if (atom rhs)
  143. `(progn ,.(destructure-form (cdr lhs) rhs) ,rhs)
  144. `(let ((***LIST-SETF-VAR*** ,rhs))
  145. ,.(destructure-form (cdr lhs) '***LIST-SETF-VAR***)
  146. ***LIST-SETF-VAR***)))
  147. (de cons-setf (lhs rhs)
  148. (if (atom rhs)
  149. `(progn
  150. (setf ,(cadr lhs) (car ,rhs))
  151. (setf ,(caddr lhs) (cdr ,rhs))
  152. ,rhs)
  153. `(let ((***CONS-SETF-VAR*** ,rhs))
  154. (setf ,(cadr lhs) (car ***CONS-SETF-VAR***))
  155. (setf ,(caddr lhs) (cdr ***CONS-SETF-VAR***))
  156. ***CONS-SETF-VAR***)))
  157. (de vector-setf (lhs rhs)
  158. (let ((x (if (atom rhs) rhs '***VECTOR-SETF-VAR***)))
  159. (let ((L (for (in u (cdr lhs)) (from i 0)
  160. (collect `(setf ,u (getv ,x ,i))))))
  161. (if (atom rhs)
  162. `(progn ,.L ,x)
  163. `(let ((***VECTOR-SETF-VAR*** ,rhs)) ,.L ,x)))))
  164. % Some more useful assignment macros
  165. (defmacro push (item stack) `(setf ,stack (cons ,item ,stack)))
  166. (defmacro pop (stack . rst)
  167. (let ((x `(prog1 (car ,stack) (setf ,stack (cdr ,stack)))))
  168. (if rst `(setf ,(car rst) ,x) x)))
  169. (defmacro adjoin-to (e s) `(setf ,s (adjoin ,e ,s)))
  170. (defmacro adjoinq-to (e s) `(setf ,s (adjoinq ,e ,s)))
  171. (defmacro incr (var . rst)
  172. `(setf ,var ,(if rst `(plus ,var ,@rst) `(add1 ,var))))
  173. (defmacro decr (var . rst)
  174. `(setf ,var ,(if rst `(difference ,var (plus ,@rst)) `(sub1 ,var))))
  175. (defmacro clear L
  176. `(setf ,.(foreach u in L conc `(,u nil))))
  177. % Parallel assignment macros
  178. (defmacro psetq rst
  179. % psetq looks like a multi-arg setq but does its work in parallel.
  180. (cond ((null rst) nil)
  181. ((cddr rst)
  182. `(setq ,(car rst)
  183. (prog1 ,(cadr rst) (psetq . ,(cddr rst)))))
  184. % the last pair. keep it simple; no superfluous
  185. % (prog1 (setq...) (psetq)).
  186. ((cdr rst) `(setq . ,rst))
  187. (t (StdError "psetq passed an odd number of arguments"))))
  188. (defmacro psetf rst
  189. % psetf looks like a multi-arg setf but does its work in parallel.
  190. (cond ((null rst) nil)
  191. ((cddr rst)
  192. `(setf ,(car rst)
  193. (prog1 ,(cadr rst) (psetf . ,(cddr rst)))))
  194. ((cdr rst) `(setf . ,rst))
  195. (t (StdError "psetf passed an odd number of arguments"))))
  196. (defmacro defswitch (nam var . acts)
  197. (let ((read-act (if (pairp acts) (car acts) nil))
  198. (set-acts (if (pairp acts) (cdr acts) nil)))
  199. (when (null var)
  200. (setf var (newid (bldmsg "%w-SWITCH-VAR*" nam))))
  201. `(progn
  202. (fluid '(,var))
  203. (de ,nam () (let ((,nam ,var)) ,read-act) ,var)
  204. (setf
  205. (get ',nam 'assign-op)
  206. #'(lambda (,nam) ,@set-acts (setq ,var ,nam)))
  207. (flag '(,nam) 'setf-safe))))