[gambit-list] Compiling Gambit Scheme to JavaScript

Marc Feeley feeley at iro.umontreal.ca
Tue Mar 13 11:10:11 EDT 2012


I was inspired by the ClojureScript project, a Clojure to JavaScript compiler, to look into the feasibility of a JavaScript back-end for Gambit.  A JavaScript back-end would allow running Gambit programs in web browsers.  Moreover, Scheme objects, including closures and continuations, could be sent between a Gambit Scheme program running on the browser and a Gambit Scheme program running on the server.

I did a fairly direct translation of the GVM code for the fib function into JavaScript (see the code attached below which interleaves the GVM code and JavaScript code).  Under V8 on a recent Mac Book Pro, this JavaScript program runs about 10 times slower than when the Scheme program is compiled with the C back-end (and 4 times faster than when the Scheme program is interpreted with gsi).  This is not so bad considering that JavaScript is a dynamic language with more overhead than C.  Moreover, for event-driven programs, which are most of the time waiting for input, this is probably an acceptable level of performance.

If anyone would like to pursue this idea, please let me know.

Marc


// GVM state
var _stack;
var _nargs;
var _r0;
var _r1;

//**** #<primitive | fib.o1|> =
//#line 10 "/Users/feeley/gambit/work/fib.scm"

//#1 0 entry-point 0 ()                       ; +0=#
function _primitive_fib_o1()
{
if (_nargs !== 0) error("wrong number of arguments");
var _stk = {parent: _stack}; // allocate frame

//#line 16
//  -1 = +0                                   ; -1=#
_stk.slot1 = _r0;

//  +1 = '40                                  ; -1=# +1=.
_r1 = 40;

//  +0 = #3                                   ; -1=# +0=. +1=.
_r0 = _primitive_fib_o1_label3;

//  -2 = .                                    ; -1=# -2 +0=. +1=.
//  -3 = .                                    ; -1=# -2 -3 +0=. +1=.
//  -4 = .                                    ; -1=# -2 -3 -4 +0=. +1=.
//  jump* 4 #2                                ; -1=# -2 -3 -4 +0=. +1=.
//#2 4                                        ; -1=# -2 -3 -4 +0=. +1=.
//  jump 4 '#<primitive fib> 1                ; -1=# -2 -3 -4 +0=. +1=.
_nargs = 1;
_stack = _stk;
return _primitive_fib;
}

//#3 4 return-point                           ; -1=# -2 -3 -4 +1=.
function _primitive_fib_o1_label3()
{
var _stk = _stack;

//  +0 = -1                                   ; -1 -2 -3 -4 +0=# +1=.
_r0 = _stk.slot1;

//  jump* 4 #4                                ; -1 -2 -3 -4 +0=# +1=.
//#4 4                                        ; -1 -2 -3 -4 +0=# +1=.
//  jump 0 println 1                          ; +0=# +1=.
_nargs = 1;
_stack = _stk.parent; // pop frame
return _primitive_println;
}

//
//**** #<primitive fib> =
//#line 10 "/Users/feeley/gambit/work/fib.scm"
//#1 0 entry-point 1 ()                       ; +0=# +1=n
function _primitive_fib()
{
if (_nargs !== 1) error("wrong number of arguments");

//#line 11
//  if (##fx< +1 '2) jump 0 #5 else #3        ; +0=# +1=n
return (_r1 < 2) ? _primitive_fib_label5 : _primitive_fib_label3;
}

//#line 10
//#2 0                                        ; +0=# +1=n
function _primitive_fib_label2()
{

//#line 11
//  if (##fx< +1 '2) jump 0 #5 else #3        ; +0=# +1=n
return (_r1 < 2) ? _primitive_fib_label5 : _primitive_fib_label3;
}

//#3 0                                        ; +0=# +1=n
function _primitive_fib_label3()
{
var _stk = {parent: _stack}; // allocate frame

//#line 13
//  -1 = +0                                   ; -1=# +1=n
_stk.slot1 = _r0;

//  -2 = +1                                   ; -1=# -2=n +1=n
_stk.slot2 = _r1;

//  +1 = (##fx- +1 '1)                        ; -1=# -2=n +1=.
_r1 = _r1 - 1;

//  +0 = #4                                   ; -1=# -2=n +0=. +1=.
_r0 = _primitive_fib_label4;

//  -3 = .                                    ; -1=# -2=n -3 +0=. +1=.
//  -4 = .                                    ; -1=# -2=n -3 -4 +0=. +1=.
//  -5 = .                                    ; -1=# -2=n -3 -4 -5 +0=. +1=.
//  -6 = .                                    ; -1=# -2=n -3 -4 -5 -6 +0=. +1=.
//  -7 = .                                    ; -1=# -2=n -3 -4 -5 -6 -7 +0=. +1=.
//  -8 = .                                    ; -1=# -2=n -3 -4 -5 -6 -7 -8 +0=. +1=.
//  jump* 8 #2                                ; -1=# -2=n -3 -4 -5 -6 -7 -8 +0=. +1=.
_stack = _stk;
return _primitive_fib_label2;
}

//#4 8 return-point                           ; -1=# -2=n -3 -4 -5 -6 -7 -8 +1=.
function _primitive_fib_label4()
{
var _stk = _stack;

//#line 14
//  -3 = +1                                   ; -1=# -2=n -3=. -4 -5 -6 -7 -8 +1=.
_stk.slot3 = _r1;

//  +1 = (##fx- -2 '2)                        ; -1=# -2 -3=. -4 -5 -6 -7 -8 +1=.
_r1 = _stk.slot2 - 2;

//  +0 = #6                                   ; -1=# -2 -3=. -4 -5 -6 -7 -8 +0=. +1=.
_r0 = _primitive_fib_label6;

//#line 11
//  if (##fx< +1 '2) jump 8 #5 else #3        ; -1=# -2 -3=. -4 -5 -6 -7 -8 +0=. +1=.
return (_r1 < 2) ? _primitive_fib_label5 : _primitive_fib_label3;
}

//#5 0                                        ; +0=# +1=n
function _primitive_fib_label5()
{

//#line 12
//  jump 0 +0                                 ; +1=.
return _r0;
}

//#line 14
//#6 8 return-point                           ; -1=# -2 -3=. -4 -5 -6 -7 -8 +1=.
function _primitive_fib_label6()
{
var _stk = _stack;

//#line 13
//  +1 = (##fx+ -3 +1)                        ; -1=# -2 -3 -4 -5 -6 -7 -8 +1=.
_r1 = _stk.slot3 + _r1;

//  jump* 8 #7                                ; -1=# -2 -3 -4 -5 -6 -7 -8 +1=.
//#7 8                                        ; -1=# -2 -3 -4 -5 -6 -7 -8 +1=.
//  jump 0 -1                                 ; +1=.
_stack = _stk.parent; // pop frame
return _stk.slot1;
}

function _primitive_println()
{
if (_nargs !== 1) error("wrong number of arguments");

print(_r1);

return _r0;
}

function main()
{
  var pc;

  pc = _primitive_fib_o1;
  _nargs = 0;
  _r0 = null;

  while (pc !== null)
    pc = pc();
}

main();




More information about the Gambit-list mailing list