r5rs niternal definitions as r5rs letrec instead mz letrec
svn: r9286
This commit is contained in:
parent
aa1a56c3fd
commit
b372856777
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
(module main scheme/base
|
(module main scheme/base
|
||||||
(require scheme/mpair
|
(require scheme/mpair
|
||||||
(for-syntax scheme/base)
|
(for-syntax scheme/base syntax/kerncase)
|
||||||
(only-in mzscheme transcript-on transcript-off))
|
(only-in mzscheme transcript-on transcript-off))
|
||||||
|
|
||||||
(provide (for-syntax syntax-rules ...)
|
(provide (for-syntax syntax-rules ...)
|
||||||
|
@ -227,47 +227,60 @@
|
||||||
;; Copied from R5rS, but with an added `let' around body,
|
;; Copied from R5rS, but with an added `let' around body,
|
||||||
;; and with optimization for precedure letrecs
|
;; and with optimization for precedure letrecs
|
||||||
(define undefined (letrec ([u u]) u))
|
(define undefined (letrec ([u u]) u))
|
||||||
(define-syntax r5rs:letrec
|
(define-for-syntax (immediate-value? stx)
|
||||||
(syntax-rules (r5rs:lambda)
|
(let ([v (syntax-e stx)])
|
||||||
((r5rs:letrec ((var1 (r5rs:lambda . _rest)) ...) body ...)
|
(or (number? v)
|
||||||
(letrec ((var1 (r5rs:lambda . _rest)) ...) body ...))
|
(boolean? v)
|
||||||
|
(string? v)
|
||||||
|
(syntax-case stx (r5rs:lambda quote r5rs:quote #%datum)
|
||||||
|
[(r5rs:lambda . _rest) #t]
|
||||||
|
[(quote . _) #t]
|
||||||
|
[(r5rs:quote . _) #t]
|
||||||
|
[(#%datum . _) #t]
|
||||||
|
[_ #f]))))
|
||||||
|
(define-syntax (r5rs:letrec stx)
|
||||||
|
(syntax-case stx (r5rs:lambda)
|
||||||
|
((r5rs:letrec ((var1 rhs) ...) body ...)
|
||||||
|
(andmap immediate-value? (syntax->list #'(rhs ...)))
|
||||||
|
#'(letrec ((var1 rhs) ...) (r5rs:body body ...)))
|
||||||
((r5rs:letrec ((var1 init1) ...) body ...)
|
((r5rs:letrec ((var1 init1) ...) body ...)
|
||||||
(r5rs:letrec "generate_temp_names"
|
#'(r5rs:letrec "generate_temp_names"
|
||||||
(var1 ...)
|
(var1 ...)
|
||||||
()
|
()
|
||||||
((var1 init1) ...)
|
((var1 init1) ...)
|
||||||
body ...))
|
body ...))
|
||||||
((r5rs:letrec "generate_temp_names"
|
((r5rs:letrec "generate_temp_names"
|
||||||
()
|
()
|
||||||
(temp1 ...)
|
(temp1 ...)
|
||||||
((var1 init1) ...)
|
((var1 init1) ...)
|
||||||
body ...)
|
body ...)
|
||||||
(let ((var1 undefined) ...)
|
#'(let ((var1 undefined) ...)
|
||||||
(let ((temp1 init1) ...)
|
(let ((temp1 init1) ...)
|
||||||
(set! var1 temp1)
|
(set! var1 temp1)
|
||||||
...
|
...
|
||||||
(let ()
|
(let ()
|
||||||
body ...))))
|
(r5rs:body
|
||||||
|
body ...)))))
|
||||||
((r5rs:letrec "generate_temp_names"
|
((r5rs:letrec "generate_temp_names"
|
||||||
(x y ...)
|
(x y ...)
|
||||||
(temp ...)
|
(temp ...)
|
||||||
((var1 init1) ...)
|
((var1 init1) ...)
|
||||||
body ...)
|
body ...)
|
||||||
(r5rs:letrec "generate_temp_names"
|
#'(r5rs:letrec "generate_temp_names"
|
||||||
(y ...)
|
(y ...)
|
||||||
(newtemp temp ...)
|
(newtemp temp ...)
|
||||||
((var1 init1) ...)
|
((var1 init1) ...)
|
||||||
body ...))))
|
body ...))))
|
||||||
|
|
||||||
(define-syntax r5rs:lambda
|
(define-syntax r5rs:lambda
|
||||||
;; Convert rest-arg list to mlist:
|
;; Convert rest-arg list to mlist:
|
||||||
(syntax-rules ()
|
(syntax-rules ()
|
||||||
[(_ (id ...) . body)
|
[(_ (id ...) . body)
|
||||||
(#%plain-lambda (id ...) . body)]
|
(#%plain-lambda (id ...) (r5rs:body . body))]
|
||||||
[(_ (id ... . rest) . body)
|
[(_ (id ... . rest) . body)
|
||||||
(#%plain-lambda (id ... . rest)
|
(#%plain-lambda (id ... . rest)
|
||||||
(let ([rest (list->mlist rest)])
|
(let ([rest (list->mlist rest)])
|
||||||
. body))]))
|
(r5rs:body . body)))]))
|
||||||
|
|
||||||
(define-syntax (r5rs:define stx)
|
(define-syntax (r5rs:define stx)
|
||||||
;; Use r5rs:lambda
|
;; Use r5rs:lambda
|
||||||
|
@ -283,6 +296,12 @@
|
||||||
(define . rest))]))
|
(define . rest))]))
|
||||||
|
|
||||||
(define-syntax (r5rs:define-syntax stx)
|
(define-syntax (r5rs:define-syntax stx)
|
||||||
|
;; Disallow in internal-definition contexts:
|
||||||
|
(when (pair? (syntax-local-context))
|
||||||
|
(raise-syntax-error
|
||||||
|
#f
|
||||||
|
"disallowed as an internal definition"
|
||||||
|
stx))
|
||||||
(syntax-case stx ()
|
(syntax-case stx ()
|
||||||
[(_ id expr)
|
[(_ id expr)
|
||||||
(identifier? #'id)
|
(identifier? #'id)
|
||||||
|
@ -316,6 +335,98 @@
|
||||||
(apply values (promise-p p)))
|
(apply values (promise-p p)))
|
||||||
(apply values v))))
|
(apply values v))))
|
||||||
|
|
||||||
|
(define-syntax r5rs:let
|
||||||
|
(syntax-rules ()
|
||||||
|
[(_ (binding ...) . body)
|
||||||
|
(let (binding ...) (r5rs:body . body))]
|
||||||
|
[(_ id (binding ...) . body)
|
||||||
|
(let id (binding ...) (r5rs:body . body))]))
|
||||||
|
(define-syntax-rule (r5rs:let* bindings . body)
|
||||||
|
(let* bindings (r5rs:body . body)))
|
||||||
|
(define-syntax-rule (r5rs:let-syntax bindings . body)
|
||||||
|
(let-syntax bindings (r5rs:body . body)))
|
||||||
|
(define-syntax-rule (r5rs:letrec-syntax bindings . body)
|
||||||
|
(letrec-syntax bindings (r5rs:body . body)))
|
||||||
|
|
||||||
|
(define-syntax (r5rs:body stx)
|
||||||
|
(syntax-case stx (let)
|
||||||
|
[(_ (let () . body))
|
||||||
|
#'(let () . body)]
|
||||||
|
[_
|
||||||
|
;; Convert internal definitions to `r5rs:letrec', as opposed
|
||||||
|
;; to `letrec'.
|
||||||
|
(let ([def-ctx (syntax-local-make-definition-context)]
|
||||||
|
[ctx (list (gensym 'intdef))]
|
||||||
|
[kernel-forms (kernel-form-identifier-list)]
|
||||||
|
[init-exprs (let ([v (syntax->list stx)])
|
||||||
|
(unless v
|
||||||
|
(raise-syntax-error #f "bad syntax" stx))
|
||||||
|
(cdr v))])
|
||||||
|
(with-syntax ([(exprs ((id ...) ...) (rhs ...) (stx-ids ...) (stx-rhs ...))
|
||||||
|
(let loop ([exprs init-exprs]
|
||||||
|
[idss null][rhss null]
|
||||||
|
[stx-idss null][stx-rhss null])
|
||||||
|
(if (null? exprs)
|
||||||
|
(raise-syntax-error
|
||||||
|
#f
|
||||||
|
"no expression in body"
|
||||||
|
stx)
|
||||||
|
(let ([expr (local-expand (car exprs) ctx kernel-forms def-ctx)])
|
||||||
|
(syntax-case expr (begin define-syntaxes define-values)
|
||||||
|
[(begin . rest)
|
||||||
|
(let ([l (syntax->list #'rest)])
|
||||||
|
(if l
|
||||||
|
(loop (append l exprs) idss rhss stx-idss stx-rhss)
|
||||||
|
(raise-syntax-error #f expr "bad syntax")))]
|
||||||
|
[(define-syntaxes (id ...) rhs)
|
||||||
|
(andmap identifier? (syntax->list #'(id ...)))
|
||||||
|
(with-syntax ([rhs (local-transformer-expand
|
||||||
|
#'rhs
|
||||||
|
'expression
|
||||||
|
null)])
|
||||||
|
(syntax-local-bind-syntaxes
|
||||||
|
(syntax->list #'(id ...))
|
||||||
|
#'rhs def-ctx)
|
||||||
|
(loop (cdr exprs)
|
||||||
|
idss rhss
|
||||||
|
(cons #'(id ...) stx-idss)
|
||||||
|
(cons #'rhs stx-rhss)))]
|
||||||
|
[(define-values (id ...) rhs)
|
||||||
|
(andmap identifier? (syntax->list #'(id ...)))
|
||||||
|
(let ([ids (syntax->list #'(id ...))])
|
||||||
|
(syntax-local-bind-syntaxes ids #f def-ctx)
|
||||||
|
(loop (cdr exprs)
|
||||||
|
(cons #'(id ...) idss)
|
||||||
|
(cons #'rhs rhss)
|
||||||
|
stx-idss stx-rhss))]
|
||||||
|
[else
|
||||||
|
(list (cons expr
|
||||||
|
(map (lambda (expr)
|
||||||
|
(local-expand expr ctx kernel-forms def-ctx))
|
||||||
|
(cdr exprs)))
|
||||||
|
(reverse idss) (reverse rhss)
|
||||||
|
(reverse stx-idss) (reverse stx-rhss))]))))])
|
||||||
|
(if (and (null? (syntax-e #'(stx-rhs ...)))
|
||||||
|
(andmap (lambda (ids)
|
||||||
|
(= 1 (length (syntax->list ids))))
|
||||||
|
(syntax->list #'((id ...) ...))))
|
||||||
|
;; This is the normal case: use `r5rs:letrec':
|
||||||
|
#`(r5rs:letrec ([id ... rhs] ...)
|
||||||
|
(let () . exprs))
|
||||||
|
;; Unusual case: need to expand to `set!' manually:
|
||||||
|
(with-syntax ([((tmp-id ...) ...)
|
||||||
|
(map (lambda (ids)
|
||||||
|
(generate-temporaries ids))
|
||||||
|
(syntax->list #'((id ...) ...)))])
|
||||||
|
#`(letrec-syntaxes+values
|
||||||
|
([stx-ids stx-rhs] ...)
|
||||||
|
([(id ...) (values (mk-undefined id) ...)] ...)
|
||||||
|
(let-values ([(tmp-id ...) rhs] ...)
|
||||||
|
(begin (set! id tmp-id) ...) ...
|
||||||
|
. exprs))))))]))
|
||||||
|
|
||||||
|
(define-syntax-rule (mk-undefined id) undefined)
|
||||||
|
|
||||||
(provide unquote unquote-splicing
|
(provide unquote unquote-splicing
|
||||||
(rename-out [r5rs:quote quote]
|
(rename-out [r5rs:quote quote]
|
||||||
[r5rs:quasiquote quasiquote]
|
[r5rs:quasiquote quasiquote]
|
||||||
|
@ -324,10 +435,13 @@
|
||||||
[r5rs:letrec letrec]
|
[r5rs:letrec letrec]
|
||||||
[r5rs:define define]
|
[r5rs:define define]
|
||||||
[r5rs:define-syntax define-syntax]
|
[r5rs:define-syntax define-syntax]
|
||||||
[r5rs:delay delay])
|
[r5rs:delay delay]
|
||||||
let and or cond case do
|
[r5rs:let let]
|
||||||
let* begin set!
|
[r5rs:let* let*]
|
||||||
let-syntax letrec-syntax
|
[r5rs:let-syntax let-syntax]
|
||||||
|
[r5rs:letrec-syntax letrec-syntax])
|
||||||
|
and or cond case do
|
||||||
|
begin set!
|
||||||
=> else
|
=> else
|
||||||
|
|
||||||
;; We have to include the following MzScheme-isms to do anything,
|
;; We have to include the following MzScheme-isms to do anything,
|
||||||
|
|
Loading…
Reference in New Issue
Block a user