|
119 | 119 | [(ssyntax? (xcar s)) (ac (cons (expand-ssyntax (car s)) (cdr s)) env)] |
120 | 120 | [(eq? (xcar s) '$) (ac-$ (cadr s) env)] |
121 | 121 | [(eq? (xcar s) 'quote) (list 'quote (ac-quoted (cadr s)))] |
| 122 | + ((eq? (xcar s) 'lexenv) (ac-lenv (cdr s) env)) |
122 | 123 | [(and (eq? (xcar s) 'quasiquote) |
123 | 124 | (not (ac-macro? 'quasiquote))) |
124 | 125 | (ac-qq (cadr s) env)] |
|
323 | 324 | #f) |
324 | 325 |
|
325 | 326 | (define (ac-var-ref s env) |
326 | | - (cond [(lex? s env) s] |
| 327 | + (cond [(ac-boxed? 'get s) (ac-boxed-get s)] |
| 328 | + [(lex? s env) s] |
327 | 329 | [(ac-defined-var? s) (list (ac-global-name s))] |
328 | 330 | [#t (ac-global-name s)])) |
329 | 331 |
|
|
550 | 552 | (list 'let `([zz ,b]) |
551 | 553 | (cond [(eqv? a 'nil) (err "Can't rebind nil")] |
552 | 554 | [(eqv? a 't) (err "Can't rebind t")] |
| 555 | + [(ac-boxed? 'set a) `(begin ,(ac-boxed-set a b) ,(ac-boxed-get a))] |
553 | 556 | [(lex? a env) `(set! ,a zz)] |
554 | 557 | [(ac-defined-var? a) `(,(ac-global-name a) zz)] |
555 | 558 | [#t `(set! ,(ac-global-name a) zz)]) |
|
568 | 571 | (cdr exprs) |
569 | 572 | env)))) |
570 | 573 |
|
| 574 | +(define (ac-lexname env) |
| 575 | + (let ((name (ac-dbname env))) |
| 576 | + (if (eqv? name #f) |
| 577 | + 'fn |
| 578 | + (apply string-append |
| 579 | + (map (lambda (x) (string-append (symbol->string x) "-")) |
| 580 | + (apply append (keep pair? env))))))) |
| 581 | + |
| 582 | +(define (ac-lenv args env) |
| 583 | + (ac-lexenv (ac-lexname env) env)) |
| 584 | + |
| 585 | +(define (ac-lexenv name env) |
| 586 | + `(list (list '*name ',name) |
| 587 | + ,@(imap (lambda (var) |
| 588 | + (let ((val (gensym))) |
| 589 | + `(list ',var |
| 590 | + (lambda ,val ,var) |
| 591 | + (lambda (,val) (set! ,var ,val))))) |
| 592 | + (filter (lambda (x) (not (or (ar-false? x) (pair? x)))) env)))) |
| 593 | + |
| 594 | +(define boxed* '()) |
| 595 | + |
| 596 | +(define (ac-boxed? op name) |
| 597 | + (let ((result |
| 598 | + (when (not (ar-false? name)) |
| 599 | + (when (not (ar-false? boxed*)) |
| 600 | + (let ((slot (assoc name boxed*))) |
| 601 | + (case op |
| 602 | + ((get) (when (and slot (>= (length slot) 2)) (cadr slot))) |
| 603 | + ((set) (when (and slot (>= (length slot) 3)) (caddr slot))) |
| 604 | + (else (err "ac-boxed?: bad op" name op)))))))) |
| 605 | + (if (void? result) #f result))) |
| 606 | + |
| 607 | +(define (ac-boxed-set name val) |
| 608 | + (let ((setter (ac-boxed? 'set name))) |
| 609 | + (if (procedure? setter) |
| 610 | + `(,setter ,val) |
| 611 | + (err "invalid setter" name val setter)))) |
| 612 | + |
| 613 | +(define (ac-boxed-get name) |
| 614 | + (let ((getter (ac-boxed? 'get name))) |
| 615 | + (if (procedure? getter) |
| 616 | + `(,getter 'nil) |
| 617 | + getter))) |
| 618 | + |
| 619 | + |
571 | 620 | ; generate special fast code for ordinary two-operand |
572 | 621 | ; calls to the following functions. this is to avoid |
573 | 622 | ; calling e.g. ar-is with its &rest and apply. |
|
1265 | 1314 | (eval (parameterize ([compile-allow-set!-undefined #t]) |
1266 | 1315 | (compile racket-expr)))) |
1267 | 1316 |
|
1268 | | -(define (arc-eval expr) |
1269 | | - (arc-exec (ac expr '()))) |
| 1317 | +(define (arc-eval expr . args) |
| 1318 | + (if (null? args) |
| 1319 | + (arc-exec (ac expr '())) |
| 1320 | + (apply arc-eval-boxed expr args))) |
| 1321 | + |
| 1322 | +(define-syntax w/restore |
| 1323 | + (syntax-rules () |
| 1324 | + ((_ var val body ...) |
| 1325 | + (let ((w/restore-prev var) |
| 1326 | + (w/restore-val val)) |
| 1327 | + (dynamic-wind (lambda () (set! var w/restore-val)) |
| 1328 | + (lambda () body ...) |
| 1329 | + (lambda () (set! var w/restore-prev))))))) |
| 1330 | + |
| 1331 | +(define (arc-eval-boxed expr lexenv) |
| 1332 | + (w/restore boxed* (if (or (ar-false? boxed*) |
| 1333 | + (ar-false? lexenv)) |
| 1334 | + lexenv |
| 1335 | + (append lexenv boxed*)) |
| 1336 | + (arc-eval expr))) |
1270 | 1337 |
|
1271 | 1338 | (define (tle) |
1272 | 1339 | (display "Arc> ") |
|
0 commit comments