~ chicken-core (chicken-5) /eval.scm
Trap1;;;; eval.scm - Interpreter for CHICKEN
2;
3; Copyright (c) 2008-2022, The CHICKEN Team
4; Copyright (c) 2000-2007, Felix L. Winkelmann
5; All rights reserved.
6;
7; Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
8; conditions are met:
9;
10; Redistributions of source code must retain the above copyright notice, this list of conditions and the following
11; disclaimer.
12; Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
13; disclaimer in the documentation and/or other materials provided with the distribution.
14; Neither the name of the author nor the names of its contributors may be used to endorse or promote
15; products derived from this software without specific prior written permission.
16;
17; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
18; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
19; AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
20; CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22; SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25; POSSIBILITY OF SUCH DAMAGE.
26
27
28(declare
29 (unit eval)
30 (uses modules)
31 (not inline ##sys#alias-global-hook ##sys#user-read-hook ##sys#syntax-error-hook))
32
33#>
34#ifndef C_INSTALL_EGG_HOME
35# define C_INSTALL_EGG_HOME "."
36#endif
37
38#ifndef C_INSTALL_SHARE_HOME
39# define C_INSTALL_SHARE_HOME NULL
40#endif
41
42#ifndef C_BINARY_VERSION
43# define C_BINARY_VERSION 0
44#endif
45<#
46
47(module chicken.eval
48 (eval-handler module-environment)
49
50(import scheme
51 chicken.base
52 chicken.blob
53 chicken.fixnum
54 chicken.internal
55 chicken.keyword
56 chicken.syntax
57 chicken.type)
58
59(include "common-declarations.scm")
60
61(define-syntax d (syntax-rules () ((_ . _) (void))))
62
63;;; Compile lambda to closure:
64
65(define (eval-decorator p ll h cntr)
66 (##sys#decorate-lambda
67 p
68 (lambda (x) (and (not (##sys#immediate? x)) (##core#inline "C_lambdainfop" x)))
69 (lambda (p i)
70 (##sys#setslot
71 p i
72 (##sys#make-lambda-info
73 (let ((o (open-output-string)))
74 (write ll o)
75 (get-output-string o))))
76 p) ) )
77
78(define ##sys#unbound-in-eval #f)
79(define ##sys#eval-debug-level (make-parameter 1))
80
81(define compile-to-closure
82 (let ((reverse reverse))
83 (lambda (exp env #!optional cntr evalenv static tl?)
84 (define-syntax thread-id
85 (syntax-rules ()
86 ((_ t) (##sys#slot t 14))))
87
88 (define (find-id id se) ; ignores macro bindings
89 (cond ((null? se) #f)
90 ((and (eq? id (caar se)) (symbol? (cdar se))) (cdar se))
91 (else (find-id id (cdr se)))))
92
93 (define (rename var)
94 (cond ((find-id var (##sys#current-environment)))
95 ((##sys#get var '##core#macro-alias) symbol? => values)
96 (else var)))
97
98 (define (lookup var0 e)
99 (let ((var (rename var0)))
100 (d `(LOOKUP/EVAL: ,var0 ,var ,e ,(map (lambda (x) (car x)) (##sys#current-environment))))
101 (let loop ((envs e) (ei 0))
102 (cond ((null? envs) (values #f var))
103 ((posq var (##sys#slot envs 0)) => (lambda (p) (values ei p)))
104 (else (loop (##sys#slot envs 1) (fx+ ei 1))) ) ) ))
105
106 (define (posq x lst)
107 (let loop ((lst lst) (i 0))
108 (cond ((null? lst) #f)
109 ((eq? x (##sys#slot lst 0)) i)
110 (else (loop (##sys#slot lst 1) (fx+ i 1))) ) ) )
111
112 (define (emit-trace-info tf ln info cntr e v)
113 (when tf
114 (##core#inline
115 "C_emit_trace_info"
116 ln
117 info
118 (##sys#make-structure 'frameinfo cntr e v)
119 (thread-id ##sys#current-thread) ) ) )
120
121 (define (emit-syntax-trace-info tf info cntr)
122 (when tf
123 (##core#inline
124 "C_emit_trace_info"
125 (or (get-line-number info) "<syntax>")
126 info
127 cntr
128 (thread-id ##sys#current-thread) ) ) )
129
130 (define (decorate p ll h cntr)
131 (eval-decorator p ll h cntr))
132
133 (define (handle-expansion-result outer-ln)
134 (lambda (input output)
135 (and-let* (((not (eq? input output)))
136 (ln (or (get-line-number input) outer-ln)))
137 (##sys#update-line-number-database! output ln))
138 output))
139
140 (define (compile x e h tf cntr tl?)
141 (cond ((keyword? x) (lambda v x))
142 ((symbol? x)
143 (receive (i j) (lookup x e)
144 (cond ((not i)
145 (let ((var (cond ((not (symbol? j)) x) ; syntax?
146 ((assq x (##sys#current-environment)) j)
147 ((not static)
148 (##sys#alias-global-hook j #f cntr))
149 ((not (eq? x j)) j) ; has macro-alias
150 (else #f))))
151 (when (and ##sys#unbound-in-eval
152 (or (not var)
153 (not (##sys#symbol-has-toplevel-binding? var))))
154 (set! ##sys#unbound-in-eval
155 (cons (cons var cntr) ##sys#unbound-in-eval)) )
156 (cond ((not var)
157 (lambda (v)
158 (##sys#error "unbound variable" x)))
159 ((##sys#symbol-has-toplevel-binding? var)
160 (lambda v (##sys#slot var 0)))
161 (else
162 (lambda v (##core#inline "C_fast_retrieve" var))))))
163 (else
164 (case i
165 ((0) (lambda (v)
166 (##sys#slot (##sys#slot v 0) j)))
167 ((1) (lambda (v)
168 (##sys#slot (##sys#slot (##sys#slot v 1) 0) j)))
169 ((2) (lambda (v)
170 (##sys#slot
171 (##sys#slot (##sys#slot (##sys#slot v 1) 1) 0)
172 j)))
173 ((3) (lambda (v)
174 (##sys#slot
175 (##sys#slot
176 (##sys#slot (##sys#slot (##sys#slot v 1) 1) 1)
177 0)
178 j)))
179 (else
180 (lambda (v)
181 (##sys#slot (##core#inline "C_u_i_list_ref" v i) j))))))))
182 [(##sys#number? x)
183 (case x
184 [(-1) (lambda v -1)]
185 [(0) (lambda v 0)]
186 [(1) (lambda v 1)]
187 [(2) (lambda v 2)]
188 [else (lambda v x)] ) ]
189 [(boolean? x)
190 (if x
191 (lambda v #t)
192 (lambda v #f) ) ]
193 ((or (char? x)
194 (eof-object? x)
195 (##core#inline "C_bwpp" x) ; TODO: Remove once we have a bootstrapping libchicken with bwp-object?
196 ;;(bwp-object? x)
197 (string? x)
198 (blob? x)
199 (vector? x)
200 (##sys#srfi-4-vector? x))
201 (lambda v x) )
202 [(not (pair? x))
203 (##sys#syntax-error/context "illegal non-atomic object" x)]
204 [(symbol? (##sys#slot x 0))
205 (emit-syntax-trace-info tf x cntr)
206 (let* ((ln (get-line-number x))
207 (x2 (fluid-let ((chicken.syntax#expansion-result-hook
208 (handle-expansion-result ln)))
209 (expand x (##sys#current-environment)))))
210 (d `(EVAL/EXPANDED: ,x2))
211 (if (not (eq? x2 x))
212 (compile x2 e h tf cntr tl?)
213 (let ((head (rename (##sys#slot x 0))))
214 ;; here we did't resolve ##core#primitive, but that is done in compile-call (via
215 ;; a normal walking of the operator)
216 (case head
217
218 [(##core#quote)
219 (let* ((c (strip-syntax (cadr x))))
220 (case c
221 [(-1) (lambda v -1)]
222 [(0) (lambda v 0)]
223 [(1) (lambda v 1)]
224 [(2) (lambda v 2)]
225 [(#t) (lambda v #t)]
226 [(#f) (lambda v #f)]
227 [(()) (lambda v '())]
228 [else (lambda v c)] ) ) ]
229
230 ((##core#syntax)
231 (let ((c (cadr x)))
232 (lambda v c)))
233
234 [(##core#check)
235 (compile (cadr x) e h tf cntr #f) ]
236
237 [(##core#immutable)
238 (compile (cadr x) e #f tf cntr #f) ]
239
240 [(##core#undefined) (lambda (v) (##core#undefined))]
241
242 [(##core#if)
243 (let* ((test (compile (cadr x) e #f tf cntr #f))
244 (cns (compile (caddr x) e #f tf cntr #f))
245 (alt (if (pair? (cdddr x))
246 (compile (cadddr x) e #f tf cntr #f)
247 (compile '(##core#undefined) e #f tf cntr #f) ) ) )
248 (lambda (v) (if (##core#app test v) (##core#app cns v) (##core#app alt v))) ) ]
249
250 [(##core#begin)
251 (let* ((body (##sys#slot x 1))
252 (len (length body)) )
253 (case len
254 ((0) (compile '(##core#undefined) e #f tf cntr tl?))
255 ((1) (compile (##sys#slot body 0) e #f tf cntr tl?))
256 ((2) (let* ((x1 (compile (##sys#slot body 0) e #f tf cntr tl?))
257 (x2 (compile (cadr body) e #f tf cntr tl?)) )
258 (lambda (v) (##core#app x1 v) (##core#app x2 v)) ) )
259 (else
260 (let* ((x1 (compile (##sys#slot body 0) e #f tf cntr tl?))
261 (x2 (compile (cadr body) e #f tf cntr tl?))
262 (x3 (compile `(##core#begin ,@(##sys#slot (##sys#slot body 1) 1)) e #f tf cntr tl?)) )
263 (lambda (v) (##core#app x1 v) (##core#app x2 v) (##core#app x3 v)) ) ) ) ) ]
264
265 ((##core#ensure-toplevel-definition)
266 (unless tl?
267 (##sys#error "toplevel definition in non-toplevel context for variable" (cadr x)))
268 (##sys#put/restore! (cadr x) '##sys#override 'value)
269 (compile
270 '(##core#undefined) e #f tf cntr #f))
271
272 [(##core#set!)
273 (let ((var (cadr x)))
274 (receive (i j) (lookup var e)
275 (let ((val (compile (caddr x) e var tf cntr #f)))
276 (cond ((not i)
277 (when ##sys#notices-enabled
278 (and-let* ((a (assq var (##sys#current-environment)))
279 ((symbol? (cdr a))))
280 (##sys#notice "assignment to imported value binding" var)))
281 (if static
282 (lambda (v)
283 (##sys#error 'eval "environment is not mutable" evalenv var)) ;XXX var?
284 (let ((var (##sys#alias-global-hook j #t cntr)))
285 (lambda (v)
286 (let ((result (##core#app val v)))
287 (##core#inline "C_i_persist_symbol" var)
288 (##sys#setslot var 0 result))))))
289 ((zero? i) (lambda (v) (##sys#setslot (##sys#slot v 0) j (##core#app val v))))
290 (else
291 (lambda (v)
292 (##sys#setslot
293 (##core#inline "C_u_i_list_ref" v i) j (##core#app val v))))))))]
294
295 [(##core#let)
296 (let* ((bindings (cadr x))
297 (n (length bindings))
298 (vars (map (lambda (x) (car x)) bindings))
299 (aliases (map gensym vars))
300 (e2 (cons aliases e))
301 (se2 (##sys#extend-se (##sys#current-environment) vars aliases))
302 (body (parameterize ((##sys#current-environment se2))
303 (compile-to-closure
304 (##sys#canonicalize-body (cddr x) (##sys#current-environment) #f)
305 e2 cntr evalenv static #f)) ) )
306 (case n
307 ((1) (let ([val (compile (cadar bindings) e (car vars) tf cntr #f)])
308 (lambda (v)
309 (##core#app body (cons (vector (##core#app val v)) v)) ) ) )
310 ((2) (let ((val1 (compile (cadar bindings) e (car vars) tf cntr #f))
311 (val2 (compile (cadadr bindings) e (cadr vars) tf cntr #f)) )
312 (lambda (v)
313 (##core#app body (cons (vector (##core#app val1 v) (##core#app val2 v)) v)) ) ) )
314 ((3) (let* ((val1 (compile (cadar bindings) e (car vars) tf cntr #f))
315 (val2 (compile (cadadr bindings) e (cadr vars) tf cntr #f))
316 (t (cddr bindings))
317 (val3 (compile (cadar t) e (caddr vars) tf cntr #f)) )
318 (lambda (v)
319 (##core#app
320 body
321 (cons (vector (##core#app val1 v) (##core#app val2 v) (##core#app val3 v)) v)) ) ) )
322 ((4) (let* ((val1 (compile (cadar bindings) e (car vars) tf cntr #f))
323 (val2 (compile (cadadr bindings) e (cadr vars) tf cntr #f))
324 (t (cddr bindings))
325 (val3 (compile (cadar t) e (caddr vars) tf cntr #f))
326 (val4 (compile (cadadr t) e (cadddr vars) tf cntr #f)) )
327 (lambda (v)
328 (##core#app
329 body
330 (cons (vector (##core#app val1 v)
331 (##core#app val2 v)
332 (##core#app val3 v)
333 (##core#app val4 v))
334 v)) ) ) )
335 [else
336 (let ((vals (map (lambda (x) (compile (cadr x) e (car x) tf cntr #f)) bindings)))
337 (lambda (v)
338 (let ([v2 (##sys#make-vector n)])
339 (do ([i 0 (fx+ i 1)]
340 [vlist vals (##sys#slot vlist 1)] )
341 ((fx>= i n))
342 (##sys#setslot v2 i (##core#app (##sys#slot vlist 0) v)) )
343 (##core#app body (cons v2 v)) ) ) ) ] ) ) ]
344
345 ((##core#letrec*)
346 (let ((bindings (cadr x))
347 (body (cddr x)) )
348 (compile
349 `(##core#let
350 ,(##sys#map (lambda (b)
351 (list (car b) '(##core#undefined)))
352 bindings)
353 ,@(##sys#map (lambda (b)
354 `(##core#set! ,(car b) ,(cadr b)))
355 bindings)
356 (##core#let () ,@body) )
357 e h tf cntr #f)))
358
359 ((##core#letrec)
360 (let* ((bindings (cadr x))
361 (vars (map car bindings))
362 (tmps (map gensym vars))
363 (body (cddr x)) )
364 (compile
365 `(##core#let
366 ,(map (lambda (b)
367 (list (car b) '(##core#undefined)))
368 bindings)
369 (##core#let ,(map (lambda (t b) (list t (cadr b))) tmps bindings)
370 ,@(map (lambda (v t)
371 `(##core#set! ,v ,t))
372 vars tmps)
373 (##core#let () ,@body) ) )
374 e h tf cntr #f)))
375
376 [(##core#lambda)
377 (##sys#check-syntax 'lambda x '(_ lambda-list . #(_ 1)) #f (##sys#current-environment))
378 (let* ([llist (cadr x)]
379 [body (cddr x)]
380 [info (cons (or h '?) llist)] )
381 (when (##sys#extended-lambda-list? llist)
382 (set!-values
383 (llist body)
384 (##sys#expand-extended-lambda-list
385 llist body ##sys#syntax-error-hook (##sys#current-environment)) ) )
386 (##sys#decompose-lambda-list
387 llist
388 (lambda (vars argc rest)
389 (let* ((aliases (map gensym vars))
390 (se2 (##sys#extend-se (##sys#current-environment) vars aliases))
391 (e2 (cons aliases e))
392 (body
393 (parameterize ((##sys#current-environment se2))
394 (compile-to-closure
395 (##sys#canonicalize-body body se2 #f)
396 e2 (or h cntr) evalenv static #f)) ) )
397 (case argc
398 [(0) (if rest
399 (lambda (v)
400 (decorate
401 (lambda r
402 (##core#app body (cons (vector r) v)))
403 info h cntr) )
404 (lambda (v)
405 (decorate
406 (lambda () (##core#app body (cons #f v)))
407 info h cntr) ) ) ]
408 [(1) (if rest
409 (lambda (v)
410 (decorate
411 (lambda (a1 . r)
412 (##core#app body (cons (vector a1 r) v)))
413 info h cntr) )
414 (lambda (v)
415 (decorate
416 (lambda (a1)
417 (##core#app body (cons (vector a1) v)))
418 info h cntr) ) ) ]
419 [(2) (if rest
420 (lambda (v)
421 (decorate
422 (lambda (a1 a2 . r)
423 (##core#app body (cons (vector a1 a2 r) v)))
424 info h cntr) )
425 (lambda (v)
426 (decorate
427 (lambda (a1 a2)
428 (##core#app body (cons (vector a1 a2) v)))
429 info h cntr) ) ) ]
430 [(3) (if rest
431 (lambda (v)
432 (decorate
433 (lambda (a1 a2 a3 . r)
434 (##core#app body (cons (vector a1 a2 a3 r) v)))
435 info h cntr) )
436 (lambda (v)
437 (decorate
438 (lambda (a1 a2 a3)
439 (##core#app body (cons (vector a1 a2 a3) v)))
440 info h cntr) ) ) ]
441 [(4) (if rest
442 (lambda (v)
443 (decorate
444 (lambda (a1 a2 a3 a4 . r)
445 (##core#app body (cons (vector a1 a2 a3 a4 r) v)))
446 info h cntr) )
447 (lambda (v)
448 (decorate
449 (lambda (a1 a2 a3 a4)
450 (##core#app body (##sys#cons (##sys#vector a1 a2 a3 a4) v)))
451 info h cntr) ) ) ]
452 [else
453 (if rest
454 (lambda (v)
455 (decorate
456 (lambda as
457 (##core#app
458 body
459 (##sys#cons (apply ##sys#vector (fudge-argument-list argc as)) v)) )
460 info h cntr) )
461 (lambda (v)
462 (decorate
463 (lambda as
464 (let ([len (length as)])
465 (if (not (fx= len argc))
466 (##sys#error "bad argument count" argc len)
467 (##core#app body (##sys#cons (apply ##sys#vector as) v)))))
468 info h cntr) ) ) ] ) ) ) ) ) ]
469
470 ((##core#let-syntax)
471 (parameterize
472 ((##sys#current-environment
473 (append
474 (map (lambda (b)
475 (list
476 (car b)
477 (##sys#current-environment)
478 (##sys#ensure-transformer
479 (##sys#eval/meta (cadr b))
480 (strip-syntax (car b)))))
481 (cadr x) )
482 (##sys#current-environment)) ) )
483 (compile
484 (##sys#canonicalize-body (cddr x) (##sys#current-environment) #f)
485 e #f tf cntr #f)))
486
487 ((##core#letrec-syntax)
488 (let* ((ms (map (lambda (b)
489 (list
490 (car b)
491 #f
492 (##sys#ensure-transformer
493 (##sys#eval/meta (cadr b))
494 (strip-syntax (car b)))))
495 (cadr x) ) )
496 (se2 (append ms (##sys#current-environment))) )
497 (for-each
498 (lambda (sb)
499 (set-car! (cdr sb) se2) )
500 ms)
501 (parameterize ((##sys#current-environment se2))
502 (compile
503 (##sys#canonicalize-body (cddr x) (##sys#current-environment) #f)
504 e #f tf cntr #f))))
505
506 ((##core#define-syntax)
507 (let* ((var (cadr x))
508 (body (caddr x))
509 (name (rename var)))
510 (when (and static (not (assq var (##sys#current-environment))))
511 (##sys#error 'eval "environment is not mutable" evalenv var))
512 (##sys#put/restore! name '##sys#override 'syntax)
513 (##sys#register-syntax-export
514 name (##sys#current-module)
515 body) ; not really necessary, it only shouldn't be #f
516 (##sys#extend-macro-environment
517 name
518 (##sys#current-environment)
519 (##sys#eval/meta body))
520 (compile '(##core#undefined) e #f tf cntr #f) ) )
521
522 ((##core#define-compiler-syntax)
523 (compile '(##core#undefined) e #f tf cntr #f))
524
525 ((##core#let-compiler-syntax)
526 (compile
527 (##sys#canonicalize-body (cddr x) (##sys#current-environment) #f)
528 e #f tf cntr #f))
529
530 ((##core#include)
531 (##sys#include-forms-from-file
532 (cadr x)
533 (caddr x)
534 (lambda (forms path)
535 (let ((code (if (pair? (cdddr x)) ; body?
536 (##sys#canonicalize-body
537 (append forms (cadddr x))
538 (##sys#current-environment))
539 `(##core#begin ,@forms))))
540 (fluid-let ((##sys#current-source-filename path))
541 (compile code e #f tf cntr tl?))))))
542
543 ((##core#let-module-alias)
544 (##sys#with-module-aliases
545 (map (lambda (b)
546 (##sys#check-syntax 'functor b '(symbol symbol))
547 (strip-syntax b))
548 (cadr x))
549 (lambda ()
550 (compile `(##core#begin ,@(cddr x)) e #f tf cntr tl?))))
551
552 ((##core#module)
553 (let* ((x (strip-syntax x))
554 (name (cadr x))
555 (exports
556 (or (eq? #t (caddr x))
557 (map (lambda (exp)
558 (cond ((symbol? exp) exp)
559 ((and (pair? exp)
560 (let loop ((exp exp))
561 (or (null? exp)
562 (and (symbol? (car exp))
563 (loop (cdr exp))))))
564 exp)
565 (else
566 (##sys#syntax-error-hook
567 'module
568 "invalid export syntax" exp name))))
569 (caddr x)))))
570 (when (##sys#current-module)
571 (##sys#syntax-error-hook 'module "modules may not be nested" name))
572 (parameterize ((##sys#current-module
573 (##sys#register-module name #f exports))
574 (##sys#current-environment '())
575 (##sys#macro-environment
576 ##sys#initial-macro-environment)
577 (##sys#module-alias-environment
578 (##sys#module-alias-environment)))
579 (##sys#with-property-restore
580 (lambda ()
581 (let loop ((body (cdddr x)) (xs '()))
582 (if (null? body)
583 (let ((xs (reverse xs)))
584 (##sys#finalize-module (##sys#current-module))
585 (##sys#provide (module-requirement name))
586 (lambda (v)
587 (let loop2 ((xs xs))
588 (if (null? xs)
589 (##sys#void)
590 (let ((n (cdr xs)))
591 (cond ((pair? n)
592 ((car xs) v)
593 (loop2 n))
594 (else
595 ((car xs) v))))))))
596 (loop
597 (cdr body)
598 (cons (compile
599 (car body)
600 '() #f tf cntr
601 #t) ; reset back to toplevel!
602 xs))))) ) )))
603
604 [(##core#loop-lambda)
605 (compile `(,(rename 'lambda) ,@(cdr x)) e #f tf cntr #f) ]
606
607 [(##core#provide)
608 (compile `(##sys#provide (##core#quote ,(cadr x))) e #f tf cntr #f)]
609
610 [(##core#require-for-syntax)
611 (chicken.load#load-extension (cadr x) #f #f)
612 (compile '(##core#undefined) e #f tf cntr #f)]
613
614 [(##core#require)
615 (let ((lib (cadr x))
616 (mod (and (pair? (cddr x)) (caddr x))))
617 (compile (##sys#process-require lib mod #f) e #f tf cntr #f))]
618
619 [(##core#elaborationtimeonly ##core#elaborationtimetoo) ; <- Note this!
620 (##sys#eval/meta (cadr x))
621 (compile '(##core#undefined) e #f tf cntr tl?) ]
622
623 [(##core#compiletimetoo)
624 (compile (cadr x) e #f tf cntr tl?) ]
625
626 [(##core#compiletimeonly ##core#callunit ##core#local-specialization)
627 (compile '(##core#undefined) e #f tf cntr tl?) ]
628
629 [(##core#declare)
630 (##sys#notice "declarations are ignored in interpreted code" x)
631 (compile '(##core#undefined) e #f tf cntr #f) ]
632
633 [(##core#define-inline ##core#define-constant)
634 (compile `(,(rename 'define) ,@(cdr x)) e #f tf cntr tl?) ]
635
636 [(##core#primitive ##core#inline ##core#inline_allocate ##core#foreign-lambda
637 ##core#define-foreign-variable
638 ##core#define-external-variable ##core#let-location
639 ##core#foreign-primitive ##core#location
640 ##core#foreign-lambda* ##core#define-foreign-type)
641 (##sys#syntax-error-hook "cannot evaluate compiler-special-form" x) ]
642
643 [(##core#app)
644 (compile-call (cdr x) e tf cntr (##sys#current-environment)) ]
645
646 ((##core#the)
647 (compile (cadddr x) e h tf cntr tl?))
648
649 ((##core#typecase)
650 ;; drops exp and requires "else" clause
651 (cond ((assq 'else (strip-syntax (cdddr x))) =>
652 (lambda (cl)
653 (compile (cadr cl) e h tf cntr tl?)))
654 (else
655 (##sys#syntax-error-hook
656 'compiler-typecase
657 "no `else-clause' in unresolved `compiler-typecase' form"
658 x))))
659
660 (else
661 (fluid-let ((##sys#syntax-context (cons head ##sys#syntax-context)))
662 (compile-call x e tf cntr (##sys#current-environment))))))))]
663
664 [else
665 (emit-syntax-trace-info tf x cntr)
666 (compile-call x e tf cntr (##sys#current-environment))] ) )
667
668 (define (fudge-argument-list n alst)
669 (if (null? alst)
670 (list alst)
671 (do ((n n (fx- n 1))
672 (c 0 (fx+ c 1))
673 (args alst
674 (if (eq? '() args)
675 (##sys#error "bad argument count" n c)
676 (##sys#slot args 1)))
677 (last #f args) )
678 ((fx= n 0)
679 (##sys#setslot last 1 (list args))
680 alst) ) ) )
681
682 (define (checked-length lst)
683 (let loop ([lst lst] [n 0])
684 (cond [(null? lst) n]
685 [(pair? lst) (loop (##sys#slot lst 1) (fx+ n 1))]
686 [else #f] ) ) )
687
688 (define (compile-call x e tf cntr se)
689 (let* ((head (##sys#slot x 0))
690 (fn (if (procedure? head)
691 (lambda _ head)
692 (compile (##sys#slot x 0) e #f tf cntr #f)))
693 (args (##sys#slot x 1))
694 (argc (checked-length args))
695 (info x)
696 (ln (or (get-line-number info) "<eval>")))
697 (case argc
698 ((#f) (##sys#syntax-error/context "malformed expression" x))
699 ((0) (lambda (v)
700 (emit-trace-info tf ln info cntr e v)
701 ((##core#app fn v))))
702 ((1) (let ((a1 (compile (##sys#slot args 0) e #f tf cntr #f)))
703 (lambda (v)
704 (emit-trace-info tf ln info cntr e v)
705 ((##core#app fn v) (##core#app a1 v))) ) )
706 ((2) (let* ((a1 (compile (##sys#slot args 0) e #f tf cntr #f))
707 (a2 (compile (##core#inline "C_u_i_list_ref" args 1) e #f tf cntr #f)) )
708 (lambda (v)
709 (emit-trace-info tf ln info cntr e v)
710 ((##core#app fn v) (##core#app a1 v) (##core#app a2 v))) ) )
711 ((3) (let* ((a1 (compile (##sys#slot args 0) e #f tf cntr #f))
712 (a2 (compile (##core#inline "C_u_i_list_ref" args 1) e #f tf cntr #f))
713 (a3 (compile (##core#inline "C_u_i_list_ref" args 2) e #f tf cntr #f)) )
714 (lambda (v)
715 (emit-trace-info tf ln info cntr e v)
716 ((##core#app fn v) (##core#app a1 v) (##core#app a2 v) (##core#app a3 v))) ) )
717 ((4) (let* ((a1 (compile (##sys#slot args 0) e #f tf cntr #f))
718 (a2 (compile (##core#inline "C_u_i_list_ref" args 1) e #f tf cntr #f))
719 (a3 (compile (##core#inline "C_u_i_list_ref" args 2) e #f tf cntr #f))
720 (a4 (compile (##core#inline "C_u_i_list_ref" args 3) e #f tf cntr #f)) )
721 (lambda (v)
722 (emit-trace-info tf ln info cntr e v)
723 ((##core#app fn v) (##core#app a1 v) (##core#app a2 v) (##core#app a3 v) (##core#app a4 v))) ) )
724 (else (let ((as (##sys#map (lambda (a) (compile a e #f tf cntr #f)) args)))
725 (lambda (v)
726 (emit-trace-info tf ln info cntr e v)
727 (apply (##core#app fn v) (##sys#map (lambda (a) (##core#app a v)) as))) ) ) ) ) )
728
729 (compile exp env #f (fx> (##sys#eval-debug-level) 0) cntr tl?) ) ) )
730
731
732;;; evaluate in the macro-expansion/compile-time environment
733(define (##sys#eval/meta form)
734 (parameterize ((##sys#current-module #f)
735 (##sys#macro-environment (##sys#meta-macro-environment))
736 (##sys#current-environment (##sys#current-meta-environment)))
737 (dynamic-wind
738 void
739 (lambda ()
740 ((compile-to-closure
741 form
742 '()
743 #f #f #f ;XXX evalenv? static?
744 #t) ; toplevel.
745 '()) )
746 (lambda ()
747 ;; Just before restoring the parameters, update "meta"
748 ;; environments to receive a copy of the current
749 ;; environments one level "down". We don't support more
750 ;; than two evaluation phase levels currently. XXX: Should
751 ;; we change this to a "stack" of environments?
752 (##sys#current-meta-environment (##sys#current-environment))
753 (##sys#meta-macro-environment (##sys#macro-environment))))))
754
755(define eval-handler
756 (make-parameter
757 (lambda (x #!optional env)
758 (let ((se (##sys#current-environment)))
759 ;; When se is empty, it's the first time eval was called:
760 ;; ensure an active default environment. We do it here because
761 ;; eval does not work yet at the end of modules.scm, and we
762 ;; don't want to inject calls into every toplevel (see #1437)
763 (when (null? se)
764 ((compile-to-closure
765 `(##core#begin (import-for-syntax ,@default-syntax-imports)
766 (import ,@default-imports))
767 '() #f #f #f #t) '()))
768 (cond (env
769 (##sys#check-structure env 'environment 'eval)
770 (let ((se2 (##sys#slot env 2)))
771 ((if se2 ; not interaction-environment?
772 (parameterize ((##sys#macro-environment '())
773 (##sys#current-environment se2))
774 (compile-to-closure x '() #f env (##sys#slot env 3) #t))
775 (compile-to-closure x '() #f env #f #t))
776 '() ) ) )
777 (else
778 ((compile-to-closure x '() #f #f #f #t) '())))))))
779
780(set! scheme#eval
781 (lambda (x . env)
782 (apply (eval-handler) x env)))
783
784;;; User-facing `module-environment` procedure:
785
786(define (module-environment name)
787 (chicken.module#module-environment name))
788
789
790;;; Setting properties dynamically scoped
791
792(define-values (##sys#put/restore! ##sys#with-property-restore)
793 (let ((trail '())
794 (restoring #f))
795 (values
796 (lambda (sym prop val)
797 (when restoring
798 (set! trail (cons (list sym prop (##sys#get sym prop)) trail)))
799 (##sys#put! sym prop val)
800 val)
801 (lambda (thunk)
802 (let ((t0 #f)
803 (r0 restoring))
804 (dynamic-wind
805 (lambda ()
806 (set! t0 trail)
807 (set! restoring #t))
808 thunk
809 (lambda ()
810 (do () ((eq? t0 trail))
811 (apply ##sys#put! (car trail))
812 (set! trail (cdr trail)))
813 (set! restoring r0))))))))
814
815
816;;; Split lambda-list into its parts:
817
818(define ##sys#decompose-lambda-list
819 (let ([reverse reverse])
820 (lambda (llist0 k)
821
822 (define (err)
823 (set! ##sys#syntax-error-culprit #f)
824 (##sys#syntax-error-hook "illegal lambda-list syntax" llist0) )
825
826 (let loop ([llist llist0] [vars '()] [argc 0])
827 (cond [(eq? llist '()) (k (reverse vars) argc #f)]
828 [(not (##core#inline "C_blockp" llist)) (err)]
829 [(##core#inline "C_symbolp" llist) (k (reverse (cons llist vars)) argc llist)]
830 [(not (##core#inline "C_pairp" llist)) (err)]
831 [else (loop (##sys#slot llist 1)
832 (cons (##sys#slot llist 0) vars)
833 (fx+ argc 1) ) ] ) ) ) ) )
834
835(set! scheme#interaction-environment
836 (let ((e (##sys#make-structure 'environment 'interaction-environment #f #f)))
837 (lambda () e)))
838
839(set-record-printer! 'environment
840 (lambda (e p)
841 (##sys#print "#<environment " #f p)
842 (##sys#print (##sys#slot e 1) #f p)
843 (##sys#write-char-0 #\> p)))
844
845(let* ((r4s (chicken.module#module-environment 'r4rs 'scheme-report-environment/4))
846 (r5s (chicken.module#module-environment 'scheme 'scheme-report-environment/5))
847 (r4n (chicken.module#module-environment 'r4rs-null 'null-environment/4))
848 (r5n (chicken.module#module-environment 'r5rs-null 'null-environment/5)))
849 (define (strip se)
850 (foldr
851 (lambda (s r)
852 (if (memq (car s)
853 '(cond-expand
854 define-interface
855 delay-force
856 export
857 export/rename
858 functor
859 import
860 import-for-syntax
861 import-syntax
862 import-syntax-for-syntax
863 letrec*
864 module
865 reexport
866 require-library
867 syntax))
868 r
869 (cons s r)))
870 '()
871 se))
872 ;; Strip non-std syntax from SEs
873 (##sys#setslot r4s 2 (strip (##sys#slot r4s 2)))
874 (##sys#setslot r4n 2 (strip (##sys#slot r4n 2)))
875 (##sys#setslot r5s 2 (strip (##sys#slot r5s 2)))
876 (##sys#setslot r5n 2 (strip (##sys#slot r5n 2)))
877 (set! scheme#scheme-report-environment
878 (lambda (n)
879 (##sys#check-fixnum n 'scheme-report-environment)
880 (case n
881 ((4) r4s)
882 ((5) r5s)
883 (else
884 (##sys#error
885 'scheme-report-environment
886 "unsupported scheme report environment version" n)))))
887 (set! scheme#null-environment
888 (lambda (n)
889 (##sys#check-fixnum n 'null-environment)
890 (case n
891 ((4) r4n)
892 ((5) r5n)
893 (else
894 (##sys#error
895 'null-environment
896 "unsupported null environment version" n))))))
897
898) ; eval module
899
900
901(module chicken.load
902 (dynamic-load-libraries set-dynamic-load-mode!
903 load-library load-noisily load-relative load-verbose
904 provide provided? require)
905
906(import scheme
907 chicken.base
908 chicken.eval
909 chicken.fixnum
910 chicken.foreign
911 chicken.internal
912 chicken.platform
913 chicken.syntax
914 chicken.time)
915
916(include "mini-srfi-1.scm")
917
918;;; Installation locations
919
920(define-foreign-variable binary-version int "C_BINARY_VERSION")
921(define-foreign-variable install-lib-name c-string "C_INSTALL_LIB_NAME")
922(define-foreign-variable uses-soname? bool "C_USES_SONAME")
923
924;;; Core unit information
925
926;; this maps built-in library names to require forms when the mapping isn't 1:1
927(define-constant core-unit-requirements
928 '((chicken.foreign
929 . (##core#require-for-syntax chicken-ffi-syntax))
930 (chicken.condition
931 . (##core#begin
932 (##core#require-for-syntax chicken-syntax)
933 (##core#require library)))))
934
935;; this list contains built-in units that are provided by libchicken
936;; and should not be treated as separate extension libraries during
937;; linking (they are omitted from types/inline/link files etc.)
938(define-constant core-units
939 '(chicken-syntax chicken-ffi-syntax continuation data-structures
940 debugger-client eval eval-modules expand extras file internal
941 irregex library lolevel pathname port posix profiler read-syntax
942 repl scheduler srfi-4 tcp))
943
944(define-constant cygwin-default-dynamic-load-libraries '("cygchicken-0"))
945(define-constant macosx-load-library-extension ".dylib")
946(define-constant windows-load-library-extension ".dll")
947(define-constant hppa-load-library-extension ".sl")
948(define-constant default-load-library-extension ".so")
949(define-constant source-file-extension ".scm")
950
951(define load-library-extension
952 (cond ((eq? (software-type) 'windows) windows-load-library-extension)
953 ((eq? (software-version) 'macosx) macosx-load-library-extension)
954 ((and (eq? (software-version) 'hpux)
955 (eq? (machine-type) 'hppa)) hppa-load-library-extension)
956 (else default-load-library-extension)))
957
958(define ##sys#load-dynamic-extension default-load-library-extension)
959
960(define (chicken.load#core-library? id) ; used by core.scm
961 (or (memq id core-units)
962 (assq id core-unit-requirements)))
963
964(define default-dynamic-load-libraries
965 (case (software-version)
966 ((cygwin) cygwin-default-dynamic-load-libraries)
967 (else `(,(string-append "lib" install-lib-name)))))
968
969
970;;; Library registration (used for code loading):
971
972(define (##sys#provide id)
973 (##core#inline_allocate ("C_a_i_provide" 8) id))
974
975(define (##sys#provided? id)
976 (##core#inline "C_i_providedp" id))
977
978
979;;; Pathname helpers:
980
981(define path-separators
982 (if ##sys#windows-platform '(#\\ #\/) '(#\/)))
983
984(define (path-separator-index/right s)
985 (let loop ((i (fx- (##sys#size s) 1)))
986 (if (memq (##core#inline "C_subchar" s i) path-separators)
987 i
988 (and (fx< 0 i) (loop (fx- i 1))))))
989
990(define (make-relative-pathname from file)
991 (let ((i (and (string? from)
992 (positive? (##sys#size file)) ; XXX probably an error?
993 (not (memq (##core#inline "C_subchar" file 0) path-separators))
994 (path-separator-index/right from))))
995 (if (not i) file (string-append (##sys#substring from 0 i) "/" file))))
996
997
998;;; Loading source/object files:
999
1000(define load-verbose (make-parameter (##sys#debug-mode?)))
1001
1002(define ##sys#current-load-filename #f)
1003(define ##sys#dload-disabled #f)
1004
1005(define-foreign-variable _dlerror c-string "C_dlerror")
1006
1007(define (set-dynamic-load-mode! mode)
1008 (let ([mode (if (pair? mode) mode (list mode))]
1009 [now #f]
1010 [global #t] )
1011 (let loop ([mode mode])
1012 (when (pair? mode)
1013 (case (##sys#slot mode 0)
1014 [(global) (set! global #t)]
1015 [(local) (set! global #f)]
1016 [(lazy) (set! now #f)]
1017 [(now) (set! now #t)]
1018 [else (##sys#signal-hook 'set-dynamic-load-mode! "invalid dynamic-load mode" (##sys#slot mode 0))] )
1019 (loop (##sys#slot mode 1)) ) )
1020 (##sys#set-dlopen-flags! now global) ) )
1021
1022(define (toplevel name)
1023 (if (not name)
1024 "toplevel"
1025 (##sys#string-append
1026 (string->c-identifier (##sys#slot name 1))
1027 "_toplevel")))
1028
1029(define (c-toplevel name loc)
1030 (##sys#make-c-string (##sys#string-append "C_" (toplevel name)) loc))
1031
1032(define load/internal
1033 (let ((write write)
1034 (display display)
1035 (newline newline)
1036 (eval eval)
1037 (open-input-file open-input-file)
1038 (close-input-port close-input-port))
1039 (lambda (input evaluator #!optional pf timer printer unit)
1040
1041 (define evalproc
1042 (or evaluator eval))
1043
1044 ;; dload doesn't consider filenames without slashes to be paths,
1045 ;; so we prepend a dot to force a relative pathname.
1046 (define (dload-path path)
1047 (if (path-separator-index/right path)
1048 path
1049 (##sys#string-append "./" path)))
1050
1051 (define (dload path)
1052 (let ((c-path (##sys#make-c-string (dload-path path) 'load)))
1053 (or (##sys#dload c-path (c-toplevel unit 'load))
1054 (and (symbol? unit)
1055 (##sys#dload c-path (c-toplevel #f 'load))))))
1056
1057 (define dload?
1058 (and (not ##sys#dload-disabled)
1059 (feature? #:dload)))
1060
1061 (define fname
1062 (cond ((port? input) #f)
1063 ((not (string? input))
1064 (##sys#signal-hook #:type-error 'load "bad argument type - not a port or string" input))
1065 ((##sys#file-exists? input #t #f 'load) input)
1066 ((let ((f (##sys#string-append input ##sys#load-dynamic-extension)))
1067 (and dload? (##sys#file-exists? f #t #f 'load) f)))
1068 ((let ((f (##sys#string-append input source-file-extension)))
1069 (and (##sys#file-exists? f #t #f 'load) f)))
1070 (else
1071 (##sys#signal-hook #:file-error 'load "cannot open file" input))))
1072
1073 (when (and (load-verbose) fname)
1074 (display "; loading ")
1075 (display fname)
1076 (display " ...\n")
1077 (flush-output))
1078
1079 (or (and fname dload? (dload fname))
1080 (call-with-current-continuation
1081 (lambda (abrt)
1082 (fluid-let ((##sys#read-error-with-line-number #t)
1083 (##sys#current-load-filename fname)
1084 (##sys#current-source-filename fname))
1085 (let ((in (if fname (open-input-file fname) input))
1086 (read-with-source-info chicken.syntax#read-with-source-info)) ; OBSOLETE - after bootstrapping we can get rid of this explicit namespacing
1087 (##sys#dynamic-wind
1088 (lambda () #f)
1089 (lambda ()
1090 (let ((c1 (peek-char in)))
1091 (when (eq? c1 (integer->char 127))
1092 (##sys#error
1093 'load
1094 (##sys#string-append
1095 "unable to load compiled module - "
1096 (or _dlerror "unknown reason"))
1097 fname)))
1098 (let ((x1 (read-with-source-info in)))
1099 (do ((x x1 (read-with-source-info in)))
1100 ((eof-object? x))
1101 (when printer (printer x))
1102 (##sys#call-with-values
1103 (lambda ()
1104 (if timer
1105 (time (evalproc x))
1106 (evalproc x)))
1107 (lambda results
1108 (when pf
1109 (for-each
1110 (lambda (r)
1111 (write r)
1112 (newline))
1113 results)))))))
1114 (lambda ()
1115 (close-input-port in))))))))
1116 (##core#undefined))))
1117
1118(set! scheme#load
1119 (lambda (filename #!optional evaluator)
1120 (load/internal filename evaluator)))
1121
1122(define (load-relative filename #!optional evaluator)
1123 (let ((fn (make-relative-pathname ##sys#current-load-filename filename)))
1124 (load/internal fn evaluator)))
1125
1126(define (load-noisily filename #!key (evaluator #f) (time #f) (printer #f))
1127 (load/internal filename evaluator #t time printer))
1128
1129(define dynamic-load-libraries
1130 (let ((ext
1131 (if uses-soname?
1132 (string-append
1133 load-library-extension
1134 "."
1135 (number->string binary-version))
1136 load-library-extension)))
1137 (define complete
1138 (cut ##sys#string-append <> ext))
1139 (make-parameter
1140 (map complete default-dynamic-load-libraries)
1141 (lambda (x)
1142 (##sys#check-list x)
1143 x) ) ) )
1144
1145(define (load-unit unit-name lib loc)
1146 (unless (##sys#provided? unit-name)
1147 (let ((libs
1148 (if lib
1149 (##sys#list lib)
1150 (cons (##sys#string-append (##sys#slot unit-name 1) load-library-extension)
1151 (dynamic-load-libraries))))
1152 (top
1153 (c-toplevel unit-name loc)))
1154 (when (load-verbose)
1155 (display "; loading library ")
1156 (display unit-name)
1157 (display " ...\n"))
1158 (let loop ((libs libs))
1159 (cond ((null? libs)
1160 (##sys#error loc "unable to load library" unit-name (or _dlerror "library not found")))
1161 ((##sys#dload (##sys#make-c-string (##sys#slot libs 0) 'load-library) top)
1162 (##core#undefined))
1163 (else
1164 (loop (##sys#slot libs 1))))))))
1165
1166(define (load-library unit-name #!optional lib)
1167 (##sys#check-symbol unit-name 'load-library)
1168 (unless (not lib) (##sys#check-string lib 'load-library))
1169 (load-unit unit-name lib 'load-library))
1170
1171(define ##sys#include-forms-from-file
1172 (let ((call-with-input-file call-with-input-file)
1173 (reverse reverse))
1174 (lambda (filename source k)
1175 (let ((path (##sys#resolve-include-filename filename #t #f source))
1176 (read-with-source-info chicken.syntax#read-with-source-info)) ; OBSOLETE - after bootstrapping we can get rid of this explicit namespacing
1177 (when (not path)
1178 (##sys#signal-hook #:file-error 'include "cannot open file" filename))
1179 (when (load-verbose)
1180 (print "; including " path " ..."))
1181 (call-with-input-file path
1182 (lambda (in)
1183 (k (fluid-let ((##sys#current-source-filename path))
1184 (do ((x (read-with-source-info in) (read-with-source-info in))
1185 (xs '() (cons x xs)))
1186 ((eof-object? x)
1187 (reverse xs))))
1188 path)))))))
1189
1190
1191;;; Extensions:
1192
1193(define ##sys#setup-mode #f)
1194
1195(define (file-exists? name) ; defined here to avoid file unit dependency
1196 (and (##sys#file-exists? name #t #f #f) name))
1197
1198(define (find-file name search-path)
1199 (cond ((not search-path) #f)
1200 ((null? search-path) #f)
1201 ((string? search-path) (find-file name (list search-path)))
1202 ((file-exists? (string-append (car search-path) "/" name)))
1203 (else (find-file name (cdr search-path)))))
1204
1205(define find-dynamic-extension
1206 (let ((string-append string-append))
1207 (lambda (id inc?)
1208 (let ((rp (repository-path))
1209 (basename (if (symbol? id) (symbol->string id) id)))
1210 (define (check path)
1211 (let ((p0 (string-append path "/" basename)))
1212 (or (and rp
1213 (not ##sys#dload-disabled)
1214 (feature? #:dload)
1215 (file-exists? (##sys#string-append p0 ##sys#load-dynamic-extension)))
1216 (file-exists? (##sys#string-append p0 source-file-extension)))))
1217 (let loop ((paths (##sys#append
1218 (if ##sys#setup-mode '(".") '())
1219 (or rp '())
1220 (if inc? ##sys#include-pathnames '())
1221 (if ##sys#setup-mode '() '("."))) ))
1222 (and (pair? paths)
1223 (let ((pa (##sys#slot paths 0)))
1224 (or (check pa)
1225 (loop (##sys#slot paths 1)) ) ) ) ) ) ) ))
1226
1227(define-inline (extension-loaded? lib mod)
1228 (cond ((##sys#provided? lib))
1229 ((eq? mod #t)
1230 (##sys#provided? (module-requirement lib)))
1231 ((symbol? mod)
1232 (##sys#provided? (module-requirement mod)))
1233 (else #f)))
1234
1235(define (load-extension lib mod loc)
1236 (unless (extension-loaded? lib mod)
1237 (cond ((memq lib core-units)
1238 (load-unit lib #f loc))
1239 ((find-dynamic-extension lib #f) =>
1240 (lambda (ext)
1241 (load/internal ext #f #f #f #f lib)
1242 (##sys#provide lib)
1243 (##core#undefined)))
1244 (else
1245 (##sys#error loc "cannot load extension" lib)))))
1246
1247(define (require . ids)
1248 (for-each (cut ##sys#check-symbol <> 'require) ids)
1249 (for-each (cut load-extension <> #f 'require) ids))
1250
1251(define (provide . ids)
1252 (for-each (cut ##sys#check-symbol <> 'provide) ids)
1253 (for-each (cut ##sys#provide <>) ids))
1254
1255(define (provided? . ids)
1256 (for-each (cut ##sys#check-symbol <> 'provided?) ids)
1257 (every ##sys#provided? ids))
1258
1259;; Export for internal use in the expansion of `##core#require':
1260(define chicken.load#load-unit load-unit)
1261(define chicken.load#load-extension load-extension)
1262
1263;; Export for internal use in csc, modules and batch-driver:
1264(define chicken.load#find-file find-file)
1265(define chicken.load#find-dynamic-extension find-dynamic-extension)
1266
1267;; Do the right thing with a `##core#require' form.
1268(define (##sys#process-require lib mod compile-mode)
1269 (let ((mod (or (eq? lib mod) mod)))
1270 (cond
1271 ((assq lib core-unit-requirements) => cdr)
1272 ((memq lib core-units)
1273 (if compile-mode
1274 `(##core#callunit ,lib)
1275 `(chicken.load#load-unit (##core#quote ,lib)
1276 (##core#quote #f)
1277 (##core#quote #f))))
1278 ((eq? compile-mode 'static)
1279 `(##core#callunit ,lib))
1280 (else
1281 `(chicken.load#load-extension (##core#quote ,lib)
1282 (##core#quote ,mod)
1283 (##core#quote #f))))))
1284
1285;;; Find included file:
1286
1287(define ##sys#resolve-include-filename
1288 (let ((string-append string-append) )
1289 (lambda (fname exts repo source)
1290 (define (test-extensions fname lst)
1291 (if (null? lst)
1292 (and (file-exists? fname) fname)
1293 (let ((fn (##sys#string-append fname (car lst))))
1294 (or (file-exists? fn)
1295 (test-extensions fname (cdr lst))))))
1296 (define (test fname)
1297 (test-extensions
1298 fname
1299 (cond ((pair? exts) exts) ; specific list of extensions
1300 ((not (feature? #:dload)) ; no dload -> source only
1301 (list source-file-extension))
1302 ((not exts) ; prefer compiled
1303 (list ##sys#load-dynamic-extension source-file-extension))
1304 (else ; prefer source
1305 (list source-file-extension ##sys#load-dynamic-extension)))))
1306 (or (test (make-relative-pathname source fname))
1307 (let loop ((paths (if repo
1308 (##sys#append
1309 ##sys#include-pathnames
1310 (or (repository-path) '()) )
1311 ##sys#include-pathnames) ) )
1312 (cond ((eq? paths '()) #f)
1313 ((test (string-append (##sys#slot paths 0)
1314 "/"
1315 fname) ) )
1316 (else (loop (##sys#slot paths 1))) ) ) ) ) ) )
1317
1318) ; chicken.load
1319
1320
1321;;; Simple invocation API:
1322
1323(import scheme chicken.base chicken.condition chicken.eval chicken.fixnum chicken.load)
1324
1325(declare
1326 (hide last-error run-safe store-result store-string
1327 CHICKEN_yield CHICKEN_eval CHICKEN_eval_string
1328 CHICKEN_eval_to_string CHICKEN_eval_string_to_string
1329 CHICKEN_apply CHICKEN_apply_to_string CHICKEN_eval_apply
1330 CHICKEN_read CHICKEN_load CHICKEN_get_error_message))
1331
1332(define last-error #f)
1333
1334(define (run-safe thunk)
1335 (set! last-error #f)
1336 (handle-exceptions ex
1337 (let ((o (open-output-string)))
1338 (print-error-message ex o)
1339 (set! last-error (get-output-string o))
1340 #f)
1341 (thunk) ) )
1342
1343#>
1344#define C_store_result(x, ptr) (*((C_word *)C_block_item(ptr, 0)) = (x), C_SCHEME_TRUE)
1345<#
1346
1347(define (store-result x result)
1348 (##sys#gc #f)
1349 (when result
1350 (##core#inline "C_store_result" x result) )
1351 #t)
1352
1353(define-external (CHICKEN_yield) bool
1354 (run-safe (lambda () (begin (##sys#thread-yield!) #t))) )
1355
1356(define-external (CHICKEN_eval (scheme-object exp) ((c-pointer "C_word") result)) bool
1357 (run-safe
1358 (lambda ()
1359 (store-result (eval exp) result))))
1360
1361(define-external (CHICKEN_eval_string (c-string str) ((c-pointer "C_word") result)) bool
1362 (run-safe
1363 (lambda ()
1364 (let ((i (open-input-string str)))
1365 (store-result (eval (read i)) result)))))
1366
1367#>
1368#define C_copy_result_string(str, buf, n) (C_memcpy((char *)C_block_item(buf, 0), C_c_string(str), C_unfix(n)), ((char *)C_block_item(buf, 0))[ C_unfix(n) ] = '\0', C_SCHEME_TRUE)
1369<#
1370
1371(define (store-string str bufsize buf)
1372 (let ((len (##sys#size str)))
1373 (cond ((fx>= len bufsize)
1374 (set! last-error "Error: not enough room for result string")
1375 #f)
1376 (else (##core#inline "C_copy_result_string" str buf len)) ) ) )
1377
1378(define-external (CHICKEN_eval_to_string (scheme-object exp) ((c-pointer "char") buf)
1379 (int bufsize))
1380 bool
1381 (run-safe
1382 (lambda ()
1383 (let ((o (open-output-string)))
1384 (write (eval exp) o)
1385 (store-string (get-output-string o) bufsize buf)) ) ) )
1386
1387(define-external (CHICKEN_eval_string_to_string (c-string str) ((c-pointer "char") buf)
1388 (int bufsize) )
1389 bool
1390 (run-safe
1391 (lambda ()
1392 (let ((o (open-output-string)))
1393 (write (eval (read (open-input-string str))) o)
1394 (store-string (get-output-string o) bufsize buf)) ) ) )
1395
1396(define-external (CHICKEN_apply (scheme-object func) (scheme-object args)
1397 ((c-pointer "C_word") result))
1398 bool
1399 (run-safe (lambda () (store-result (apply func args) result))) )
1400
1401(define-external (CHICKEN_apply_to_string (scheme-object func) (scheme-object args)
1402 ((c-pointer "char") buf) (int bufsize))
1403 bool
1404 (run-safe
1405 (lambda ()
1406 (let ((o (open-output-string)))
1407 (write (apply func args) o)
1408 (store-string (get-output-string o) bufsize buf)) ) ) )
1409
1410(define-external (CHICKEN_read (c-string str) ((c-pointer "C_word") result)) bool
1411 (run-safe
1412 (lambda ()
1413 (let ((i (open-input-string str)))
1414 (store-result (read i) result) ) ) ) )
1415
1416(define-external (CHICKEN_load (c-string str)) bool
1417 (run-safe (lambda () (load str) #t)))
1418
1419(define-external (CHICKEN_get_error_message ((c-pointer "char") buf) (int bufsize)) void
1420 (store-string (or last-error "No error") bufsize buf) )