|
32 | 32 | #!nounbound |
33 | 33 | (library (sagittarius parameters) |
34 | 34 | (export make-thread-parameter thread-parameter? <thread-parameter> |
35 | | - (rename (make-thread-parameter make-parameter)) |
36 | | - <parameter> parameter? |
| 35 | + make-parameter <parameter> parameter? |
37 | 36 |
|
38 | | - parameterize temporarily) |
39 | | - (import (rnrs) |
| 37 | + *parameterization-mark-key* |
| 38 | + |
| 39 | + parameterize |
| 40 | + parameterize/dw temporarily) |
| 41 | + (import (core) |
40 | 42 | (core syntax) |
41 | 43 | (clos user) |
42 | 44 | (sagittarius) |
43 | 45 | (sagittarius object) |
| 46 | + (sagittarius continuations) |
44 | 47 | (only (sagittarius) current-dynamic-environment)) |
45 | 48 |
|
46 | 49 | (define mark (list 0)) ;; unique mark |
47 | 50 |
|
| 51 | +(define-class <parameterization> () |
| 52 | + ((cells :init-value '() :init-keyword :cells :reader parameterization-cells))) |
| 53 | +(define (make-parameterization :optional (cells '())) |
| 54 | + (make <parameterization> :cells cells)) |
| 55 | +(define (parameterization? o) (is-a? o <parameterization>)) |
| 56 | +(define (parameterization-extend (p parameterization?) key+value*) |
| 57 | + (make-parameterization (append key+value* (parameterization-cells p)))) |
| 58 | +(define (parameterization-ref (p parameterization?) key) |
| 59 | + (assq key (parameterization-cells p))) |
| 60 | + |
| 61 | +(define *parameterization-mark-key* |
| 62 | + (make-continuation-mark-key 'parameterization)) |
| 63 | + |
| 64 | +(define (current-parameterization) |
| 65 | + ;; Use #f as prompt-tag to search marks beyond prompt boundaries. |
| 66 | + ;; This ensures parameterization from outside a prompt is visible inside. |
| 67 | + (cond ((continuation-mark-set-first #f *parameterization-mark-key* #f #f)) |
| 68 | + (else (make-parameterization)))) |
| 69 | + |
| 70 | +(define-syntax parameterize |
| 71 | + (lambda (x) |
| 72 | + (syntax-case x () |
| 73 | + ((_ ((p v) ...) e1 e2 ...) |
| 74 | + #'(with-continuation-mark |
| 75 | + *parameterization-mark-key* |
| 76 | + (parameterization-extend |
| 77 | + (current-parameterization) |
| 78 | + (list (cons p (parameter-convert p v)) ...)) |
| 79 | + (let () e1 e2 ...)))))) |
| 80 | + |
48 | 81 | (define-class <parameter> () |
49 | | - ((converter :init-keyword :converter) |
50 | | - (init :init-keyword :init))) |
| 82 | + ((converter :init-keyword :converter :reader parameter-converter) |
| 83 | + (init :init-keyword :init :reader parameter-val :writer parameter-val-set!))) |
51 | 84 | (define (parameter? o) (is-a? o <parameter>)) |
| 85 | +(define (make-parameter init :optional (converter #f)) |
| 86 | + (let ((init (if converter (converter init) init))) |
| 87 | + (make <parameter> :converter converter :init init))) |
| 88 | + |
| 89 | +(define (parameter-cell p) |
| 90 | + (parameterization-ref (current-parameterization) p)) |
| 91 | + |
| 92 | +(define-method object-apply ((p <parameter>)) |
| 93 | + (cond ((parameter-cell p) => cdr) |
| 94 | + (else (parameter-val p)))) |
| 95 | + |
| 96 | +(define-method object-apply ((p <parameter>) v) |
| 97 | + (let ((conv (parameter-converter p))) |
| 98 | + (cond ((parameter-cell p) => |
| 99 | + (lambda (cell) |
| 100 | + (set-cdr! cell (if conv (conv v) v)))) |
| 101 | + (else (parameter-val-set! p (if conv (conv v) v)))))) |
52 | 102 |
|
53 | 103 | ;; TODO thread-local? |
54 | 104 | (define-class <thread-parameter> (<parameter>) ()) |
|
80 | 130 | (p v))) |
81 | 131 |
|
82 | 132 | (define (parameter-convert p v) |
83 | | - (if (is-a? p <thread-parameter>) |
| 133 | + (if (is-a? p <parameter>) |
84 | 134 | (let ((conv (~ p 'converter))) |
85 | 135 | (if (procedure? conv) |
86 | 136 | (conv v) |
|
119 | 169 | (parameterize-aux (param ... p) (val ... v) (tmps ... (P L S)) |
120 | 170 | more body)))) |
121 | 171 |
|
122 | | -(define-syntax parameterize |
| 172 | +(define-syntax parameterize/dw |
123 | 173 | (syntax-rules () |
124 | 174 | ((_ (binds ...) . body) |
125 | 175 | (parameterize-aux () () () (binds ...) body)))) |
|
0 commit comments