[gambit-list] Compiling to Javascript
hashavtech at outlook.com
hashavtech at outlook.com
Mon Jul 8 07:34:22 EDT 2019
Thank you for the detailed example, it helped a lot. I've played with running Scheme in a browser and it's a lot of fun! (Although writing custom runtime library is not easy for a newcomer. For example is there a list of what is supported by the compiler out of the box - such as fx+ and friends? )
In any case this was using compiled Scheme as a main script, and I was thinking how to use Scheme with some JS framework that does not like to relinquish control. Ideally I think there'd be possible to do the following:
1. Initialize Gambit VM, something like GVM.init();
2. Later call into some procedure passing parameters: GM.call('do-scheme-stuff', [param1, param2]);
3. from scheme code to be able to pause the execution and to return control to the external javascript. Something like this:
(define (dostuff)
... (define (add-to-menu option) (##inline-host-expression "addToGlobalFrameworkMenu(...)"))
(add-to-menu "option1")
(add-to-menu "option2")
(##pause-vm)
Where ##pause-vm will stop executing scheme code. Later it'd be possible in JS to do GVM.resume("option2") and have (##pause-vm) return with the supplied value. Alternatively, we'd be able call GVM.dropStack() to trash the scheme stack and start anew with GVM.call('other-entry-point', ['more values']);
There does not seem to be anything in the manual regarding the various backends such as JS, so I'm not sure, but most of this probably is possible?
________________________________
From: Marc Feeley <feeley at iro.umontreal.ca>
Sent: Friday, July 5, 2019 1:46 PM
To: hashavtech at outlook.com
Cc: gambit-list at iro.umontreal.ca
Subject: Re: [gambit-list] Compiling to Javascript
I’m currently working on implementing an intelligent linker that can remove the parts of the runtime library that are not needed by the application. For the moment, to get a compact executable you need to write your own runtime library for the functions you need. If you only need basic stuff, this may be a reasonable undertaking.
Below is a sample application split in 2 files: “lib.scm” is the runtime library and “app.scm” is the main program. The library contains definitions of for-each, append, etc. Note that some operations like fx+, fx-, fx<, cons, car, cdr, println don’t need to be defined because the Gambit compiler treats them as inlined primitives (they compile to the corresponding JavaScript code instead of being actual Scheme procedure calls).
Here is how this application is linked, and the result of executing the app:
% make
gsc -target js -c lib.scm
gsc -target js -c app.scm
gsc -target js -link -l lib app.js
gsc -target js -c lib.scm
cat app_.js lib.js app.js > linked_app.js
wc *.js
339 870 7244 app.js
651 1931 14992 app_.js
335 853 7937 lib.js
1325 3654 30173 linked_app.js
2650 7308 60346 total
node linked_app.js
>>> lib.scm
>>> app.scm
1
1
2
3
5
8
410
9227465
The JavaScript code is 30K bytes, and half of that is in app_.js that is the runtime system (which won’t grow much if the application is bigger).
Aside from the intelligent linker, a more compact code could be obtained by minimizing the JavaScript code either with an external minimizer or by reducing the size of the identifiers that are emitted by the compiler and not pretty-printing the JavaScipt code which adds lots of spaces for indentation.
Marc
------------------------------------------------------------
# makefile
#GSC=../gsc/gsc -:=.. -target js
GSC=gsc -target js
all: run
lib.js: lib.scm
$(GSC) -c lib.scm
app.js: app.scm
$(GSC) -c app.scm
app_.js: lib.js app.js
$(GSC) -link -l lib app.js
linked_app.js: lib.js app.js app_.js
$(GSC) -c lib.scm
cat app_.js lib.js app.js > linked_app.js
wc *.js
run: linked_app.js
node linked_app.js
clean:
rm -f lib.js app.js app_.js linked_app.js
------------------------------------------------------------
;; file: lib.scm
(declare (standard-bindings) (extended-bindings) (not safe) (not run-time-bindings))
(println ">>> lib.scm")
(define (for-each f lst)
(if (pair? lst)
(begin
(f (car lst))
(for-each f (cdr lst)))))
(define (append lst1 lst2)
(if (pair? lst1)
(cons (car lst1) (append (cdr lst1) lst2))
lst2))
(define (current-milliseconds)
(##inline-host-expression "Date.now()"))
(define (js-alert obj)
(##inline-host-statement "alert(g_scm2js(@1@));" obj))
(app#) ;; execute app.scm module
------------------------------------------------------------
;; file: app.scm
(declare (standard-bindings) (extended-bindings) (not safe) (not run-time-bindings))
(println ">>> app.scm")
(define (fib n) (if (fx< n 2) n (fx+ (fib (fx- n 1)) (fib (fx- n 2)))))
(for-each
(lambda (x)
(println (fib x)))
(append '(1 2 3)
'(4 5 6)))
(let* ((start (current-milliseconds))
(result (fib 35))
(end (current-milliseconds)))
(js-alert (fx- end start))
(js-alert result))
------------------------------------------------------------
> On Jun 29, 2019, at 10:59 AM, hashavtech at outlook.com wrote:
>
> There are some messages in 2013 and 2016 that gave me a hint of what needs to be done in order to compile to js. But it seems that some things have changed (for example the gsc with -target js does not seem to produce a .js file, it gave me an .o1 file that contained Javascript). I was able to compile a working example once but the .js file contains the whole _gambit.js library and is 22 MB in size. That isn't really what I was hoping for. I've seen it mentioned that there was some work done on only including the necessary parts of the library, but I was unable to figure out how to do it (I'm new to Gambit although not to Lisp).
>
> I'd be glad for some help getting from a Scheme file to a working and reasonably-sized file. My goal is to include scheme-sourced parts in a web app, so there probably will be some interoperability issues, but at the moment I'm stuck at the compilation stage.
>
> _______________________________________________
> Gambit-list mailing list
> Gambit-list at iro.umontreal.ca
> https://mailman.iro.umontreal.ca/cgi-bin/mailman/listinfo/gambit-list
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.iro.umontreal.ca/pipermail/gambit-list/attachments/20190708/008f9a93/attachment.htm>
More information about the Gambit-list
mailing list