-
Notifications
You must be signed in to change notification settings - Fork 2
/
include.sls
66 lines (62 loc) · 2.62 KB
/
include.sls
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#!r6rs
;; Copyright 2009 Derick Eddington. My MIT-style license is in the file named
;; LICENSE from the original collection this file is distributed with.
(library (xitomatl include)
(export
include
include/lexical-context
include/resolve)
(import
(rnrs)
(only (xitomatl include compat) stale-when)
(for (only (xitomatl include compat) read-annotated search-paths) expand)
(for (only (xitomatl file-system base) file-mtime) run expand)
(for (only (xitomatl file-system paths) path-join path?) expand)
(for (only (xitomatl exceptions) error/conditions) expand))
(define-syntax include
(lambda (stx)
(syntax-case stx ()
((ctxt filename)
#'(include/lexical-context ctxt filename)))))
(define-syntax include/lexical-context
(lambda (stx)
(syntax-case stx ()
((_ ctxt filename)
(and (or (identifier? #'ctxt)
(syntax-violation #F "not an identifier" stx #'ctxt))
(or (path? (syntax->datum #'filename))
(syntax-violation #F "not a path" stx #'filename)))
(let* ((fn (syntax->datum #'filename))
(datums
(with-exception-handler
(lambda (ex)
(error/conditions 'include/lexical-context
"error while trying to include" (list fn)
(if (condition? ex) ex (make-irritants-condition (list ex)))))
(lambda ()
(call-with-input-file fn
(lambda (fip)
(let loop ((a '()))
(let ((x (read-annotated fip)))
(if (eof-object? x)
(reverse a)
(loop (cons x a)))))))))))
#`(stale-when
(or (not (file-exists? #,fn))
(> (file-mtime #,fn) #,(file-mtime fn)))
. #,(datum->syntax #'ctxt datums)))))))
(define-syntax include/resolve
(lambda (stx)
(syntax-case stx ()
((ctxt (lib-path* ...) file-path)
(for-all path? (syntax->datum #'(lib-path* ... file-path)))
(let ((p (apply path-join (syntax->datum #'(lib-path* ... file-path))))
(sp (search-paths)))
(let loop ((search sp))
(if (null? search)
(error 'include/resolve "cannot find file in search paths" p sp)
(let ((full (path-join (car search) p)))
(if (file-exists? full)
#`(include/lexical-context ctxt #,full)
(loop (cdr search)))))))))))
)