.
original commit: 5200f352d6becfac3b25078ca70f20e1f5fb55c0
This commit is contained in:
parent
5b897abd58
commit
3ada00788f
|
@ -1,136 +1,177 @@
|
||||||
|
|
||||||
(module include mzscheme
|
(module include mzscheme
|
||||||
(require-for-syntax (lib "stx.ss" "syntax"))
|
(require-for-syntax (lib "stx.ss" "syntax"))
|
||||||
|
(require (lib "etc.ss"))
|
||||||
|
|
||||||
(define-syntax include-at/relative-to
|
(define-syntax-set (do-include ; private
|
||||||
(lambda (stx)
|
include-at/relative-to
|
||||||
;; Parse the file name
|
include
|
||||||
(let-values ([(ctx loc file)
|
include-at/relative-to/reader
|
||||||
(syntax-case* stx (build-path) module-or-top-identifier=?
|
include/reader)
|
||||||
[(_ ctx loc fn)
|
|
||||||
(string? (syntax-e (syntax fn)))
|
(define (do-include/proc stx)
|
||||||
(values (syntax ctx) (syntax loc) (syntax-e (syntax fn)))]
|
(syntax-case stx ()
|
||||||
[(_ ctx loc (build-path elem1 elem ...))
|
[(_ orig-stx ctx loc fn reader)
|
||||||
(andmap
|
;; Parse the file name
|
||||||
(lambda (e)
|
(let ([file
|
||||||
(or (string? (syntax-e e))
|
(syntax-case* (syntax fn) (build-path) module-or-top-identifier=?
|
||||||
(and (identifier? e)
|
[fn
|
||||||
(or
|
(string? (syntax-e (syntax fn)))
|
||||||
(module-identifier=? e (quote-syntax up))
|
(syntax-e (syntax fn))]
|
||||||
(module-identifier=? e (quote-syntax same))))))
|
[(build-path elem1 elem ...)
|
||||||
(syntax->list (syntax (elem1 elem ...))))
|
(apply build-path (syntax-object->datum (syntax (elem1 elem ...))))])]
|
||||||
(values
|
[ctx (syntax ctx)]
|
||||||
(syntax ctx)
|
[loc (syntax loc)]
|
||||||
(syntax loc)
|
[reader (syntax reader)]
|
||||||
(apply build-path (syntax-object->datum (syntax (elem1 elem ...)))))])])
|
[orig-stx (syntax orig-stx)])
|
||||||
;; Complete the file name
|
|
||||||
(let ([c-file
|
(let ([read-syntax (if (syntax-e reader)
|
||||||
(if (complete-path? file)
|
(syntax-local-value reader)
|
||||||
file
|
read-syntax)])
|
||||||
(path->complete-path
|
(unless (and (procedure? read-syntax)
|
||||||
file
|
(procedure-arity-includes? read-syntax 2))
|
||||||
(cond
|
(raise-syntax-error
|
||||||
;; Src of include expression is a path?
|
#f
|
||||||
[(and (string? (syntax-source loc))
|
"reader is not a procedure of two arguments"
|
||||||
(complete-path? (syntax-source loc)))
|
orig-stx))
|
||||||
(let-values ([(base name dir?)
|
|
||||||
(split-path (syntax-source loc))])
|
;; Complete the file name
|
||||||
(if dir?
|
(let ([c-file
|
||||||
(syntax-source loc)
|
(if (complete-path? file)
|
||||||
base))]
|
file
|
||||||
;; Load relative?
|
(path->complete-path
|
||||||
[(current-load-relative-directory)]
|
file
|
||||||
;; Current directory
|
(cond
|
||||||
[(current-directory)]
|
;; Src of include expression is a path?
|
||||||
[else (raise-syntax-error
|
[(and (string? (syntax-source loc))
|
||||||
#f
|
(complete-path? (syntax-source loc)))
|
||||||
"can't determine a base path"
|
(let-values ([(base name dir?)
|
||||||
stx)])))])
|
(split-path (syntax-source loc))])
|
||||||
;; Open the included file
|
(if dir?
|
||||||
(let ([p (with-handlers ([not-break-exn?
|
(syntax-source loc)
|
||||||
(lambda (exn)
|
base))]
|
||||||
(raise-syntax-error
|
;; Load relative?
|
||||||
#f
|
[(current-load-relative-directory)]
|
||||||
(format
|
;; Current directory
|
||||||
"can't open include file (~a)"
|
[(current-directory)]
|
||||||
(if (exn? exn)
|
[else (raise-syntax-error
|
||||||
(exn-message exn)
|
#f
|
||||||
exn))
|
"can't determine a base path"
|
||||||
stx
|
orig-stx)])))])
|
||||||
c-file))])
|
;; Open the included file
|
||||||
(open-input-file c-file))])
|
(let ([p (with-handlers ([not-break-exn?
|
||||||
(port-count-lines! p)
|
(lambda (exn)
|
||||||
;; Read expressions from file
|
(raise-syntax-error
|
||||||
(let ([content
|
#f
|
||||||
(let loop ()
|
(format
|
||||||
(let ([r (with-handlers ([not-break-exn?
|
"can't open include file (~a)"
|
||||||
(lambda (exn)
|
(if (exn? exn)
|
||||||
(raise-syntax-error
|
(exn-message exn)
|
||||||
#f
|
exn))
|
||||||
(format
|
orig-stx
|
||||||
"read error (~a)"
|
c-file))])
|
||||||
(if (exn? exn)
|
(open-input-file c-file))])
|
||||||
(exn-message exn)
|
(port-count-lines! p)
|
||||||
exn))
|
;; Read expressions from file
|
||||||
stx))])
|
(let ([content
|
||||||
(read-syntax c-file p))])
|
(let loop ()
|
||||||
(if (eof-object? r)
|
(let ([r (with-handlers ([not-break-exn?
|
||||||
null
|
(lambda (exn)
|
||||||
(cons r (loop)))))])
|
(raise-syntax-error
|
||||||
;; Preserve src info for content, but set its
|
#f
|
||||||
;; lexical context to be that of the include expression
|
(format
|
||||||
(let ([lexed-content
|
"read error (~a)"
|
||||||
(let loop ([content content])
|
(if (exn? exn)
|
||||||
(cond
|
(exn-message exn)
|
||||||
[(pair? content)
|
exn))
|
||||||
(cons (loop (car content))
|
orig-stx))])
|
||||||
(loop (cdr content)))]
|
(read-syntax c-file p))])
|
||||||
[(null? content) null]
|
(if (eof-object? r)
|
||||||
[else
|
null
|
||||||
(let ([v (syntax-e content)])
|
(cons r (loop)))))])
|
||||||
(datum->syntax-object
|
;; Preserve src info for content, but set its
|
||||||
ctx
|
;; lexical context to be that of the include expression
|
||||||
|
(let ([lexed-content
|
||||||
|
(let loop ([content content])
|
||||||
(cond
|
(cond
|
||||||
[(pair? v)
|
[(pair? content)
|
||||||
(loop v)]
|
(cons (loop (car content))
|
||||||
[(vector? v)
|
(loop (cdr content)))]
|
||||||
(list->vector (loop (vector->list v)))]
|
[(null? content) null]
|
||||||
[(box? v)
|
|
||||||
(box (loop (unbox v)))]
|
|
||||||
[else
|
[else
|
||||||
v])
|
(let ([v (syntax-e content)])
|
||||||
content))]))])
|
(datum->syntax-object
|
||||||
(datum->syntax-object
|
ctx
|
||||||
(quote-syntax here)
|
(cond
|
||||||
`(begin ,@lexed-content)
|
[(pair? v)
|
||||||
stx))))))))
|
(loop v)]
|
||||||
|
[(vector? v)
|
||||||
|
(list->vector (loop (vector->list v)))]
|
||||||
|
[(box? v)
|
||||||
|
(box (loop (unbox v)))]
|
||||||
|
[else
|
||||||
|
v])
|
||||||
|
content))]))])
|
||||||
|
(datum->syntax-object
|
||||||
|
(quote-syntax here)
|
||||||
|
`(begin ,@lexed-content)
|
||||||
|
orig-stx)))))))]))
|
||||||
|
|
||||||
(define-syntax include
|
(define (check-fn-form fn stx)
|
||||||
(lambda (stx)
|
;; Check form of fn:
|
||||||
|
(syntax-case* fn (build-path) module-or-top-identifier=?
|
||||||
|
[fn
|
||||||
|
(string? (syntax-e (syntax fn)))
|
||||||
|
'ok]
|
||||||
|
[(build-path elem1 elem ...)
|
||||||
|
(andmap
|
||||||
|
(lambda (e)
|
||||||
|
(or (string? (syntax-e e))
|
||||||
|
(and (identifier? e)
|
||||||
|
(or
|
||||||
|
(module-identifier=? e (quote-syntax up))
|
||||||
|
(module-identifier=? e (quote-syntax same))))))
|
||||||
|
(syntax->list (syntax (elem1 elem ...))))
|
||||||
|
'ok]
|
||||||
|
[_else (raise-syntax-error #f "bad syntax" stx fn)]))
|
||||||
|
|
||||||
|
(define (include/proc stx)
|
||||||
(syntax-case stx ()
|
(syntax-case stx ()
|
||||||
[(_ fn)
|
[(_ fn)
|
||||||
;; Check form of fn:
|
(check-fn-form (syntax fn) stx)
|
||||||
(syntax-case* (syntax fn) (build-path) module-or-top-identifier=?
|
|
||||||
[fn
|
|
||||||
(string? (syntax-e (syntax fn)))
|
|
||||||
'ok]
|
|
||||||
[(build-path elem1 elem ...)
|
|
||||||
(andmap
|
|
||||||
(lambda (e)
|
|
||||||
(or (string? (syntax-e e))
|
|
||||||
(and (identifier? e)
|
|
||||||
(or
|
|
||||||
(module-identifier=? e (quote-syntax up))
|
|
||||||
(module-identifier=? e (quote-syntax same))))))
|
|
||||||
(syntax->list (syntax (elem1 elem ...))))
|
|
||||||
'ok]
|
|
||||||
[_else (raise-syntax-error #f "bad syntax" stx (syntax fn))])
|
|
||||||
;; Expand to include-at/relative-to:
|
|
||||||
(with-syntax ([_stx stx])
|
(with-syntax ([_stx stx])
|
||||||
(syntax/loc stx (include-at/relative-to _stx _stx fn)))])))
|
(syntax/loc stx (do-include _stx _stx _stx fn #f)))]))
|
||||||
|
|
||||||
|
(define (include-at/relative-to/proc stx)
|
||||||
|
(syntax-case stx ()
|
||||||
|
[(_ ctx loc fn)
|
||||||
|
(check-fn-form (syntax fn) stx)
|
||||||
|
(with-syntax ([_stx stx])
|
||||||
|
(syntax/loc stx (do-include _stx ctx loc fn #f)))]))
|
||||||
|
|
||||||
|
(define (include/reader/proc stx)
|
||||||
|
(syntax-case stx ()
|
||||||
|
[(_ fn reader)
|
||||||
|
(check-fn-form (syntax fn) stx)
|
||||||
|
;; Expand to do-include:
|
||||||
|
(with-syntax ([_stx stx])
|
||||||
|
(syntax/loc stx
|
||||||
|
(let-syntax ([the-reader reader])
|
||||||
|
(do-include _stx _stx _stx fn the-reader))))]))
|
||||||
|
|
||||||
|
(define (include-at/relative-to/reader/proc stx)
|
||||||
|
(syntax-case stx ()
|
||||||
|
[(_ ctx loc fn reader)
|
||||||
|
(check-fn-form (syntax fn) stx)
|
||||||
|
(with-syntax ([_stx stx])
|
||||||
|
(syntax/loc stx
|
||||||
|
(let-syntax ([the-reader reader])
|
||||||
|
(do-include _stx _stx _stx fn the-reader))))])))
|
||||||
|
|
||||||
(provide include
|
(provide include
|
||||||
include-at/relative-to))
|
include-at/relative-to
|
||||||
|
include/reader
|
||||||
|
include-at/relative-to/reader))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user