On 17-Aug-09, at 11:32 PM, peter lo wrote:
The above partition of the modules is only a random suggestion, but you get the idea. With such a system, only the relevant parts get into the final program, so we pay for only when we need.
Here's an idea that is based on
https://webmail.iro.umontreal.ca/pipermail/gambit-list/2008-October/002725.h...
It involves rewriting the Scheme library, which is not as complex as one might think, for example the BIT system contains a R4RS library written in Scheme that could be reused with only a few changes.
You need to first create a minimal Gambit library that only contains the kernel:
% ./configure % make % make bootstrap % ... now edit lib/makefile.in to only include _kernel in the library... % diff lib/makefile.in lib/makefile.in-orig 78,83c78,89 < MODULES = _kernel < MODULES_SCM = _kernel.scm < MODULES_C = _kernel.c < MODULES_O = _kernel@obj@ < MODULES_O_PLUS = +_kernel@obj@ < MODULES_O_COMMA = _kernel@obj@ ---
MODULES = _kernel _system _num _std \ _eval _io _nonstd _thread _repl MODULES_SCM = _kernel.scm _system.scm _num.scm _std.scm \ _eval.scm _io.scm _nonstd.scm _thread.scm _repl.scm MODULES_C = _kernel.c _system.c _num.c _std.c \ _eval.c _io.c _nonstd.c _thread.c _repl.c MODULES_O = _kernel@obj@ _system@obj@ _num@obj@ _std@obj@ \ _eval@obj@ _io@obj@ _nonstd@obj@ _thread@obj@ _repl@obj@ MODULES_O_PLUS = +_kernel@obj@ +_system@obj@ +_num@obj@ +_std@obj@ \ +_eval@obj@ +_io@obj@ +_nonstd@obj@ +_thread@obj@ +_repl@obj@ MODULES_O_COMMA = _kernel@obj@,_system@obj@,_num@obj@,_std@obj@,\ +_eval@obj@,_io@obj@,_nonstd@obj@,_thread@obj@,_repl@obj@
87c93,94 < MODULES_O_IN_COMPILE_ORDER = _kernel@obj@ ---
MODULES_O_IN_COMPILE_ORDER = _io@obj@ _num@obj@ _std@obj@ \ _kernel@obj@ _nonstd@obj@ _repl@obj@ _eval@obj@ _thread@obj@
_system@obj@ % cd lib % make clean % make % cd .. % ./gsc-comp -:=. -exe test.scm % strip test % ls -l test -rwxr-xr-x 1 feeley feeley 308672 Aug 18 01:35 test % ./test 10946
The file test.scm is attached below. As you can see I obtained a 300kB executable for this program.
The program could have included all of the Scheme library. Note that the definitions of the library procedures are in a "let" so the Gambit compiler can eliminate all of the definitions that are not needed. It is in effect a whole-program compilation.
What would be really nice is if this could be done with the current Gambit runtime library. This would require some changes to the structure of the library. If anyone is interested in doing this, please let me know!
Marc
;; File: "test.scm"
(declare (standard-bindings) (extended-bindings) (not inline-primitives) (inlining-limit 0) (not safe) (fixnum) (block) )
(c-declare "#include <stdio.h>") ;; to access puts
(let ()
(define puts (c-lambda (char-string) int "puts"))
(define (make-string k #!optional (f #\space)) (##make-string k f))
(define (substring-move! src-str src-start src-end dst-str dst-start) ;; Copy direction must be selected in case src-str and ;; dst-str are the same string. (if (fx< src-start dst-start) (let loop1 ((i (fx- src-end 1)) (j (fx- (fx+ dst-start (fx- src-end src-start)) 1))) (if (fx< i src-start) dst-str (begin (string-set! dst-str j (string-ref src-str i)) (loop1 (fx- i 1) (fx- j 1))))) (let loop2 ((i src-start) (j dst-start)) (if (fx< i src-end) (begin (string-set! dst-str j (string-ref src-str i)) (loop2 (fx+ i 1) (fx+ j 1))) dst-str))))
(define (substring str start end) (substring-move! str start end (make-string (fxmax (fx- end start) 0)) 0))
(define (append-strings lst) (let loop1 ((n 0) (lst1 lst) (lst2 '())) (if (pair? lst1) (let ((str (car lst1))) (loop1 (fx+ n (string-length str)) (cdr lst1) (cons str lst2))) (let ((result (make-string n))) (let loop2 ((n n) (lst2 lst2)) (if (pair? lst2) (let* ((str (car lst2)) (len (string-length str)) (new-n (fx- n len))) (substring-move! str 0 len result new-n) (loop2 new-n (cdr lst2))) result))))))
(define (string-append . lst) (append-strings lst))
(define (append x y) (if (pair? x) (cons (car x) (append (cdr x) y)) y))
(define (fold kons knil lst) (let loop ((lst lst) (ans knil)) (if (pair? lst) (loop (cdr lst) (kons (car lst) ans)) ans)))
(define (number->string n #!optional (b 10)) (if (fx< n b) (substring "0123456789abcdef" n (fx+ n 1)) (string-append (number->string (fxquotient n b) b) (number->string (fxmodulo n b) b))))
(define (display obj) (cond ((string? obj) (puts obj)) ((fixnum? obj) (puts (number->string obj))) (else (puts "<unknown object>"))))
;; ... put rest of Scheme library here ... ;; possibly a (include "scheme-lib.scm") for the whole thing
;; main program:
(define (fib n) (if (fx< n 2) 1 (fx+ (fib (fx- n 1)) (fib (fx- n 2)))))
(display (fib 20)) )