-
Notifications
You must be signed in to change notification settings - Fork 0
/
dynamic.chezscheme.sls
76 lines (71 loc) · 2.64 KB
/
dynamic.chezscheme.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
67
68
69
70
71
72
73
74
75
76
;; Chez Scheme R6RS Library dynamism.
;;
;; BEWARE: reimport uses (eval)! Use at own risk.
;;
;; Possible future work:
;; - Automatically handle reverse dependancies
;; - Automatically reimport all changed libraries, possibly by tracking file mod timestamps.
;;
;; These would use things like (library-list), (library-requirements), (file-change-time).
;;
;; Written by Akce 2020.
;; SPDX-License-Identifier: Unlicense
(library (dynamic)
(export
case-import
current-environment
reimport)
(import (chezscheme))
(define current-environment
(make-parameter
(interaction-environment)
(lambda (p)
(cond
[(environment? p)
p]
[else
(error 'current-environment "must be an environment object." p)]))))
(define has-import
(lambda (who library-tag)
(let-values ([(source-file object-file obj-exists?)
((library-search-handler) who library-tag (library-directories) (library-extensions))])
(or source-file obj-exists?))))
;; [syntax] case-import: conditionally import a library.
;; case-import has a similar syntax to case-lambda except its clauses attempt to import a library.
;;
;; Limitations:
;; - many
;; - import-spec can only contain the library path. Specifiers such as only, prefix etc are not supported.
;; - the existance of the library source or object file implies success. No checks are made to see whether the actual import succeeds.
;;
;; TODO: add support for an optional sentinal (ala syntax-case)?
(define-syntax case-import
(syntax-rules ()
[(_ (import-spec body ...) ...)
(meta-cond
[(has-import 'case-import 'import-spec)
(import import-spec)
body ...] ...)]))
;; [syntax] reimport import-spec
;; Turn on (import-notify) to see reimport messages.
;;
;; Notes:
;; - this must be written as a macro as we do not want to evaluate import-spec.
;; - (import) can only be used where (define) is legal, ie at the beginning of a block.
;; Using (eval) gets us around that requirement.
(define-syntax reimport
(syntax-rules ()
[(_ import-spec)
(let-values ([(source-file object-file libobj-exists?)
((library-search-handler) 'reimport 'import-spec (library-directories) (library-extensions))])
(cond
[source-file
(when (import-notify)
(format #t "reimport: reimporting ~a~n" source-file))
;; Update definitions.
(load source-file)
;; Update library bindings.
(eval '(import import-spec) (current-environment))]
[else
(error 'reimport "library source not found" 'import-spec (library-directories) (library-extensions))]))]))
)