|
194 | 194 | ((_ obj val)
|
195 | 195 | (vector-set! obj ,i val))))
|
196 | 196 | r))))))))))))
|
| 197 | + |
| 198 | +(define-syntax generate-dispatch-table |
| 199 | + (er-macro-transformer |
| 200 | + (lambda (form rename compare) |
| 201 | + (smatch form |
| 202 | + ((_ prefix) |
| 203 | + `(vector ,@(imap (lambda (p) |
| 204 | + (string->symbol (string-append |
| 205 | + (symbol->string prefix) "/" |
| 206 | + (symbol->string (car p))))) |
| 207 | + .intermediate-tags.))))))) |
| 208 | + |
| 209 | +;; used both pass1 and pass2 |
| 210 | +(define (id->bound-gloc id) |
| 211 | + (let ((gloc (find-binding (id-library id) (id-name id) #f))) |
| 212 | + (and gloc (gloc-bound? gloc) gloc))) |
| 213 | + |
| 214 | +;; to avoid unneccessary stack trace, we use guard. |
| 215 | +;; this is not the same as the one in exceptions.scm |
| 216 | +;; this does not use call/cc |
| 217 | +(define-syntax guard |
| 218 | + (syntax-rules () |
| 219 | + ((_ (var . clauses) . body) |
| 220 | + (with-error-handler |
| 221 | + (lambda (e) |
| 222 | + (let ((var e)) |
| 223 | + (%guard-rec var e . clauses))) |
| 224 | + (lambda () . body) #t)))) |
| 225 | + |
| 226 | +(define-syntax %guard-rec |
| 227 | + (syntax-rules (else =>) |
| 228 | + ((%guard-rec var exc) |
| 229 | + (raise exc)) |
| 230 | + ((%guard-rec var exc (else . exprs)) |
| 231 | + (begin . exprs)) |
| 232 | + ((%guard-rec var exc (test => proc) . more) |
| 233 | + (let ((tmp test)) |
| 234 | + (if tmp |
| 235 | + (proc tmp) |
| 236 | + (%guard-rec var exc . more)))) |
| 237 | + ((%guard-rec var exc (test . exprs) . more) |
| 238 | + (if test |
| 239 | + (begin . exprs) |
| 240 | + (%guard-rec var exc . more))) |
| 241 | + ((%guard-rec var exc other . more) |
| 242 | + (syntax-error "malformed guard clause" other)))) |
| 243 | + |
| 244 | +(define (add-backtrace c src) (make-trace-condition (truncate-program src))) |
| 245 | + |
| 246 | +(define (format-source-info info) |
| 247 | + (if info |
| 248 | + (format "~s:~d" (car info) (cdr info)) |
| 249 | + #f)) |
| 250 | + |
| 251 | +(define (truncate-program program) |
| 252 | + (if (circular-list? program) |
| 253 | + program |
| 254 | + (unwrap-syntax program))) |
| 255 | + |
| 256 | +;; IFORM must be a $LAMBDA node. This expands the application of IFORM |
| 257 | +;; on IARGS (list of IForm) into a mere $LET node. |
| 258 | +;; used both pass1 and pass2 |
| 259 | +(define (expand-inlined-procedure src iform iargs) |
| 260 | + (let ((lvars ($lambda-lvars iform)) |
| 261 | + (args (adjust-arglist src |
| 262 | + ($lambda-args iform) |
| 263 | + ($lambda-option iform) |
| 264 | + iargs ($lambda-name iform)))) |
| 265 | + (ifor-each2 (lambda (lv a) (lvar-initval-set! lv a)) lvars args) |
| 266 | + ($let src 'let lvars args ($lambda-body iform)))) |
| 267 | + |
| 268 | +;; Adjust argmuent list according to reqargs and optarg count. |
| 269 | +;; Used in procedure inlining and local call optimization. |
| 270 | +;; used both pass1 and pass2 |
| 271 | +(define (adjust-arglist src reqargs optarg iargs name) |
| 272 | + (unless (argcount-ok? iargs reqargs (> optarg 0)) |
| 273 | + (raise (condition (make-compile-error |
| 274 | + (format-source-info (source-info src)) |
| 275 | + (truncate-program src)) |
| 276 | + (make-who-condition name) |
| 277 | + (make-message-condition |
| 278 | + (format |
| 279 | + "wrong number of arguments: ~s requires ~a, but got ~a" |
| 280 | + name reqargs (length iargs)))))) |
| 281 | + (if (zero? optarg) |
| 282 | + iargs |
| 283 | + (receive (reqs opts) (split-at iargs reqargs) |
| 284 | + (append! reqs (list ($list #f opts)))))) |
| 285 | + |
| 286 | +;; used both pass1 and pass2 |
| 287 | +(define (argcount-ok? args reqargs optarg?) |
| 288 | + (let ((nargs (length args))) |
| 289 | + (or (and (not optarg?) (= nargs reqargs)) |
| 290 | + (and optarg? (>= nargs reqargs))))) |
| 291 | + |
| 292 | +;; see if the given iform is referentially transparent. That is the iform is |
| 293 | +;; side effect free, and alto the value of iform won't change even if we move |
| 294 | +;; iform to a differnet place in the subtree. |
| 295 | +(define (everyc proc lis c) ;avoid closure allocation |
| 296 | + (or (null? lis) |
| 297 | + (let loop ((lis lis)) |
| 298 | + (smatch lis |
| 299 | + ((x) (proc x c)) |
| 300 | + ((x . xs) (and (proc x c) (loop xs))))))) |
| 301 | +;; used both pass2 and pass3 |
| 302 | +(define (transparent? iform) (transparent?/rec iform (make-label-dic #f))) |
| 303 | +(define (transparent?/rec iform labels) |
| 304 | + (case/unquote (iform-tag iform) |
| 305 | + (($LREF ) (zero? (lvar-set-count ($lref-lvar iform)))) |
| 306 | + (($GREF ) (inlinable-binding? ($gref-id iform) #t)) |
| 307 | + (($CONST $LAMBDA $IT $UNDEF) #t) |
| 308 | + (($IF ) (and (transparent?/rec ($if-test iform) labels) |
| 309 | + (transparent?/rec ($if-then iform) labels) |
| 310 | + (transparent?/rec ($if-else iform) labels))) |
| 311 | + (($LET ) (and (everyc transparent?/rec ($let-inits iform) labels) |
| 312 | + (transparent?/rec ($let-body iform) labels))) |
| 313 | + (($LABEL ) (or (label-seen? labels iform) |
| 314 | + (begin (label-push! labels iform) |
| 315 | + (transparent?/rec ($label-body iform) labels)))) |
| 316 | + (($SEQ ) (everyc transparent?/rec ($seq-body iform) labels)) |
| 317 | + (($CALL ) (and (no-side-effect-call? ($call-proc iform) ($call-args iform)) |
| 318 | + (everyc transparent?/rec ($call-args iform) labels))) |
| 319 | + (($ASM ) (and (no-side-effect-insn? ($asm-insn iform) ($asm-args iform)) |
| 320 | + (everyc transparent?/rec ($asm-args iform) labels))) |
| 321 | + (($LIST ) (everyc transparent?/rec ($list-args iform) labels)) |
| 322 | + (($RECEIVE) (and (transparent?/rec ($receive-expr iform) labels) |
| 323 | + (transparent?/rec ($receive-body iform) labels))) |
| 324 | + (else #f))) |
| 325 | + |
| 326 | +;; label dictionary |
| 327 | +(define (make-label-dic init) (list init)) |
| 328 | +(define (copy-label-dic label) (cons (car label) (cdr label))) |
| 329 | +(define (label-seen? label-dic label-node) |
| 330 | + (memq label-node (cdr label-dic))) |
| 331 | +(define (label-push! label-dic label-node) |
| 332 | + (set-cdr! label-dic (cons label-node (cdr label-dic)))) |
| 333 | +(define (label-dic-info label-dic) (car label-dic)) |
| 334 | +(define (label-dic-info-set! label-dic val) (set-car! label-dic val)) |
| 335 | +(define (label-dic-info-push! label-dic val) |
| 336 | + (set-car! label-dic (cons val (car label-dic)))) |
| 337 | + |
0 commit comments