summaryrefslogtreecommitdiffstats
path: root/share/txr/stdlib/place.tl
diff options
context:
space:
mode:
Diffstat (limited to 'share/txr/stdlib/place.tl')
-rw-r--r--share/txr/stdlib/place.tl970
1 files changed, 0 insertions, 970 deletions
diff --git a/share/txr/stdlib/place.tl b/share/txr/stdlib/place.tl
deleted file mode 100644
index 4e2c7904..00000000
--- a/share/txr/stdlib/place.tl
+++ /dev/null
@@ -1,970 +0,0 @@
-;; Copyright 2015-2020
-;; Kaz Kylheku <kaz@kylheku.com>
-;; Vancouver, Canada
-;; All rights reserved.
-;;
-;; Redistribution and use in source and binary forms, with or without
-;; modification, are permitted provided that the following conditions are met:
-;;
-;; 1. Redistributions of source code must retain the above copyright notice, this
-;; list of conditions and the following disclaimer.
-;;
-;; 2. Redistributions in binary form must reproduce the above copyright notice,
-;; this list of conditions and the following disclaimer in the documentation
-;; and/or other materials provided with the distribution.
-;;
-;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-;; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-;; FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-;; SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-;; CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-;; OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-;; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-(defvar *place-clobber-expander* (hash))
-(defvar *place-update-expander* (hash))
-(defvar *place-delete-expander* (hash))
-(defvar *place-macro* (hash))
-(defvar sys:*pl-env* nil)
-(defvar sys:*pl-form* nil)
-
-(defun sys:eval-err (. params)
- (throwf 'eval-error . params))
-
-(defun sys:sym-update-expander (getter-name setter-name
- place-expr op-body)
- ^(macrolet ((,getter-name () ',place-expr)
- (,setter-name (val-expr) ^(sys:setq ,',place-expr
- ,val-expr)))
- ,op-body))
-
-(defun sys:sym-clobber-expander (simple-setter-name
- place-expr op-body)
- ^(macrolet ((,simple-setter-name (val-expr)
- ^(sys:setq ,',place-expr ,val-expr)))
- ,op-body))
-
-(defun sys:sym-delete-expander (deleter-name
- place-expr . op-body)
- ^(macrolet ((,deleter-name (:env env)
- (when (lexical-var-p env ',place-expr)
- (sys:eval-err "~s is a lexical variable, thus not deletable"
- ',place-expr))
- ^(prog1
- (symbol-value ',',place-expr)
- (makunbound ',',place-expr))))
- ,*op-body))
-
-(defun sys:get-place-macro (sym)
- (or [*place-macro* sym]
- (progn (sys:try-load sym) [*place-macro* sym])))
-
-(defun sys:pl-expand (unex-place env)
- (while t
- (let ((place unex-place)
- pm-expander)
- (while (and (consp place)
- (sys:setq pm-expander (sys:get-place-macro (car place)))
- (sys:setq place (sys:set-macro-ancestor [pm-expander place] place))
- (neq place unex-place))
- (sys:setq unex-place place))
- (sys:setq place (macroexpand-1 place env))
- (when (or (eq place unex-place)
- (null place)
- (and (atom place) (not (symbolp place))))
- (return-from sys:pl-expand place))
- (sys:setq unex-place place))))
-
-(defun place-form-p (unex-place env)
- (let ((place (sys:pl-expand unex-place env)))
- (or (bindable place)
- (and (consp place) [*place-update-expander* (car place)] t))))
-
-(defun get-update-expander (place)
- (cond
- ((symbolp place) (fun sys:sym-update-expander))
- ((consp place) (or [*place-update-expander* (car place)]
- (sys:eval-err "~s is not an assignable place" place)))
- (t (sys:eval-err "form ~s is not syntax denoting an assignable place" place))))
-
-(defun get-clobber-expander (place)
- (cond
- ((symbolp place) (fun sys:sym-clobber-expander))
- ((consp place) (or [*place-clobber-expander* (car place)]
- (iflet ((fun [*place-update-expander* (car place)]))
- (op apply fun (gensym) @1 @2 @rest))
- (sys:eval-err "~s is not an assignable place" place)))
- (t (sys:eval-err "form ~s is not syntax denoting an assignable place" place))))
-
-(defun get-delete-expander (place)
- (cond
- ((symbolp place) (fun sys:sym-delete-expander))
- ((consp place) (or [*place-delete-expander* (car place)]
- (sys:eval-err "~s is not a deletable place" place)))
- (t (sys:eval-err "form ~s is not syntax denoting a deletable place" place))))
-
-(defun sys:r-s-let-expander (bindings body e letsym pred)
- (let ((exp-bindings (mapcar (aret ^(,@1 ,(macroexpand @2 e))) bindings)))
- (let ((renames [keep-if pred exp-bindings second])
- (regular [remove-if pred exp-bindings second]))
- (cond ((and renames regular)
- ^(symacrolet ,renames
- (,letsym ,regular ,*body)))
- (renames ^(symacrolet ,renames ,*body))
- (regular ^(,letsym ,regular ,*body))
- (t ^(progn ,*body))))))
-
-(defmacro rlet (bindings :env e . body)
- [sys:r-s-let-expander bindings body e 'let constantp])
-
-(defmacro slet (bindings :env e . body)
- (sys:r-s-let-expander bindings body e 'let [orf constantp bindable]))
-
-(defmacro alet (bindings :env e . body)
- (let ((exp-bindings (mapcar (aret ^(,@1 ,(macroexpand @2 e))) bindings)))
- (if [some exp-bindings constantp second]
- [sys:r-s-let-expander exp-bindings body e 'alet constantp]
- ^(,(if [all exp-bindings bindable second]
- 'symacrolet 'let)
- ,exp-bindings ,*body))))
-
-(defmacro with-gensyms (syms . body)
- ^(let ,(zip syms (repeat '((gensym)))) ,*body))
-
-(defun sys:propagate-ancestor (to-tree from-form . syms)
- (tree-case to-tree
- ((a . d)
- (when (memq a syms)
- (sys:set-macro-ancestor to-tree from-form))
- (sys:propagate-ancestor a from-form . syms)
- (sys:propagate-ancestor d from-form . syms)))
- to-tree)
-
-(defun call-update-expander (getter setter unex-place env body)
- (sys:propagate-ancestor body unex-place getter setter)
- (let* ((place (sys:pl-expand unex-place env))
- (expander (get-update-expander place))
- (sys:*pl-env* env)
- (sys:*pl-form* unex-place)
- (expansion [expander getter setter place body])
- (expansion-ex (expand expansion env)))
- (sys:propagate-ancestor expansion-ex place getter setter)))
-
-(defun call-clobber-expander (ssetter unex-place env body)
- (sys:propagate-ancestor body unex-place ssetter)
- (let* ((place (sys:pl-expand unex-place env))
- (expander (get-clobber-expander place))
- (sys:*pl-env* env)
- (sys:*pl-form* unex-place)
- (expansion [expander ssetter place body])
- (expansion-ex (expand expansion env)))
- (sys:propagate-ancestor expansion-ex place ssetter)))
-
-(defun call-delete-expander (deleter unex-place env body)
- (sys:propagate-ancestor body unex-place deleter)
- (let* ((place (sys:pl-expand unex-place env))
- (expander (get-delete-expander place))
- (sys:*pl-env* env)
- (sys:*pl-form* unex-place)
- (expansion [expander deleter place body])
- (expansion-ex (expand expansion env)))
- (sys:propagate-ancestor expansion-ex place deleter)))
-
-(defmacro with-update-expander ((getter setter) unex-place env body)
- ^(with-gensyms (,getter ,setter)
- (call-update-expander ,getter ,setter ,unex-place ,env ,body)))
-
-(defmacro with-clobber-expander ((ssetter) unex-place env body)
- ^(with-gensyms (,ssetter)
- (call-clobber-expander ,ssetter ,unex-place ,env ,body)))
-
-(defmacro with-delete-expander ((deleter) unex-place env body)
- ^(with-gensyms (,deleter)
- (call-delete-expander ,deleter ,unex-place ,env ,body)))
-
-(defmacro set (:env env . place-value-pairs)
- (let ((assign-forms (mapcar (tb ((place : (value nil value-present-p)))
- (unless value-present-p
- (sys:eval-err "set: arguments must be pairs"))
- (with-clobber-expander (ssetter) place env
- ^(,ssetter ,value)))
- (tuples 2 place-value-pairs))))
- (if (cdr assign-forms)
- ^(progn ,*assign-forms)
- (car assign-forms))))
-
-(defmacro pset (:env env . place-value-pairs)
- (let ((len (length place-value-pairs)))
- (cond
- ((oddp len) (sys:eval-err "pset: arguments must be pairs"))
- ((<= len 2) ^(set ,*place-value-pairs))
- (t (let* ((pvtgs (mapcar (tb ((a b))
- (list a b (gensym) (gensym) (gensym)))
- (tuples 2 place-value-pairs)))
- (ls (reduce-left (tb ((lets stores) (place value temp getter setter))
- (list ^((,temp ,value) ,*lets)
- ^((,setter ,temp) ,*stores)))
- pvtgs '(nil nil)))
- (lets (first ls))
- (stores (second ls))
- (body-form ^(rlet (,*lets) ,*stores)))
- (reduce-left (tb (accum-form (place value temp getter setter))
- (call-update-expander getter setter
- place env accum-form))
- pvtgs body-form))))))
-
-(defmacro zap (place : (new-val nil) :env env)
- (with-update-expander (getter setter) place env
- ^(prog1 (,getter) (,setter ,new-val))))
-
-(defmacro flip (place :env env)
- (with-update-expander (getter setter) place env
- ^(,setter (not (,getter)))))
-
-(defmacro inc (place : (delta 1) :env env)
- (with-update-expander (getter setter) place env
- (caseql delta
- (0 place)
- (1 ^(,setter (succ (,getter))))
- (2 ^(,setter (ssucc (,getter))))
- (3 ^(,setter (sssucc (,getter))))
- (t ^(,setter (+ (,getter) ,delta))))))
-
-(defmacro dec (place : (delta 1) :env env)
- (with-update-expander (getter setter) place env
- (caseql delta
- (0 place)
- (1 ^(,setter (pred (,getter))))
- (2 ^(,setter (ppred (,getter))))
- (3 ^(,setter (pppred (,getter))))
- (t ^(,setter (- (,getter) ,delta))))))
-
-(defmacro pinc (place : (delta 1) :env env)
- (with-gensyms (oldval)
- (with-update-expander (getter setter) place env
- (caseql delta
- (0 place)
- (1 ^(let ((,oldval (,getter))) (,setter (succ ,oldval)) ,oldval))
- (2 ^(let ((,oldval (,getter))) (,setter (ssucc ,oldval)) ,oldval))
- (3 ^(let ((,oldval (,getter))) (,setter (sssucc ,oldval)) ,oldval))
- (t ^(let ((,oldval (,getter))) (,setter (+ ,oldval, delta)) ,oldval))))))
-
-(defmacro pdec (place : (delta 1) :env env)
- (with-gensyms (oldval)
- (with-update-expander (getter setter) place env
- (caseql delta
- (0 place)
- (1 ^(let ((,oldval (,getter))) (,setter (pred ,oldval)) ,oldval))
- (2 ^(let ((,oldval (,getter))) (,setter (ppred ,oldval)) ,oldval))
- (3 ^(let ((,oldval (,getter))) (,setter (pppred ,oldval)) ,oldval))
- (t ^(let ((,oldval (,getter))) (,setter (- ,oldval, delta)) ,oldval))))))
-
-(defmacro swap (place-0 place-1 :env env)
- (with-gensyms (tmp)
- (with-update-expander (getter-0 setter-0) place-0 env
- (with-update-expander (getter-1 setter-1) place-1 env
- ^(let ((,tmp (,getter-0)))
- (,setter-0 (,getter-1))
- (,setter-1 ,tmp))))))
-
-(defmacro push (new-item place :env env)
- (with-gensyms (new-sym)
- ^(alet ((,new-sym ,new-item))
- ,(with-update-expander (getter setter) place env
- ^(,setter (cons ,new-sym (,getter)))))))
-
-(defmacro pop (place :env env)
- (with-gensyms (tmp)
- (with-update-expander (getter setter) place env
- ^(alet ((,tmp (,getter)))
- (prog1 (car ,tmp) (,setter (cdr ,tmp)))))))
-
-(defmacro pushnew (new-item place :env env :
- (testfun :)
- (keyfun :))
- (with-update-expander (getter setter) place env
- (with-gensyms (new-item-sym old-list-sym)
- ^(rlet ((,new-item-sym ,new-item))
- ,(with-update-expander (getter setter) place env
- ^(let ((,old-list-sym (,getter)))
- (if (member ,new-item-sym ,old-list-sym ,testfun ,keyfun)
- ,old-list-sym
- (,setter (cons ,new-item-sym ,old-list-sym)))))))))
-
-(defmacro shift (:form f :env env . places)
- (tree-case places
- (() (compile-error f "need at least two arguments"))
- ((place) (compile-error f "need at least two arguments"))
- ((place newvalue)
- (with-update-expander (getter setter) place env
- ^(prog1 (,getter) (,setter ,newvalue))))
- ((place . others)
- (with-update-expander (getter setter) place env
- ^(prog1 (,getter) (,setter (shift ,*others)))))))
-
-(defmacro rotate (:env env . places)
- (tree-case places
- (() ())
- ((fplace) fplace)
- ((fplace . rplaces)
- (with-gensyms (tmp)
- (with-update-expander (getter-f setter-f) fplace env
- ^(let ((,tmp (,getter-f)))
- (,setter-f (shift ,*rplaces ,tmp))
- ,tmp))))))
-
-(defmacro test-set (:env env place)
- (with-update-expander (getter setter) place env
- ^(unless (,getter)
- (,setter t))))
-
-(defmacro test-clear (:env env place)
- (with-update-expander (getter setter) place env
- ^(when (,getter)
- (,setter nil)
- t)))
-
-(defmacro compare-swap (:env env comp-fun place comp-val store-val)
- (with-update-expander (getter setter) place env
- ^(when (,comp-fun (,getter) ,comp-val)
- (,setter ,store-val)
- t)))
-
-(defmacro test-inc (place : (delta 1) (upfrom-val 0))
- ^(eql (pinc ,place ,delta) ,upfrom-val))
-
-(defmacro test-dec (place : (delta 1) (downto-val 0))
- ^(eql (dec ,place ,delta) ,downto-val))
-
-(defmacro del (place :env env)
- (with-delete-expander (deleter) place env
- ^(,deleter)))
-
-(defmacro lset (:form f . places-source)
- (let ((places (butlast places-source))
- (source (last places-source))
- (orig (gensym))
- (iter (gensym)))
- (unless places
- (compile-error f "require one or more places followed by expression"))
- ^(let* ((,orig ,(car source))
- (,iter ,orig))
- ,*(butlast (mappend (ret ^((set ,@1 (car ,iter)) (set ,iter (cdr ,iter))))
- places))
- ,orig)))
-
-(defmacro upd (place . opip-args)
- (with-gensyms (pl)
- ^(placelet ((,pl ,place))
- (set ,pl (call (opip ,*opip-args) ,pl)))))
-
-(defmacro defplace (place-destructuring-args body-sym
- (getter-sym setter-sym update-body) :
- ((ssetter-sym clobber-body))
- ((deleter-sym delete-body)))
- (let ((name (car place-destructuring-args))
- (args (cdr place-destructuring-args)))
- (unless (and name
- (symbolp name)
- (not (keywordp name))
- (not (eq t name)))
- (compile-error sys:*pl-form* "~s cannot be used as a place name" name))
- (with-gensyms (place)
- ^(progn
- (sethash *place-update-expander* ',name
- (lambda (,getter-sym ,setter-sym ,place ,body-sym)
- (tree-bind ,args (cdr ,place)
- ,update-body)))
- ,*(if ssetter-sym
- ^((sethash *place-clobber-expander* ',name
- (lambda (,ssetter-sym ,place ,body-sym)
- (tree-bind ,args (cdr ,place)
- ,clobber-body)))))
- ,*(if deleter-sym
- ^((sethash *place-delete-expander* ',name
- (lambda (,deleter-sym ,place ,body-sym)
- (tree-bind ,args (cdr ,place)
- ,delete-body)))))
- ',name))))
-
-(defmacro define-place-macro (name place-destructuring-args . body)
- (with-gensyms (name-dummy args)
- ^(progn
- (sethash *place-macro* ',name
- (lambda (,args)
- (mac-param-bind ,args
- (,name-dummy ,*place-destructuring-args)
- ,args ,*body)))
- ',name)))
-
-(defplace (sys:var arg) body
- (getter setter
- ^(macrolet ((,getter () ^(sys:var ,',arg))
- (,setter (val) ^(sys:setq ,'(sys:var ,arg) ,val)))
- ,body)))
-
-(defplace (sys:l1-val arg) body
- (getter setter
- ^(macrolet ((,getter () ^(sys:l1-val ,',arg))
- (,setter (val) ^(sys:l1-setq ,',arg ,val)))
- ,body))
- (ssetter
- ^(macrolet ((,ssetter (val) ^(sys:l1-setq ,',arg ,val)))
- ,body)))
-
-(defplace (sys:lisp1-value arg) body
- (getter setter
- ^(macrolet ((,getter () ^(sys:lisp1-value ,',arg))
- (,setter (val) ^(sys:lisp1-setq ,',arg ,val)))
- ,body))
- (ssetter
- ^(macrolet ((,ssetter (val) ^(sys:lisp1-setq ,',arg ,val)))
- ,body)))
-
-(defplace (car cell) body
- (getter setter
- (with-gensyms (cell-sym)
- ^(slet ((,cell-sym ,cell))
- (macrolet ((,getter () ^(car ,',cell-sym))
- (,setter (val) ^(sys:rplaca ,',cell-sym ,val)))
- ,body))))
- (ssetter
- ^(macrolet ((,ssetter (val) ^(sys:rplaca ,',cell ,val)))
- ,body))
- (deleter
- ^(macrolet ((,deleter () ^(pop ,',cell)))
- ,body)))
-
-(defplace (cdr cell) body
- (getter setter
- (with-gensyms (cell-sym)
- ^(slet ((,cell-sym ,cell))
- (macrolet ((,getter () ^(cdr ,',cell-sym))
- (,setter (val) ^(sys:rplacd ,',cell-sym ,val)))
- ,body))))
- (ssetter
- ^(macrolet ((,ssetter (val) ^(sys:rplacd ,',cell ,val)))
- ,body))
- (deleter
- ^(macrolet ((,deleter ()
- (with-gensyms (tmp)
- (with-update-expander (cgetter csetter) ',cell nil
- ^(let ((,tmp (,cgetter)))
- (prog1 (cdr ,tmp) (,csetter (car ,tmp))))))))
- ,body)))
-
-(defplace (nthcdr index list) body
- (getter setter
- (with-gensyms (index-sym list-sym sentinel-head-sym parent-cell-sym)
- (if (place-form-p list sys:*pl-env*)
- (with-update-expander (lgetter lsetter) list sys:*pl-env*
- ^(alet ((,index-sym ,index)
- (,list-sym (,lgetter)))
- (let* ((,sentinel-head-sym (cons nil ,list-sym))
- (,parent-cell-sym (nthcdr ,index-sym ,sentinel-head-sym)))
- (macrolet ((,getter () ^(cdr ,',parent-cell-sym))
- (,setter (val)
- ^(prog1 (sys:rplacd ,',parent-cell-sym ,val)
- (,',lsetter (cdr ,',sentinel-head-sym)))))
- ,body))))
- ^(alet ((,index-sym ,index)
- (,list-sym ,list))
- (let ((,parent-cell-sym (nthcdr (pred ,index-sym) ,list-sym)))
- (macrolet ((,getter () ^(cdr ,',parent-cell-sym))
- (,setter (val)
- ^(sys:rplacd ,',parent-cell-sym ,val)))
- ,body)))))))
-
-(defplace (nthlast index list) body
- (getter setter
- (with-gensyms (index-sym list-sym sentinel-head-sym parent-cell-sym)
- (if (place-form-p list sys:*pl-env*)
- (with-update-expander (lgetter lsetter) list sys:*pl-env*
- ^(alet ((,index-sym ,index)
- (,list-sym (,lgetter)))
- (let* ((,sentinel-head-sym (cons nil ,list-sym))
- (,parent-cell-sym (nthlast (succ ,index-sym)
- ,sentinel-head-sym)))
- (macrolet ((,getter () ^(cdr ,',parent-cell-sym))
- (,setter (val)
- ^(prog1 (sys:rplacd ,',parent-cell-sym ,val)
- (,',lsetter (cdr ,',sentinel-head-sym)))))
- ,body))))
- ^(alet ((,index-sym index)
- (,list-sym ,list))
- (let ((,parent-cell-sym (nthlast (succ ,index-sym) ,list-sym)))
- (macrolet ((,getter () ^(cdr ,',parent-cell-sym))
- (,setter (val)
- ^(sys:rplacd ,',parent-cell-sym ,val)))
- ,body)))))))
-
-(defplace (butlastn num list) body
- (getter setter
- (with-gensyms (num-sym list-sym head-sym tail-sym val-sym)
- (with-update-expander (lgetter lsetter) list sys:*pl-env*
- ^(alet ((,num-sym ,num)
- (,list-sym (,lgetter)))
- (let* ((,tail-sym (nthlast ,num-sym ,list-sym))
- (,head-sym (ldiff ,list-sym ,tail-sym)))
- (macrolet ((,getter () ,head-sym)
- (,setter (val)
- ^(alet ((,',val-sym ,val))
- (progn (,',lsetter (append ,',val-sym
- ,',tail-sym))
- ,',val-sym))))
- ,body)))))))
-
-(defplace (vecref vector index :whole args) body
- (getter setter
- (with-gensyms (vec-sym ind-sym)
- ^(alet ((,vec-sym ,vector)
- (,ind-sym ,index))
- (macrolet ((,getter () ^(vecref ,',vec-sym ,',ind-sym))
- (,setter (val) ^(refset ,',vec-sym ,',ind-sym ,val)))
- ,body))))
- (ssetter
- ^(macrolet ((,ssetter (val) ^(refset ,*',args ,val)))
- ,body))
- (deleter
- (with-gensyms (vec-sym ind-sym)
- ^(alet ((,vec-sym ,vector)
- (,ind-sym ,index))
- (macrolet ((,deleter ()
- ^(prog1 (vecref ,',vec-sym ,',ind-sym)
- (replace-vec ,',vec-sym nil
- ,',ind-sym (succ ,',ind-sym)))))
- ,body)))))
-
-(defplace (chr-str string index :whole args) body
- (getter setter
- (with-gensyms (str-sym ind-sym)
- ^(alet ((,str-sym ,string)
- (,ind-sym ,index))
- (macrolet ((,getter () ^(chr-str ,',str-sym ,',ind-sym))
- (,setter (val) ^(chr-str-set ,',str-sym ,',ind-sym ,val)))
- ,body))))
- (ssetter
- ^(macrolet ((,ssetter (val) ^(chr-str-set ,*',args ,val)))
- ,body))
- (deleter
- (with-gensyms (str-sym ind-sym)
- ^(alet ((,str-sym ,string)
- (,ind-sym ,index))
- (macrolet ((,deleter ()
- ^(prog1 (chr-str ,',str-sym ,',ind-sym)
- (replace-str ,',str-sym nil
- ,',ind-sym (succ ,',ind-sym)))))
- ,body)))))
-
-(defplace (ref seq index :whole args) body
- (getter setter
- (with-gensyms (seq-sym ind-sym)
- ^(alet ((,seq-sym ,seq)
- (,ind-sym ,index))
- (macrolet ((,getter () ^(ref ,',seq-sym ,',ind-sym))
- (,setter (val) ^(refset ,',seq-sym ,',ind-sym ,val)))
- ,body))))
- (ssetter
- ^(macrolet ((,ssetter (val) ^(refset ,*',args ,val)))
- ,body))
- (deleter
- (with-gensyms (seq-sym ind-sym)
- ^(alet ((,seq-sym ,seq)
- (,ind-sym ,index))
- (macrolet ((,deleter ()
- ^(prog1 (ref ,',seq-sym ,',ind-sym)
- (replace ,',seq-sym nil
- ,',ind-sym (succ ,',ind-sym)))))
- ,body)))))
-
-(defplace (sub seq :whole args : (from 0) (to t)) body
- (getter setter
- (with-gensyms (seq-sym from-sym to-sym v-sym)
- (with-update-expander (seq-getter seq-setter) seq sys:*pl-env*
- ^(alet ((,seq-sym (,seq-getter))
- (,from-sym ,from)
- (,to-sym ,to))
- (macrolet ((,getter () ^(sub ,',seq-sym ,',from-sym ,',to-sym))
- (,setter (val)
- ^(alet ((,',v-sym ,val))
- (,',seq-setter (replace ,',seq-sym ,',v-sym
- ,',from-sym ,',to-sym))
- ,',v-sym)))
- ,body)))))
- (ssetter
- (with-gensyms (seq-sym from-sym to-sym v-sym)
- (with-update-expander (seq-getter seq-setter) seq sys:*pl-env*
- ^(macrolet ((,ssetter (val)
- ^(alet ((,',seq-sym (,',seq-getter))
- (,',from-sym ,',from)
- (,',to-sym ,',to)
- (,',v-sym ,val))
- (,',seq-setter (replace ,',seq-sym ,',v-sym
- ,',from-sym ,',to-sym))
- ,',v-sym)))
- ,body))))
- (deleter
- (with-gensyms (seq-sym from-sym to-sym)
- (with-update-expander (seq-getter seq-setter) seq sys:*pl-env*
- ^(alet ((,seq-sym (,seq-getter))
- (,from-sym ,from)
- (,to-sym ,to))
- (macrolet ((,deleter ()
- ^(prog1
- (sub ,',seq-sym ,',from-sym ,',to-sym)
- (,',seq-setter (replace ,',seq-sym nil
- ,',from-sym ,',to-sym)))))
- ,body))))))
-
-(defplace (gethash hash key : (default nil have-default-p)) body
- (getter setter
- (with-gensyms (entry-sym)
- ^(let ((,entry-sym (inhash ,hash ,key ,default)))
- (macrolet ((,getter () ^(cdr ,',entry-sym))
- (,setter (val) ^(sys:rplacd ,',entry-sym ,val)))
- ,body))))
- nil
- (deleter
- ^(macrolet ((,deleter ()
- (if ,have-default-p
- (with-gensyms (entry-sym
- dfl-sym)
- ^(alet ((,entry-sym (inhash ,',hash ,',key))
- (,dfl-sym ,',default))
- (if ,entry-sym
- (remhash ,',hash ,',key)
- ,dfl-sym)))
- ^(remhash ,',hash ,',key))))
- ,body)))
-
-(defplace (hash-userdata hash) body
- (getter setter
- (with-gensyms (hash-sym)
- ^(slet ((,hash-sym ,hash))
- (macrolet ((,getter () ^(hash-userdata ,',hash-sym))
- (,setter (val) ^(set-hash-userdata ,',hash-sym ,val)))
- ,body))))
- (ssetter
- ^(macrolet ((,ssetter (val)
- ^(set-hash-userdata ,',hash ,val)))
- ,body)))
-
-(defplace (dwim obj-place :env env . args) body
- (getter setter
- (with-gensyms (ogetter-sym osetter-sym obj-sym newval-sym)
- (let ((arg-syms (mapcar (ret (gensym)) args)))
- (if (place-form-p obj-place sys:*pl-env*)
- (with-update-expander (ogetter-sym osetter-sym)
- ^(sys:l1-val ,obj-place) sys:*pl-env*
- ^(rlet ((,obj-sym (,ogetter-sym))
- ,*(mapcar (ret ^(,@1 (sys:l1-val ,@2))) arg-syms args))
- (macrolet ((,getter ()
- '[,obj-sym ,*arg-syms])
- (,setter (val)
- ^(rlet ((,',newval-sym ,val))
- (,',osetter-sym
- (sys:dwim-set t ,',obj-sym
- ,*',arg-syms ,',newval-sym))
- ,',newval-sym)))
- ,body)))
- ^(rlet ((,obj-sym ,obj-place)
- ,*(mapcar (ret ^(,@1 (sys:l1-val ,@2))) arg-syms args))
- (macrolet ((,getter ()
- '[,obj-sym ,*arg-syms])
- (,setter (val)
- ^(rlet ((,',newval-sym ,val))
- (sys:dwim-set nil ,',obj-sym
- ,*',arg-syms ,',newval-sym)
- ,',newval-sym)))
- ,body))))))
- (ssetter
- (with-gensyms (osetter-sym ogetter-sym obj-sym newval-sym)
- (let ((arg-syms (mapcar (ret (gensym)) args)))
- (if (place-form-p obj-place sys:*pl-env*)
- (with-update-expander (ogetter-sym osetter-sym)
- ^(sys:l1-val ,obj-place) sys:*pl-env*
- ^(macrolet ((,ssetter (val)
- ^(rlet ((,',obj-sym (,',ogetter-sym))
- ,*(mapcar (ret ^(,@1 (sys:l1-val ,@2)))
- ',arg-syms ',args)
- (,',newval-sym ,val))
- (,',osetter-sym
- (sys:dwim-set t ,',obj-sym
- ,*',arg-syms
- ,',newval-sym))
- ,',newval-sym)))
- ,body))
- ^(macrolet ((,ssetter (val)
- ^(rlet ((,',obj-sym ,',obj-place)
- ,*(mapcar (ret ^(,@1 (sys:l1-val ,@2)))
- ',arg-syms ',args)
- (,',newval-sym ,val))
- (sys:dwim-set nil ,',obj-sym
- ,*',arg-syms
- ,',newval-sym)
- ,',newval-sym)))
- ,body)))))
-
- (deleter
- (with-gensyms (osetter-sym ogetter-sym obj-sym oldval-sym)
- (let ((arg-syms (mapcar (ret (gensym)) args)))
- (if (place-form-p obj-place sys:*pl-env*)
- (with-update-expander (ogetter-sym osetter-sym)
- ^(sys:l1-val ,obj-place) sys:*pl-env*
- ^(macrolet ((,deleter ()
- ^(rlet ((,',obj-sym (,',ogetter-sym))
- ,*(mapcar (ret ^(,@1 (sys:l1-val ,@2)))
- ',arg-syms ',args))
- (let ((,',oldval-sym [,',obj-sym ,*',arg-syms]))
- (progn
- (,',osetter-sym
- (sys:dwim-del t ,',obj-sym ,*',arg-syms))
- ,',oldval-sym)))))
- ,body))
- ^(macrolet ((,deleter ()
- ^(rlet ((,',obj-sym ,',obj-place)
- ,*(mapcar (ret ^(,@1 (sys:l1-val ,@2)))
- ',arg-syms ',args))
- (let ((,',oldval-sym [,',obj-sym ,*',arg-syms]))
- (progn
- (sys:dwim-del nil ,',obj-sym ,*',arg-syms)
- ,',oldval-sym)))))
- ,body))))))
-
-(defplace (force promise) body
- (getter setter
- (with-gensyms (promise-sym)
- ^(rlet ((,promise-sym ,promise))
- (macrolet ((,getter ()
- ^(force ,',promise-sym))
- (,setter (val)
- ^(set (car (cdr ,',promise-sym)) ,val)))
- ,body))))
- (ssetter
- (with-gensyms (promise-sym)
- ^(rlet ((,promise-sym ,promise))
- (macrolet ((,ssetter (val)
- ^(prog1
- (set (car (cdr ,',promise-sym)) ,val)
- (set (car ,',promise-sym) 'sys:promise-forced))))
- ,body)))))
-
-(defplace (errno) body
- (getter setter
- ^(macrolet ((,getter () '(errno))
- (,setter (val-expr)
- (with-gensyms (val-sym)
- ^(slet ((,val-sym ,val-expr))
- (progn (errno ,val-sym) ,val-sym)))))
- ,body)))
-
-(defplace (fun sym) body
- (getter setter
- ^(macrolet ((,getter () ^(fun ,',sym))
- (,setter (val) ^(sys:setqf ,',sym ,val)))
- ,body))
- nil
- (deleter
- ^(macrolet ((,deleter (:env env)
- (when (lexical-fun-p env ',sym)
- (compile-error ',sys:*pl-form*
- "~s is a lexical function, \
- \ thus not deletable"))
- ^(fmakunbound ',',sym)))
- ,body)))
-
-(defun sys:get-fun-getter-setter (sym : f)
- (tree-case sym
- ((type struct slot)
- (if (eq type 'meth)
- (caseql slot
- (:init (cons (op struct-get-initfun struct)
- (op struct-set-initfun struct)))
- (:postinit (cons (op struct-get-postinitfun struct)
- (op struct-set-postinitfun struct)))
- (t (cons (op static-slot struct slot)
- (op static-slot-ensure struct slot))))
- :))
- ((type sym)
- (if (eq type 'macro)
- (let ((cell (or (gethash sys:top-mb sym)
- (sethash sys:top-mb sym (cons sym nil)))))
- (cons (op cdr)
- (op sys:rplacd cell)))
- :))
- ((op . rest)
- (if (eq op 'lambda)
- (compile-error f "cannot assign to lambda")
- (compile-error f "invalid function syntax ~s" sym)))
- (else
- (let ((cell (or (gethash sys:top-fb sym)
- (sethash sys:top-fb sym (cons sym nil)))))
- (cons (op cdr)
- (op sys:rplacd cell))))))
-
-(defplace (symbol-function sym-expr) body
- (getter setter
- (with-gensyms (gs-sym)
- ^(let ((,gs-sym (sys:get-fun-getter-setter ,sym-expr ',sys:*pl-form*)))
- (macrolet ((,getter () ^(call (car ,',gs-sym)))
- (,setter (val) ^(call (cdr ,',gs-sym) ,val)))
- ,body))))
- nil
- (deleter
- ^(macrolet ((,deleter () ^(fmakunbound ,',sym-expr)))
- ,body)))
-
-(defun sys:get-mb (f sym)
- (or (gethash sys:top-mb sym)
- (compile-error f "unbound macro ~s" sym)))
-
-(defplace (symbol-macro sym-expr) body
- (getter setter
- (with-gensyms (binding-sym)
- ^(let ((,binding-sym (sys:get-mb ',sys:*pl-form* ,sym-expr)))
- (macrolet ((,getter () ^(cdr ,',binding-sym))
- (,setter (val) ^(sys:rplacd ,',binding-sym ,val)))
- ,body))))
- nil
- (deleter
- ^(macrolet ((,deleter () ^(mmakunbound ,',sym-expr)))
- ,body)))
-
-(defun sys:get-vb (sym)
- (or (gethash sys:top-vb sym)
- (sethash sys:top-vb sym (cons sym nil))))
-
-(defplace (symbol-value sym-expr) body
- (getter setter
- (with-gensyms (binding-sym)
- ^(let ((,binding-sym (sys:get-vb ,sym-expr)))
- (macrolet ((,getter () ^(cdr ,',binding-sym))
- (,setter (val) ^(sys:rplacd ,',binding-sym ,val)))
- ,body))))
- nil
- (deleter
- ^(macrolet ((,deleter () ^(makunbound ,',sym-expr)))
- ,body)))
-
-(defplace (slot struct sym) body
- (getter setter
- (with-gensyms (struct-sym slot-sym)
- ^(alet ((,struct-sym ,struct)
- (,slot-sym ,sym))
- (macrolet ((,getter () ^(slot ,',struct-sym ,',slot-sym))
- (,setter (val) ^(slotset ,',struct-sym ,',slot-sym ,val)))
- ,body))))
- (ssetter
- ^(macrolet ((,ssetter (val) ^(slotset ,',struct ,',sym ,val)))
- ,body)))
-
-(defmacro define-modify-macro (name lambda-list function)
- (let ((cleaned-lambda-list (mapcar [iffi consp car]
- (remql : lambda-list))))
- (with-gensyms (place-sym args-sym)
- ^(defmacro ,name (:env env ,place-sym ,*lambda-list)
- (with-update-expander (getter setter) ,place-sym env
- ^(,setter (,',function (,getter) ,,*cleaned-lambda-list)))))))
-
-(defmacro sys:placelet-1 (((sym place)) :env env . body)
- (with-gensyms (tmp-place pl-getter pl-setter)
- (unwind-protect
- (progn
- ;; This temporary proxy place installed into the
- ;; *place-update-expander* hash, and the forced expansion
- ;; of the symacrolet form are necessary for correctness.
- ;; If we don't perform that expand, then the temporary proxy
- ;; place is not used, and sym ends up being an alias
- ;; for the getter form (,',pl-getter) of the original place.
- ;; Then, placelet will only work for places whose getter forms
- ;; themselves places. This is not required in general. A (foo ...)
- ;; place can, for instance, use (get-foo ...) and (set-foo ...)
- ;; getters and setters, where (get-foo ...) is not a place.
- ;; If sym turns into a symbol macro for a (get-foo ...) form,
- ;; uses of sym as a place will fail due to get-foo not being a place.
- (sethash *place-update-expander* tmp-place
- (lambda (tmp-getter tmp-setter tmp-place tmp-body)
- ^(macrolet ((,tmp-getter () ^(,',pl-getter))
- (,tmp-setter (val) ^(,',pl-setter ,val)))
- ,tmp-body)))
- (call-update-expander pl-getter pl-setter place env
- ^(macrolet ((,tmp-place () ^(,',pl-getter)))
- ,(expand ^(symacrolet ((,sym (,tmp-place)))
- ,*body) env))))
- (remhash *place-update-expander* tmp-place))))
-
-(defmacro placelet* (:form f sym-place-pairs . body)
- (tree-case sym-place-pairs
- (() ^(progn ,*body))
- (((sym place)) ^(sys:placelet-1 ((,sym ,place)) ,*body))
- (((sym place) . rest-pairs) ^(sys:placelet-1 ((,sym ,place))
- (placelet* (,*rest-pairs) ,*body)))
- (obj (compile-error f "bad syntax: ~s" obj))))
-
-(defmacro placelet (:form f sym-place-pairs . body)
- (unless (all sym-place-pairs
- [andf consp (opip length (= 2)) (oand first bindable)])
- (compile-error f "bad syntax: ~s" sym-place-pairs))
- (tree-bind (: syms places) (transpose sym-place-pairs)
- (let ((temps (mapcar (ret (gensym)) syms)))
- ^(placelet* (,*(zip temps places))
- (symacrolet (,*(zip syms temps))
- ,*body)))))
-
-(defun sys:register-simple-accessor (get-fun set-fun)
- (sethash *place-update-expander* get-fun
- (lambda (getter setter place body)
- (let* ((args (cdr place))
- (temps (mapcar (ret (gensym)) args)))
- ^(let (,(zip temps args))
- (macrolet ((,getter () ^(,',get-fun ,*',temps))
- (,setter (val)
- ^(,',set-fun ,*',temps ,val)))
- ,body)))))
- (sethash *place-clobber-expander* get-fun
- (lambda (ssetter place body)
- ^(macrolet ((,ssetter (val)
- ^(,',set-fun ,*(cdr ',place) ,val)))
- ,body)))
- get-fun)
-
-(defmacro define-accessor (get-fun set-fun)
- ^(sys:register-simple-accessor ',get-fun ',set-fun))
-
-(define-place-macro first (obj) ^(car ,obj))
-(define-place-macro rest (obj) ^(cdr ,obj))
-(define-place-macro second (obj) ^(ref ,obj 1))
-(define-place-macro third (obj) ^(ref ,obj 2))
-(define-place-macro fourth (obj) ^(ref ,obj 3))
-(define-place-macro fifth (obj) ^(ref ,obj 4))
-(define-place-macro sixth (obj) ^(ref ,obj 5))
-(define-place-macro seventh (obj) ^(ref ,obj 6))
-(define-place-macro eighth (obj) ^(ref ,obj 7))
-(define-place-macro ninth (obj) ^(ref ,obj 8))
-(define-place-macro tenth (obj) ^(ref ,obj 9))
-
-(define-place-macro last (:env e obj : (n nil have-n))
- (cond
- ((and have-n (constantp n e) (not (plusp n)))
- ^(sub ,obj t t))
- ((and have-n (constantp n e))
- ^(sub ,obj ,(- n) t))
- (have-n
- ^(sub ,obj (- (max ,n 0)) t))
- (t ^(sub ,obj -1 t))))
-
-(define-place-macro butlast (:env e obj : (n nil have-n))
- (cond
- ((and have-n (constantp n e) (not (plusp n)))
- obj)
- ((and have-n (constantp n e))
- ^(sub ,obj 0 ,(- n)))
- (have-n
- ^(sub ,obj 0 (- (max ,n 0))))
- (t ^(sub ,obj 0 -1))))
-
-(define-place-macro nth (index obj)
- ^(car (nthcdr ,index ,obj)))