-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathrun.ss
160 lines (138 loc) · 5.18 KB
/
run.ss
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#lang scheme
(provide (all-defined-out))
(require scheme/path)
(define runtime-get
(case-lambda
((runtime varname)
(namespace-variable-value varname #t #f runtime))
((runtime varname default)
(namespace-variable-value varname #t (lambda () default) runtime))))
(define (runtime-set runtime varname value)
(namespace-set-variable-value! varname value #t runtime))
(define (racket-eval runtime form)
(parameterize ((compile-allow-set!-undefined #t))
(eval form runtime)))
(define (ail-code-eval runtime form)
(cond ((and (pair? form) (eq? (car form) 'ail-code))
(for-each (lambda (expr)
(racket-eval runtime expr))
(cdr form)))
((and (pair? form) (eq? (car form) 'use))
(for-each (lambda (item)
((runtime-get runtime 'use-apply) item))
(cdr form)))
(else
(error "sorry, this primitive eval only knows how to do ail-code and use!" form))))
(define (loadin runtime in)
(let ((form (read in)))
(if (eof-object? form)
'nil
(begin (ail-code-eval runtime form)
((runtime-get runtime 'loadin) in)))))
(define (ail-load runtime filename)
(call-with-input-file filename
(lambda (in)
(loadin runtime in))))
(define (full-path basedir filename)
(path->string
(path->complete-path
filename
(if (or (not basedir) (eqv? basedir 'nil))
(current-directory)
basedir))))
(define (load runtime basedir filename)
((runtime-get runtime 'load)
(full-path (or basedir (current-directory)) filename)))
(define (asstring x)
(cond ((string? x) x)
((symbol? x) (symbol->string x))
(else (error "can't convert to string" x))))
(define (assymbol x)
(cond ((string? x) (string->symbol x))
((symbol? x) x)
(else (error "can't convert to symbol" x))))
(define (dirpart path)
(let-values (((dir file must) (split-path path)))
(path->string dir)))
(define (filepart path)
(let ((r (file-name-from-path path)))
(if r (path->string r) #f)))
(define (extension path)
(let ((r (regexp-match #px"\\.([^\\.]+)$" (filepart path))))
(if r (cadr r) #f)))
(define (default-arc path)
(if (extension path)
path
(string-append path ".arc")))
(define (find file dirs)
(cond ((absolute-path? file)
(cond ((file-exists? file)
file)
((and (not (extension file))
(file-exists? (string-append file ".arc")))
(string-append file ".arc"))
(else
(error "not found" file))))
((eq? dirs 'nil)
(error "not found" file))
(else
(let ((try (string-append (mcar dirs) "/" (default-arc file))))
(if (file-exists? (string->path try))
try
(find file (mcdr dirs)))))))
(define (adir item)
(let-values (((dir file must) (split-path item)))
must))
(define (add-usepath runtime dir)
((runtime-get runtime 'usepath*)
(mcons (path->string (normalize-path dir))
((runtime-get runtime 'usepath*)))))
(define (begins str pat)
(and (<= (string-length pat) (string-length str))
(equal? (substring str 0 (string-length pat)) pat)))
(define (use-apply runtime item)
(let ((loaded* (runtime-get runtime 'loaded*))
(usepath* (runtime-get runtime 'usepath*)))
(cond ((begins (asstring item) "git:")
(use-apply runtime 'use-git)
((runtime-get runtime 'use-apply) item))
((adir (asstring item))
(add-usepath runtime (asstring item)))
(else
(unless (hash-ref loaded* (assymbol item) #f)
(let ((path (find (asstring item) (usepath*))))
(load runtime #f path)
(hash-set! loaded* (assymbol item) 't)))))
't))
(define (new-runtime usepath)
(let ((runtime (make-base-empty-namespace)))
(parameterize ((current-namespace runtime))
(namespace-require '(only scheme/base #%app #%datum #%top))
(namespace-require '(prefix racket- scheme/base))
(namespace-require '(prefix racket- scheme/mpair)))
(runtime-set runtime 'runtime* runtime)
(runtime-set runtime 'usepath* (make-parameter usepath))
(runtime-set runtime 'loaded* (make-hash))
(runtime-set runtime 'ar-racket-eval racket-eval)
(runtime-set runtime 'ar-var
(case-lambda
((name)
(runtime-get runtime name))
((name default)
(runtime-get runtime name default))))
(runtime-set runtime 'ar-assign
(lambda (name value)
(runtime-set runtime name value)))
(runtime-set runtime 'load (lambda (filename) (ail-load runtime filename)))
(runtime-set runtime 'use-apply (lambda (item)
(use-apply runtime item)))
(runtime-set runtime 'loadin (lambda (in)
(loadin runtime in)))
(runtime-set runtime 'add-usepath
(lambda (path)
(add-usepath runtime path)))
(runtime-set runtime 'use-find
(lambda (item (usepath ((runtime-get runtime 'usepath*))))
(find item usepath)))
(runtime-set runtime 'new-runtime new-runtime)
runtime))