;;;; calling.scm --- Calling Conventions ;;;; ;;;; Copyright (C) 1995, 1996, 1997, 2000, 2001, 2006 Free Software Foundation, Inc. ;;;; ;;;; This library is free software; you can redistribute it and/or ;;;; modify it under the terms of the GNU Lesser General Public ;;;; License as published by the Free Software Foundation; either ;;;; version 3 of the License, or (at your option) any later version. ;;;; ;;;; This library is distributed in the hope that it will be useful, ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;;;; Lesser General Public License for more details. ;;;; ;;;; You should have received a copy of the GNU Lesser General Public ;;;; License along with this library; if not, write to the Free Software ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ;;;; (define-module (ice-9 calling) :export-syntax (with-excursion-function with-getter-and-setter with-getter with-delegating-getter-and-setter with-excursion-getter-and-setter with-configuration-getter-and-setter with-delegating-configuration-getter-and-setter let-with-configuration-getter-and-setter)) ;;;; ;;; ;;; This file contains a number of macros that support ;;; common calling conventions. ;;; ;;; with-excursion-function <vars> proc ;;; <vars> is an unevaluated list of names that are bound in the caller. ;;; proc is a procedure, called: ;;; (proc excursion) ;;; ;;; excursion is a procedure isolates all changes to <vars> ;;; in the dynamic scope of the call to proc. In other words, ;;; the values of <vars> are saved when proc is entered, and when ;;; proc returns, those values are restored. Values are also restored ;;; entering and leaving the call to proc non-locally, such as using ;;; call-with-current-continuation, error, or throw. ;;; (defmacro with-excursion-function (vars proc) `(,proc ,(excursion-function-syntax vars))) ;;; with-getter-and-setter <vars> proc ;;; <vars> is an unevaluated list of names that are bound in the caller. ;;; proc is a procedure, called: ;;; (proc getter setter) ;;; ;;; getter and setter are procedures used to access ;;; or modify <vars>. ;;; ;;; setter, called with keywords arguments, modifies the named ;;; values. If "foo" and "bar" are among <vars>, then: ;;; ;;; (setter :foo 1 :bar 2) ;;; == (set! foo 1 bar 2) ;;; ;;; getter, called with just keywords, returns ;;; a list of the corresponding values. For example, ;;; if "foo" and "bar" are among the <vars>, then ;;; ;;; (getter :foo :bar) ;;; => (<value-of-foo> <value-of-bar>) ;;; ;;; getter, called with no arguments, returns a list of all accepted ;;; keywords and the corresponding values. If "foo" and "bar" are ;;; the *only* <vars>, then: ;;; ;;; (getter) ;;; => (:foo <value-of-bar> :bar <value-of-foo>) ;;; ;;; The unusual calling sequence of a getter supports too handy ;;; idioms: ;;; ;;; (apply setter (getter)) ;; save and restore ;;; ;;; (apply-to-args (getter :foo :bar) ;; fetch and bind ;;; (lambda (foo bar) ....)) ;;; ;;; ;; [ "apply-to-args" is just like two-argument "apply" except that it ;;; ;; takes its arguments in a different order. ;;; ;;; (defmacro with-getter-and-setter (vars proc) `(,proc ,@ (getter-and-setter-syntax vars))) ;;; with-getter vars proc ;;; A short-hand for a call to with-getter-and-setter. ;;; The procedure is called: ;;; (proc getter) ;;; (defmacro with-getter (vars proc) `(,proc ,(car (getter-and-setter-syntax vars)))) ;;; with-delegating-getter-and-setter <vars> get-delegate set-delegate proc ;;; Compose getters and setters. ;;; ;;; <vars> is an unevaluated list of names that are bound in the caller. ;;; ;;; get-delegate is called by the new getter to extend the set of ;;; gettable variables beyond just <vars> ;;; set-delegate is called by the new setter to extend the set of ;;; gettable variables beyond just <vars> ;;; ;;; proc is a procedure that is called ;;; (proc getter setter) ;;; (defmacro with-delegating-getter-and-setter (vars get-delegate set-delegate proc) `(,proc ,@ (delegating-getter-and-setter-syntax vars get-delegate set-delegate))) ;;; with-excursion-getter-and-setter <vars> proc ;;; <vars> is an unevaluated list of names that are bound in the caller. ;;; proc is called: ;;; ;;; (proc excursion getter setter) ;;; ;;; See also: ;;; with-getter-and-setter ;;; with-excursion-function ;;; (defmacro with-excursion-getter-and-setter (vars proc) `(,proc ,(excursion-function-syntax vars) ,@ (getter-and-setter-syntax vars))) (define (excursion-function-syntax vars) (let ((saved-value-names (map gensym vars)) (tmp-var-name (gensym "temp")) (swap-fn-name (gensym "swap")) (thunk-name (gensym "thunk"))) `(lambda (,thunk-name) (letrec ((,tmp-var-name #f) (,swap-fn-name (lambda () ,@ (map (lambda (n sn) `(begin (set! ,tmp-var-name ,n) (set! ,n ,sn) (set! ,sn ,tmp-var-name))) vars saved-value-names))) ,@ (map (lambda (sn n) `(,sn ,n)) saved-value-names vars)) (dynamic-wind ,swap-fn-name ,thunk-name ,swap-fn-name))))) (define (getter-and-setter-syntax vars) (let ((args-name (gensym "args")) (an-arg-name (gensym "an-arg")) (new-val-name (gensym "new-value")) (loop-name (gensym "loop")) (kws (map symbol->keyword vars))) (list `(lambda ,args-name (let ,loop-name ((,args-name ,args-name)) (if (null? ,args-name) ,(if (null? kws) ''() `(let ((all-vals (,loop-name ',kws))) (let ,loop-name ((vals all-vals) (kws ',kws)) (if (null? vals) '() `(,(car kws) ,(car vals) ,@(,loop-name (cdr vals) (cdr kws))))))) (map (lambda (,an-arg-name) (case ,an-arg-name ,@ (append (map (lambda (kw v) `((,kw) ,v)) kws vars) `((else (throw 'bad-get-option ,an-arg-name)))))) ,args-name)))) `(lambda ,args-name (let ,loop-name ((,args-name ,args-name)) (or (null? ,args-name) (null? (cdr ,args-name)) (let ((,an-arg-name (car ,args-name)) (,new-val-name (cadr ,args-name))) (case ,an-arg-name ,@ (append (map (lambda (kw v) `((,kw) (set! ,v ,new-val-name))) kws vars) `((else (throw 'bad-set-option ,an-arg-name))))) (,loop-name (cddr ,args-name))))))))) (define (delegating-getter-and-setter-syntax vars get-delegate set-delegate) (let ((args-name (gensym "args")) (an-arg-name (gensym "an-arg")) (new-val-name (gensym "new-value")) (loop-name (gensym "loop")) (kws (map symbol->keyword vars))) (list `(lambda ,args-name (let ,loop-name ((,args-name ,args-name)) (if (null? ,args-name) (append! ,(if (null? kws) ''() `(let ((all-vals (,loop-name ',kws))) (let ,loop-name ((vals all-vals) (kws ',kws)) (if (null? vals) '() `(,(car kws) ,(car vals) ,@(,loop-name (cdr vals) (cdr kws))))))) (,get-delegate)) (map (lambda (,an-arg-name) (case ,an-arg-name ,@ (append (map (lambda (kw v) `((,kw) ,v)) kws vars) `((else (car (,get-delegate ,an-arg-name))))))) ,args-name)))) `(lambda ,args-name (let ,loop-name ((,args-name ,args-name)) (or (null? ,args-name) (null? (cdr ,args-name)) (let ((,an-arg-name (car ,args-name)) (,new-val-name (cadr ,args-name))) (case ,an-arg-name ,@ (append (map (lambda (kw v) `((,kw) (set! ,v ,new-val-name))) kws vars) `((else (,set-delegate ,an-arg-name ,new-val-name))))) (,loop-name (cddr ,args-name))))))))) ;;; with-configuration-getter-and-setter <vars-etc> proc ;;; ;;; Create a getter and setter that can trigger arbitrary computation. ;;; ;;; <vars-etc> is a list of variable specifiers, explained below. ;;; proc is called: ;;; ;;; (proc getter setter) ;;; ;;; Each element of the <vars-etc> list is of the form: ;;; ;;; (<var> getter-hook setter-hook) ;;; ;;; Both hook elements are evaluated; the variable name is not. ;;; Either hook may be #f or procedure. ;;; ;;; A getter hook is a thunk that returns a value for the corresponding ;;; variable. If omitted (#f is passed), the binding of <var> is ;;; returned. ;;; ;;; A setter hook is a procedure of one argument that accepts a new value ;;; for the corresponding variable. If omitted, the binding of <var> ;;; is simply set using set!. ;;; (defmacro with-configuration-getter-and-setter (vars-etc proc) `((lambda (simpler-get simpler-set body-proc) (with-delegating-getter-and-setter () simpler-get simpler-set body-proc)) (lambda (kw) (case kw ,@(map (lambda (v) `((,(symbol->keyword (car v))) ,(cond ((cadr v) => list) (else `(list ,(car v)))))) vars-etc))) (lambda (kw new-val) (case kw ,@(map (lambda (v) `((,(symbol->keyword (car v))) ,(cond ((caddr v) => (lambda (proc) `(,proc new-val))) (else `(set! ,(car v) new-val))))) vars-etc))) ,proc)) (defmacro with-delegating-configuration-getter-and-setter (vars-etc delegate-get delegate-set proc) `((lambda (simpler-get simpler-set body-proc) (with-delegating-getter-and-setter () simpler-get simpler-set body-proc)) (lambda (kw) (case kw ,@(append! (map (lambda (v) `((,(symbol->keyword (car v))) ,(cond ((cadr v) => list) (else `(list ,(car v)))))) vars-etc) `((else (,delegate-get kw)))))) (lambda (kw new-val) (case kw ,@(append! (map (lambda (v) `((,(symbol->keyword (car v))) ,(cond ((caddr v) => (lambda (proc) `(,proc new-val))) (else `(set! ,(car v) new-val))))) vars-etc) `((else (,delegate-set kw new-val)))))) ,proc)) ;;; let-configuration-getter-and-setter <vars-etc> proc ;;; ;;; This procedure is like with-configuration-getter-and-setter (q.v.) ;;; except that each element of <vars-etc> is: ;;; ;;; (<var> initial-value getter-hook setter-hook) ;;; ;;; Unlike with-configuration-getter-and-setter, let-configuration-getter-and-setter ;;; introduces bindings for the variables named in <vars-etc>. ;;; It is short-hand for: ;;; ;;; (let ((<var1> initial-value-1) ;;; (<var2> initial-value-2) ;;; ...) ;;; (with-configuration-getter-and-setter ((<var1> v1-get v1-set) ...) proc)) ;;; (defmacro let-with-configuration-getter-and-setter (vars-etc proc) `(let ,(map (lambda (v) `(,(car v) ,(cadr v))) vars-etc) (with-configuration-getter-and-setter ,(map (lambda (v) `(,(car v) ,(caddr v) ,(cadddr v))) vars-etc) ,proc)))
Name | Type | Size | Permission | Actions |
---|---|---|---|---|
peg | Folder | 0755 |
|
|
and-let-star.scm | File | 2.53 KB | 0644 |
|
arrays.scm | File | 2.63 KB | 0644 |
|
atomic.scm | File | 1.55 KB | 0644 |
|
binary-ports.scm | File | 1.99 KB | 0644 |
|
boot-9.scm | File | 143.94 KB | 0644 |
|
buffered-input.scm | File | 4.82 KB | 0644 |
|
calling.scm | File | 10.54 KB | 0644 |
|
channel.scm | File | 5.19 KB | 0644 |
|
command-line.scm | File | 18.2 KB | 0644 |
|
common-list.scm | File | 8.95 KB | 0644 |
|
control.scm | File | 4.08 KB | 0644 |
|
curried-definitions.scm | File | 1.79 KB | 0644 |
|
debug.scm | File | 1.09 KB | 0644 |
|
deprecated.scm | File | 2.95 KB | 0644 |
|
documentation.scm | File | 7.41 KB | 0644 |
|
eval-string.scm | File | 2.99 KB | 0644 |
|
eval.scm | File | 25.12 KB | 0644 |
|
expect.scm | File | 5.5 KB | 0644 |
|
fdes-finalizers.scm | File | 1.06 KB | 0644 |
|
format.scm | File | 74.37 KB | 0644 |
|
ftw.scm | File | 24.17 KB | 0644 |
|
futures.scm | File | 10.49 KB | 0644 |
|
gap-buffer.scm | File | 10.14 KB | 0644 |
|
getopt-long.scm | File | 16.49 KB | 0644 |
|
hash-table.scm | File | 1.77 KB | 0644 |
|
hcons.scm | File | 2.55 KB | 0644 |
|
history.scm | File | 2.29 KB | 0644 |
|
i18n.scm | File | 20.51 KB | 0644 |
|
iconv.scm | File | 3.65 KB | 0644 |
|
lineio.scm | File | 3.85 KB | 0644 |
|
list.scm | File | 1.29 KB | 0644 |
|
local-eval.scm | File | 9.96 KB | 0644 |
|
ls.scm | File | 3.2 KB | 0644 |
|
mapping.scm | File | 4.84 KB | 0644 |
|
match.scm | File | 2 KB | 0644 |
|
match.upstream.scm | File | 35.92 KB | 0644 |
|
networking.scm | File | 3.33 KB | 0644 |
|
null.scm | File | 1.13 KB | 0644 |
|
occam-channel.scm | File | 7.26 KB | 0644 |
|
optargs.scm | File | 15.75 KB | 0644 |
|
peg.scm | File | 1.64 KB | 0644 |
|
poe.scm | File | 3.3 KB | 0644 |
|
poll.scm | File | 5.79 KB | 0644 |
|
popen.scm | File | 6.82 KB | 0644 |
|
ports.scm | File | 18.89 KB | 0644 |
|
posix.scm | File | 2.73 KB | 0644 |
|
pretty-print.scm | File | 16.88 KB | 0644 |
|
psyntax-pp.scm | File | 180.55 KB | 0644 |
|
psyntax.scm | File | 148.7 KB | 0644 |
|
q.scm | File | 4.2 KB | 0644 |
|
quasisyntax.scm | File | 5.22 KB | 0644 |
|
r5rs.scm | File | 1.56 KB | 0644 |
|
r6rs-libraries.scm | File | 9.43 KB | 0644 |
|
rdelim.scm | File | 7.72 KB | 0644 |
|
readline.scm | File | 9.56 KB | 0644 |
|
receive.scm | File | 1.06 KB | 0644 |
|
regex.scm | File | 8.87 KB | 0644 |
|
runq.scm | File | 8.18 KB | 0644 |
|
rw.scm | File | 1.02 KB | 0644 |
|
safe-r5rs.scm | File | 3.72 KB | 0644 |
|
safe.scm | File | 1.25 KB | 0644 |
|
sandbox.scm | File | 34.23 KB | 0644 |
|
save-stack.scm | File | 2.15 KB | 0644 |
|
scm-style-repl.scm | File | 11.62 KB | 0644 |
|
serialize.scm | File | 3.78 KB | 0644 |
|
session.scm | File | 17.72 KB | 0644 |
|
slib.scm | File | 1.55 KB | 0644 |
|
stack-catch.scm | File | 1.94 KB | 0644 |
|
streams.scm | File | 5.86 KB | 0644 |
|
string-fun.scm | File | 8.59 KB | 0644 |
|
suspendable-ports.scm | File | 29.87 KB | 0644 |
|
syncase.scm | File | 1.52 KB | 0644 |
|
textual-ports.scm | File | 2.29 KB | 0644 |
|
threads.scm | File | 12.54 KB | 0644 |
|
time.scm | File | 2.07 KB | 0644 |
|
top-repl.scm | File | 2.75 KB | 0644 |
|
unicode.scm | File | 1005 B | 0644 |
|
vlist.scm | File | 21.56 KB | 0644 |
|
weak-vector.scm | File | 1.2 KB | 0644 |
|