|
90 | 90 | [(_ fn expr)
|
91 | 91 | (with-syntax ([id (datum->syntax stx (gensym))])
|
92 | 92 | #'(send this max-min-helper fn (lambda () (send this wally-evaluate expr)) 'id (interesting-time?)))]))
|
| 93 | + |
93 | 94 | ; integral macro
|
94 | 95 | ; The form is (integral expr) with additional optional keyword arguments as follows:
|
95 | 96 | ; #:var v -- variable of integration; default is (milliseconds) -- note that an expression is allowed here
|
96 |
| -; #:numeric or #:symbolic -- which kind of integration to use. Default is to try symbolic, and if that doesn't work, use numeric |
| 97 | +; #:numeric or #:symbolic -- which kind of integration to use. Can provide at most one of these, or omit. |
| 98 | +; The default is to try symbolic, and if that doesn't work, use numeric. However, if #:symbolic is listed |
| 99 | +; explicitly, then either symbolic integration must succeed or the system raises an exception. |
97 | 100 | ; #:dt d -- time step (only allowed with #:numeric)
|
98 | 101 | ; Example: (integral (sin x) #:var x #:numeric #:dt 0.1)
|
99 |
| -(require (for-syntax "symbolic-integration.rkt")) ; function to do simple symbolic integration |
| 102 | +(require (for-syntax "integral-preprocessor.rkt")) |
100 | 103 | (require (for-syntax syntax/parse))
|
101 | 104 | (define-syntax (integral stx)
|
102 | 105 | (syntax-parse stx
|
103 |
| - [(integral e:expr (~or (~optional (~seq #:var v:expr)) (~optional #:numeric) (~optional #:symbolic) (~optional (~seq #:dt d:expr))) ...) |
104 |
| - (with-syntax ([intgl (datum->syntax stx (symbolic-integral (syntax->datum #'e) |
105 |
| - (if (attribute v) (syntax->datum #'v) '(milliseconds))))] |
106 |
| - [id (datum->syntax stx (gensym))]) |
107 |
| - #'(send this integral-helper (lambda () (send this wally-evaluate intgl)) 'id (interesting-time?)))])) |
| 106 | + [(integral e:expr (~or (~optional (~seq #:var v:expr)) |
| 107 | + (~optional (~seq (~and #:numeric numeric-kw))) |
| 108 | + (~optional (~seq (~and #:symbolic symbolic-kw))) |
| 109 | + (~optional (~seq #:dt dt:expr))) ...) |
| 110 | + (let-values ([(symbolic? symbolic-integral dt) |
| 111 | + (integral-preprocessor (syntax->datum #'e) |
| 112 | + (if (attribute v) (syntax->datum #'v) '(milliseconds)) |
| 113 | + (attribute numeric-kw) |
| 114 | + (attribute symbolic-kw) |
| 115 | + (if (attribute dt) (syntax->datum #'dt) #f))]) |
| 116 | + (if symbolic? |
| 117 | + (with-syntax ([s (datum->syntax stx symbolic-integral)] ; symbolic version |
| 118 | + [id (datum->syntax stx (gensym))]) |
| 119 | + #'(send this integral-symbolic-run-time-fn (lambda () (send this wally-evaluate s)) 'id (interesting-time?))) |
| 120 | + (with-syntax ([d (datum->syntax stx dt)] |
| 121 | + [id (datum->syntax stx (gensym))]) ; numeric version |
| 122 | + #'(send this integral-numeric-run-time-fn (lambda () (send this wally-evaluate e)) 'id d))))])) |
108 | 123 |
|
109 | 124 |
|
110 | 125 | (define reactive-thing%
|
|
146 | 161 | (max-or-min (f) (hash-ref accumulator-values id)))])
|
147 | 162 | (hash-set! accumulator-values id updated-value)
|
148 | 163 | updated-value))
|
149 |
| - ; helper for code generated by integral macro |
150 |
| - (define/public (integral-helper f id interesting) |
| 164 | + ; runtime function for code generated by integral macro for symbolic integration -- this should evaluate to the |
| 165 | + ; correct value for (integral expr) at the current time |
| 166 | + (define/public (integral-symbolic-run-time-fn f id interesting) |
151 | 167 | ; If the value for this integral isn't stored already, or if this is the first time through a 'while', save that value.
|
152 | 168 | ; Hack (hopefully temporary): if time=0, also save the value (i.e., reset the value for this integral). This is
|
153 | 169 | ; to get around a bug where the integral expression is being evaluated on startup before all variables have values.
|
154 | 170 | (cond [(or (not (hash-has-key? accumulator-values id)) (eq? interesting 'first) (equal? (send this milliseconds-evaluated) 0))
|
155 | 171 | (hash-set! accumulator-values id (f))
|
156 | 172 | 0.0]
|
157 | 173 | [else (- (f) (hash-ref accumulator-values id))]))
|
| 174 | + ; version for code for numeric integration |
| 175 | + (define/public (integral-numeric-run-time-fn f id dt) |
| 176 | + (error "not finished\n")) |
158 | 177 |
|
159 | 178 | (define/override (milliseconds)
|
160 | 179 | symbolic-time)
|
|
0 commit comments