<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=Windows-1252">
<style type="text/css" style="display:none;"> P {margin-top:0;margin-bottom:0;} </style>
</head>
<body dir="ltr">
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
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? )</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
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:</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<ol>
<li>Initialize Gambit VM, something like GVM.init();</li><li>Later call into some procedure passing parameters: GM.call('do-scheme-stuff', [param1, param2]);</li><li>from scheme code to be able to pause the execution and to return control to the external javascript. Something like this:<br>
</li></ol>
<div>(define (dostuff)</div>
<div>... (define (add-to-menu option) (<span style="color: rgb(32, 31, 30); font-family: "Segoe UI", "Segoe UI Web (West European)", "Segoe UI", -apple-system, system-ui, Roboto, "Helvetica Neue", sans-serif; font-size: 14.6667px; background-color: rgb(255, 255, 255); display: inline !important">##inline-host-expression
"addToGlobalFrameworkMenu(...)"))</span></div>
<div> (add-to-menu "option1")</div>
<div><span style="font-family: Calibri, Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255); display: inline !important"> (add-to-menu "option2")</span><br>
</div>
<div><span style="font-family: Calibri, Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255); display: inline !important"> (##pause-vm)</span></div>
<div><span style="font-family: Calibri, Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255); display: inline !important"><br>
</span></div>
<div><span style="font-family: Calibri, Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255); display: inline !important">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']);</span></div>
<div><span style="font-family: Calibri, Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255); display: inline !important"><br>
</span></div>
<div><span style="font-family: Calibri, Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255); display: inline !important">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?</span></div>
<div><span style="font-family: Calibri, Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255); display: inline !important"><br>
</span></div>
<div><span style="font-family: Calibri, Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255); display: inline !important"><br>
</span></div>
</div>
<div id="Signature"></div>
<div id="appendonsend"></div>
<hr style="display:inline-block;width:98%" tabindex="-1">
<div id="divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" style="font-size:11pt" color="#000000"><b>From:</b> Marc Feeley <feeley@iro.umontreal.ca><br>
<b>Sent:</b> Friday, July 5, 2019 1:46 PM<br>
<b>To:</b> hashavtech@outlook.com<br>
<b>Cc:</b> gambit-list@iro.umontreal.ca<br>
<b>Subject:</b> Re: [gambit-list] Compiling to Javascript</font>
<div> </div>
</div>
<div class="BodyFragment"><font size="2"><span style="font-size:11pt;">
<div class="PlainText">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.<br>
<br>
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).<br>
<br>
Here is how this application is linked, and the result of executing the app:<br>
<br>
% make<br>
gsc -target js -c lib.scm<br>
gsc -target js -c app.scm<br>
gsc -target js -link -l lib app.js<br>
gsc -target js -c lib.scm<br>
cat app_.js lib.js app.js > linked_app.js<br>
wc *.js<br>
339 870 7244 app.js<br>
651 1931 14992 app_.js<br>
335 853 7937 lib.js<br>
1325 3654 30173 linked_app.js<br>
2650 7308 60346 total<br>
node linked_app.js<br>
>>> lib.scm<br>
>>> app.scm<br>
1<br>
1<br>
2<br>
3<br>
5<br>
8<br>
410<br>
9227465<br>
<br>
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).<br>
<br>
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.<br>
<br>
Marc<br>
<br>
<br>
<br>
------------------------------------------------------------<br>
# makefile<br>
<br>
#GSC=../gsc/gsc -:=.. -target js<br>
GSC=gsc -target js<br>
<br>
all: run<br>
<br>
lib.js: lib.scm<br>
$(GSC) -c lib.scm<br>
<br>
app.js: app.scm<br>
$(GSC) -c app.scm<br>
<br>
app_.js: lib.js app.js<br>
$(GSC) -link -l lib app.js<br>
<br>
linked_app.js: lib.js app.js app_.js<br>
$(GSC) -c lib.scm<br>
cat app_.js lib.js app.js > linked_app.js<br>
wc *.js<br>
<br>
run: linked_app.js<br>
node linked_app.js<br>
<br>
clean:<br>
rm -f lib.js app.js app_.js linked_app.js<br>
------------------------------------------------------------<br>
;; file: lib.scm<br>
<br>
(declare (standard-bindings) (extended-bindings) (not safe) (not run-time-bindings))<br>
<br>
(println ">>> lib.scm")<br>
<br>
(define (for-each f lst)<br>
(if (pair? lst)<br>
(begin<br>
(f (car lst))<br>
(for-each f (cdr lst)))))<br>
<br>
(define (append lst1 lst2)<br>
(if (pair? lst1)<br>
(cons (car lst1) (append (cdr lst1) lst2))<br>
lst2))<br>
<br>
(define (current-milliseconds)<br>
(##inline-host-expression "Date.now()"))<br>
<br>
(define (js-alert obj)<br>
(##inline-host-statement "alert(g_scm2js(@1@));" obj))<br>
<br>
(app#) ;; execute app.scm module<br>
------------------------------------------------------------<br>
;; file: app.scm<br>
<br>
(declare (standard-bindings) (extended-bindings) (not safe) (not run-time-bindings))<br>
<br>
(println ">>> app.scm")<br>
<br>
(define (fib n) (if (fx< n 2) n (fx+ (fib (fx- n 1)) (fib (fx- n 2)))))<br>
<br>
(for-each<br>
(lambda (x)<br>
(println (fib x)))<br>
(append '(1 2 3)<br>
'(4 5 6)))<br>
<br>
(let* ((start (current-milliseconds))<br>
(result (fib 35))<br>
(end (current-milliseconds)))<br>
(js-alert (fx- end start))<br>
(js-alert result))<br>
------------------------------------------------------------<br>
<br>
<br>
> On Jun 29, 2019, at 10:59 AM, hashavtech@outlook.com wrote:<br>
> <br>
> 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).
<br>
> <br>
> 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.<br>
> <br>
> _______________________________________________<br>
> Gambit-list mailing list<br>
> Gambit-list@iro.umontreal.ca<br>
> <a href="https://mailman.iro.umontreal.ca/cgi-bin/mailman/listinfo/gambit-list">
https://mailman.iro.umontreal.ca/cgi-bin/mailman/listinfo/gambit-list</a><br>
<br>
<br>
</div>
</span></font></div>
</body>
</html>