r6rs module layer

svn: r8676
This commit is contained in:
Matthew Flatt 2008-02-15 22:27:54 +00:00
parent f69f0753e3
commit 5dfcc624f8
5 changed files with 479 additions and 6 deletions

1
collects/r6rs/info.ss Normal file
View File

@ -0,0 +1 @@
#lang setup/infotab

View File

@ -1,9 +1,381 @@
#lang scheme/base
(provide (rename-out [module-begin #%module-begin])
quote)
#|
FIXME:
* (for ... expand) should shift all exports, not just run-time (requires a mzscheme change)
* need meta levels other than 0, 1, and -1
* Check that each identifier is imported only once across phases.
|#
(define-syntax-rule (module-begin . stuff)
(#%module-begin
"The R6RS language just supplies a reader, so far."
'stuff))
(require (for-syntax scheme/base
syntax/kerncase
"private/find-version.ss"))
(provide (rename-out [module-begin #%module-begin]))
;; ----------------------------------------
;; Library and top-level forms
(define-for-syntax (syntax-list? stx)
(syntax->list stx))
(define-syntax (module-begin stx)
(syntax-case stx (library)
[(_ (library . rest))
;; A library
(with-syntax ([(_ orig) stx])
#'(#%plain-module-begin
(library-body orig . rest)))]
[(_ (library . rest) . _)
(raise-syntax-error
#f
"allowed only in as a top-level module by itself"
(syntax-case stx ()
[(_ lib . _) #'lib]))]
[(_ decl . rest)
(syntax-list? #'rest)
;; A top-level program
#'(#%plain-module-begin
(top-level-body decl . rest))]
[(_)
(raise-syntax-error 'r6rs
(string-append
"must contain a `library' form (for a library)"
" or start with `import' (for a top-level program)")
stx)]
[_
(raise-syntax-error #f "ill-formed module (misuse of `.')" stx)]))
(define-syntax (top-level-body stx)
(syntax-case stx (import)
[(_ (import . im) . rest)
(syntax-list? #'im)
(with-syntax ([(_ im . _) stx])
#'(begin
(r6rs-import im)
. rest))]
[(_ (import . im) . rest)
(raise-syntax-error #f
"ill-formed imports (misuse of `.')"
(syntax-case stx ()
[(_ im . _) #'im]))]
[(_ thing . _)
(raise-syntax-error 'top-level-program
"expected an `import' declaration, found something else"
#'thing)]))
(define-for-syntax (symbolic-identifier=? a b)
(eq? (syntax-e a) (syntax-e b)))
(define-for-syntax (valid-library-name? n)
(syntax-case n ()
[(id id2 ... (vers ...))
(and (identifier? #'id)
(andmap identifier? (syntax->list #'(id2 ...)))
(andmap (lambda (v)
(exact-nonnegative-integer? (syntax-e v)))
(syntax->list #'(vers ...))))]
[(id id2 ...)
(valid-library-name? #'(id id2 ... ()))]
[_ #f]))
(define-syntax (library-body stx)
(syntax-case* stx (export import) symbolic-identifier=?
[(_ orig name
(export . ex)
(import . im)
. body)
(and (valid-library-name? #'name)
(syntax-list? #'ex)
(syntax-list? #'im)
(syntax-list? #'body))
(with-syntax ([(_ _ _ ex im . _) stx])
#'(begin
(r6rs-import im)
(r6rs-export ex)
(library-body/defns . body)))]
[(_ orig name . _)
(not (valid-library-name? #'name))
(raise-syntax-error #f
"invalid library name"
#'orig
#'name)]
[(_ orig name (export . ex) . _)
(not (syntax-list? #'ex))
(raise-syntax-error #f
"ill-formed export sequence (misuse of `.')"
#'orig
(syntax-case stx ()
[(_ _ _ ex . _) #'ex]))]
[(_ orig name (export . ex) (import . im) . _)
(not (syntax-list? #'im))
(raise-syntax-error #f
"ill-formed import sequence (misuse of `.')"
#'orig
(syntax-case stx ()
[(_ _ _ _ im . _) #'im]))]
[(_ orig name (export . ex) (import . im) . _)
(raise-syntax-error #f
"ill-formed body (misuse of `.')"
#'orig)]
[(_ orig name (export . ex))
(raise-syntax-error #f
"missing `import' clause"
#'orig)]
[(_ orig name (export . ex) im . _)
(raise-syntax-error #f
"expected `import' clause, found something else"
#'orig
#'im)]
[(_ orig name)
(raise-syntax-error #f
"missing `export' and `import' clauses"
#'orig)]
[(_ orig name ex . _)
(raise-syntax-error #f
"expected `export' clause, found something else"
#'orig
#'ex)]
[(_ orig)
(raise-syntax-error #f
"missing name, `export' clauses, and `import' clause"
#'orig)]
[(_ orig . _)
(raise-syntax-error #f
"ill-formed library"
#'orig)]))
(define-syntax (library-body/defns stx)
(syntax-case stx ()
[(_ thing . more)
(let ([a (local-expand
#'thing
'module
(kernel-form-identifier-list))])
(syntax-case a (begin)
[(def . _)
(ormap (lambda (id)
(free-identifier=? id #'def))
(list #'define-values
#'define-syntaxes
#'define-values-for-syntax))
#`(begin #,a (library-body/defns . more))]
[(begin sub ...)
#`(library-body/defns sub ... . more)]
[else
#`(begin (let () #,a . more))]))]
[(_) #'(begin)]))
;; ----------------------------------------
;; Imports and exports
(define-for-syntax (is-sub-version-reference? stx)
(syntax-case* stx (<= >= and or not) symbolic-identifier=?
[n (exact-nonnegative-integer? (syntax-e #'n)) #t]
[(>= n) (exact-nonnegative-integer? (syntax-e #'n))]
[(<= n) (exact-nonnegative-integer? (syntax-e #'n))]
[(and sv ...) (andmap is-sub-version-reference? (syntax->list #'(sv ...)))]
[(or sv ...) (andmap is-sub-version-reference? (syntax->list #'(sv ...)))]
[(not sv) (is-sub-version-reference? #'sv)]
[_ #f]))
(define-for-syntax (is-version-reference? stx)
(syntax-case* stx (and or not) symbolic-identifier=?
[(and vr ...)
(andmap is-version-reference? (syntax->list #'(vr ...)))]
[(or vr ...)
(andmap is-version-reference? (syntax->list #'(vr ...)))]
[(not vr)
(is-version-reference? #'vr)]
[(sv ...)
(andmap is-sub-version-reference? (syntax->list #'(sv ...)))]
[_ #f]))
(define-for-syntax (parse-library-reference orig stx)
(syntax-case stx ()
[(id1 id2 ... (vers ...))
(and (identifier? #'id1)
(andmap identifier? (syntax->list #'(id2 ...)))
(is-version-reference? #'(vers ...)))
(let-values ([(coll file)
(let ([strs (map (lambda (id)
(symbol->string (syntax-e id)))
(syntax->list #'(id1 id2 ...)))])
(if (= 1 (length strs))
(values (car strs) "main")
(values (reverse (cdr (reverse strs)))
(car (reverse strs)))))])
(let ([base (build-path (with-handlers ([exn:fail?
(lambda (exn)
(raise-syntax-error
#f
(format
"cannot find suitable library installed (exception: ~a)"
(if (exn? exn)
(exn-message exn)
exn))
orig
stx))])
(apply collection-path coll))
file)])
(let ([vers (find-version (path->bytes base) (syntax->datum #'(vers ...)))])
(if vers
(datum->syntax
stx
`(,#'lib ,(apply string-append
(car coll)
(append
(map (lambda (s)
(string-append "/" s))
(append (cdr coll) (list file)))
(map (lambda (v)
(format "-~a" v))
vers)
(list ".ss")))))
(raise-syntax-error
#f
"cannot find suitable installed library"
orig
stx)))))]
[(id1 id2 ...)
(and (identifier? #'id1)
(andmap identifier? (syntax->list #'(id2 ...))))
(parse-library-reference orig #'(id1 id2 ... ()))]
[_
(raise-syntax-error #f
"ill-formed library reference"
orig
stx)]))
(define-for-syntax (parse-import-set orig stx)
(define (bad)
(raise-syntax-error #f
(format "bad `~a' form"
(syntax-e (car (syntax-e stx))))
orig
stx))
(define (check-id id)
(unless (identifier? id)
(raise-syntax-error #f
(format "not an identifier in `~a' form"
(syntax-e (car (syntax-e stx))))
orig
id)))
(syntax-case* stx (library only except prefix rename) symbolic-identifier=?
[(library lib)
(parse-library-reference orig #'lib)]
[(library . _) (bad)]
[(only im id ...)
(for-each check-id (syntax->list #'(id ...)))
#`(only-in #,(parse-import-set orig #'im) id ...)]
[(only . _) (bad)]
[(except im id ...)
(for-each check-id (syntax->list #'(id ...)))
#`(except-in #,(parse-import-set orig #'im) id ...)]
[(except . _) (bad)]
[(prefix im id)
(check-id #'id)
#`(prefix-in id #,(parse-import-set orig #'im))]
[(prefix . _) (bad)]
[(rename im (id id2) ...)
(for-each check-id
(apply
append
(map syntax->list
(syntax->list #'((id id2) ...)))))
#`(except-in #,(parse-import-set orig #'im) id ...)]
[(rename . _) (bad)]
[_ (parse-library-reference orig stx)]))
(define-syntax (r6rs-import stx)
(let ([orig (syntax-case stx ()
[(_ orig) #'orig])])
(syntax-case stx (import)
[(_ (import im ...))
(with-syntax ([((im ...) ...)
(map (lambda (im)
(syntax-case* im (for) symbolic-identifier=?
[(for base-im level ...)
(let* ([levels
(map (lambda (level)
(syntax-case* level (run expand meta) symbolic-identifier=?
[run #'except-in]
[expand #'for-syntax]
[(meta 0) #'except-in]
[(meta 1) #'for-syntax]
[(meta -1) #'for-template]
[(meta n)
(raise-syntax-error
#f
"meta level not supported"
orig
level)]
[_
(raise-syntax-error
#f
"bad `for' level"
orig
level)]))
(syntax->list #'(level ...)))])
(with-syntax ([is (parse-import-set orig #'im)]
[(level ...) (if (null? levels)
(list #'only-in)
null)])
#`((level is) ...)))]
[(for . _)
(raise-syntax-error
#f
"bad `for' import form"
orig
im)]
[_ (list (parse-import-set orig im))]))
(syntax->list #'(im ...)))])
#'(require im ... ...))])))
(define-syntax (r6rs-export stx)
(let ([orig (syntax-case stx ()
[(_ orig) #'orig])])
(syntax-case stx (export)
[(_ (export ex ...))
(let ([exs (syntax->list #'(ex ...))])
(for-each (lambda (ex)
(unless (identifier? ex)
(syntax-case ex (rename)
[(rename thing ...)
(for-each (lambda (thing)
(syntax-case thing ()
[(id1 id2)
(unless (and (identifier? #'id1)
(identifier? #'id2))
(raise-syntax-error #f
"not an identifier"
orig
(if (identifier? #'id1)
#'id2
#'id1)))]
[_ (raise-syntax-error
#f
"expected `(<id> <id>)' for rename, but found something else"
orig
thing)]))
(syntax->list #'(thing ...)))]
[(rename . _)
(raise-syntax-error #f
"bad syntax (misuse of `.')"
orig
ex)]
[_
(raise-syntax-error #f
"not an identifier or `rename' clause"
orig
ex)])))
exs)
(with-syntax ([(ex ...)
(map (lambda (ex)
(syntax-case ex ()
[(rename . rest)
#'(rename-out . rest)]
[_ ex]))
exs)])
#'(provide ex ...)))])))

View File

@ -0,0 +1,77 @@
#lang scheme/base
(provide find-version)
(define (find-version base-path vers)
(let-values ([(dir name _) (split-path (bytes->path base-path))])
(let ([files (with-handlers ([exn:fail:filesystem? (lambda (exn) null)])
(directory-list dir))])
(and files
(let* ([p (path-element->bytes name)]
[len (bytes-length p)]
[candidate-versions
(filter
values
(map
(lambda (file)
(let ([s (path-element->bytes file)])
(and (len . < . (bytes-length s))
(regexp-match? #rx#"[.]ss$" s)
(bytes=? p (subbytes s 0 len))
(or (and (= (bytes-length s) (+ len 3))
null)
(let ([vers (subbytes s len (- (bytes-length s) 3))])
(and (regexp-match #rx#"^(-[0-9]+)+$" vers)
(map string->number
(cdr
(map bytes->string/latin-1
(regexp-split #rx#"-" vers))))))))))
files))]
[versions
(sort candidate-versions
(lambda (a b)
(let loop ([a a][b b])
(cond
[(null? a) #t]
[(null? b) #f]
[(> (car a) (car b)) #t]
[(< (car a) (car b)) #f]
[else (loop (cdr a) (cdr b))]))))])
(ormap (lambda (candidate-version)
(and (version-match? candidate-version vers)
candidate-version))
versions))))))
(define (version-match? cand vers)
(cond
[(null? vers) #t]
[(null? cand) #f]
[(eq? (car vers) 'and)
(andmap (lambda (v)
(version-match? cand v))
(cdr vers))]
[(eq? (car vers) 'or)
(ormap (lambda (v)
(version-match? cand v))
(cdr vers))]
[(eq? (car vers) 'not)
(not (version-match? (cadr vers)))]
[(sub-version-match? (car cand) (car vers))
(version-match? (cdr cand) (cdr vers))]
[else #f]))
(define (sub-version-match? cand subvers)
(cond
[(number? subvers) (= cand subvers)]
[else (case (car subvers)
[(>=) (>= cand (cadr subvers))]
[(<=) (<= cand (cadr subvers))]
[(and) (andmap (lambda (sv)
(sub-version-match? cand sv))
(cdr subvers))]
[(or) (ormap (lambda (sv)
(sub-version-match? cand sv))
(cdr subvers))]
[(not) (not (sub-version-match? cand (cadr subvers)))]
[else (error "bad subversion")])]))

22
collects/rnrs/base-6.ss Normal file
View File

@ -0,0 +1,22 @@
#lang scheme/base
(require (for-syntax scheme/base)
(prefix-in r5rs: r5rs))
(provide (rename-out [datum #%datum]
[r5rs:define define]
[r5rs:lambda lambda])
#%app)
;; ----------------------------------------
;; Datum
(define-syntax (datum stx)
(syntax-case stx ()
[(_ . thing)
(if (vector? (syntax-e #'thing))
(raise-syntax-error 'r6rs
"a vector is not an expression"
#'thing)
#`(quote thing))]))

1
collects/rnrs/info.ss Normal file
View File

@ -0,0 +1 @@
#lang setup/infotab