With the most recent changes to the universal backend and library, Gambit's JavaScript and Python backends are now much easier to use.
The following steps will build and install the universal library with the JavaScript and Python backends:
% make
% make _gambit.js _gambit.py
% make install
Scheme programs can be compiled to either JavaScript or Python shell scripts by specifying the -exe flag and the target language to gsc:
% gsc -target js -o fib-js -exe fib.scm
% ./fib-js
(time (f 30))
0.076000 secs real time
0.076000 secs cpu time (0.076000 user, 0.000000 system)
no collections
no bytes allocated
no minor faults
no major faults
832040
% cat fib.scm
(declare (standard-bindings))
(define (f n) (if (< n 2) n (+ (f (- n 1)) (f (- n 2)))))
(println (time (f 30)))
It is also possible to build a version of the Gambit interpreter implemented in JavaScript with:
% gsc -target js -o gsi-js -exe -prelude '(include"../lib/header.scm")' gsi/_gsi.scm
Replacing "js" with "python" will build gsi implemented in Python:
% ./gsi-python
Gambit v4.9.3
> (host-decl "import os")
> (define (env var) (host-eval "g_host2scm(os.environ[g_scm2host(@1@)])" var))
> (env "TERM")
"dumb"
> ,q
% ./gsi-js
Gambit v4.9.3
> (define (f n) (if (< n 2) n (+ (f (- n 1)) (f (- n 2)))))
> (time (f 30))
(time (f 30))
2.254000 secs real time
2.254000 secs cpu time (2.254000 user, 0.000000 system)
no collections
no bytes allocated
no minor faults
no major faults
832040
> (apropos 'inexact)
"##" namespace:
exact->inexact, fail-check-inexact-real, fail-check-inexact-real-list,
flonum->inexact-exponential-format, inexact, inexact->exact, inexact?
empty namespace:
exact->inexact, inexact, inexact->exact, inexact?
> (define (show x) (host-exec "console.log(g_scm2host(@1@));" x))
> (show "hello")
hello
> (show (host-eval "g_host2scm(new Date().toString())"))
Sun Mar 22 2020 23:20:29 GMT-0400 (GMT-04:00)
> ,q
The universal library is quite large (> 30MB)... so the memory conscious may choose to link with a custom runtime library that defines only the procedures needed. The compiler's -l flag is useful to specify the library to link with.
;;; minlib.scm
(println "running minlib.scm")
(define (twice thunk) ;; exported procedure
(thunk)
(thunk))
(define (##run-each-module)
(declare (extended-bindings) (not safe))
(let ((mods (##vector-ref ##program-descr 0)))
(let loop ((i 1)) ;; start at module after the current one
(if (##fx< i (##vector-length mods))
(let ((mod (##vector-ref mods i)))
((##vector-ref mod 4)) ;; call module's init procedure
(loop (##fx+ i 1)))))))
(##run-each-module) ;; run each module (after the current one)
;; To use this minimal library to compile a program prog.scm,
;; follow these steps:
;;
;; % cat prog.scm
;; (twice (lambda () (println "hello")))
;; % TARGET=js # could also be python or php
;; % gsc -target $TARGET -c minlib.scm
;; % gsc -target $TARGET -l minlib -exe prog.scm
;; % ./prog
;; running minlib.scm
;; hello
;; hello
;; % head -1 prog
;; #! /usr/bin/env node
There are still some issues with the universal backend, but it is now much closer to the features offered by the C backend.
Marc