- a simpler ecmascript/javascript syntax. ecmascript written as scheme-like s-expressions
- the output, after formatting, is supposed to be as if originally written in ecmascript
- supports all es5
- command-line compiler and scheme library
- possibly also useful as an intermediate language for applications that want to compile to ecmascript
- status: should work, been around for a while, easy to maintain and extend
- license: gpl3+. does not apply to generated code. generated code has your license
- you can try it out here
echo "(define (test x y) (return #t))" | ses
->
function test(x, y){return(true)};
(declare d e f)
(define myobject
(object
a 1
b (object c 2)))
(set
d 1
e 3
f 9)
myobject.a.b
(get myobject "a" "b")
(get myarray 0 1)
- adds return statement to the last expression in a function. lambda just feels wrong without this behaviour
- let, let*
$ ses --help
parameters
options ... paths ...
description
compile sescript to ecmascript. read from files or standard input,
and write to a file or standard output depending on if paths are given as arguments.
input/output depends on the number of given paths:
none: read from standard input and write to standard output
one: read from file and write to standard output
two: read from the first file and write to the second
more: read from all files except the last one and write to the last one
options
--compress | -c compress output with uglifyjs
--format | -f format output with uglifyjs
--help | -h
--interface
run the install script, "./exe/install". it supports one optional argument, an install path prefix.
alternatively
- copy everything under modules/ into a directory that is in guiles default load path or $GUILE_LOAD_PATH
- copy exe/ses to /usr/bin or wherever executables are to be installed
try to run ses --help
to see if it works
(import (sph lang sescript))
examples
(sescript->ecmascript-string (quote (begin (define a 1) (set a 2))))
(sescript->ecmascript (quote ((define a 1) (set a 2))) (current-output-port))
(define scheme-value 8)
(define code
(quasiquote
(begin
(define a 1)
(set a (unquote scheme-value)))))
(sescript->ecmascript-string code)
how to add your own syntax: this is currently only possible when compiling with scheme and not via the sescript command-line interface. create a scheme file with new bindings, example below, and then use sescript->ecmascript-string or similar as usual
(import (sph lang sescript) (rnrs hashtables))
(hashtable-set! ses-descend-sescript (quote myprefix)
(lambda (a compile)
"(any:sescript-argument ...) procedure:recurse -> any:sescript
create sescript that will be parsed again"
(list (quote if) (car a) #t #f)))
(hashtable-set! ses-descend-ecmascript (quote myprefix2)
(lambda (a compile)
"(any:sescript-argument ...) procedure:recurse -> string:ecmascript
create final ecmascript strings directly"
(string-join (map compile a) "\n")))
(define code (quote (myprefix "test")))
(sescript->ecmascript-string code)
- filename extension .sjs or .ses
- --format and --compress option on the command-line if uglifyjs is installed
- js-beautify is another recommended auto formatter
- sescript only outputs valid ecmascript syntax
- a benefit of using sescript is that editor modes for scheme syntax and structural editing can be used
- other languages that compile to javascript
ses expression and the ecmascript result. taken from the automated tests
(array #\a)
->
["a"];
(array "\"")
->
["\""];
(array #t)
->
[true];
(begin a->b a-b a! a& a?)
->
a_to_b;a_b;a_x;a_ampersand;a_p;
(case a ((b c d) #t))
->
switch(a){case b:case c:case d:true;break};
(begin 1 a #t #\a "1")
->
1;a;true;"a";"1";
(begin 1 (begin 2 3))
->
1;2;3;
(case (+ 1 2) (2 #t #f) (3 #t) (else 4 5))
->
switch(1+2){case 2:true;false;break;case 3:true;break;default:4;5;break};
(= 1 2 3)
->
(1===2)&&(2===3);
(and 1 2 3)
->
(1&&2&&3);
(array 1 2 3)
->
[1,2,3];
(chain c (chain a b) 1 2 "d")
->
b.a().c(1,2,"d");
(cond (a b) ((= c 3) #f #t) (else #t #f))
->
if(a){b}else if(c===3){false;true;}else{true;false;};
(cond (a b))
->
if(a){b};
(declare a)
->
var a;
(declare a b c)
->
var a,b,c;
(define a 1)
->
var a=1;
(define a 1 b 2)
->
var a=1,b=2;
(define a (lambda (a b) 1 2 3))
->
var a=(function(a,b){1;2;return(3);});
(define (a b c-d) 1 2 3)
->
function a(b,c_d){1;2;return(3);};
(for ((set index 0) (< index len) (set index (+ 1 index))) #t)
->
for(index=0;(index<len);index=(1+index)){true};
(for (((set a 0) (set b 1)) (< index len) ((set a (+ 1 a)) (set b (+ 2 b)))) #t)
->
for(a=0,b=1;(index<len);a=(1+a),b=(2+b)){true};
(for ((begin a b) (< c d) (begin e f)) #t)
->
for(a,b;(c<d);e,f){true};
(get a 1)
->
a[1];
(get a 1 2 3)
->
a[1][2][3];
(get (get a 1) 2)
->
a[1][2];
(if* a (if* b c d) e)
->
(a?(b?c:d):e);
(if* a (if* (if* b c) d) e)
->
(a?((b?c:undefined)?d:undefined):e);
(if* 1 (lambda () #t) 2)
->
(1?(function(){return(true)}):2);
(if* (not 1) a b)
->
(!1?a:b);
(lambda (a) 1)
->
(function(a){return(1)});
(lambda () (if* a b c))
->
(function(){return(a?b:c)});
((lambda (a) 1))
->
(function(a){return(1)})();
(let (a 1) 2)
->
(function(a){return(2)})(1);
(let ((a 1) (b 2)) #t)
->
(function(a,b){return(true)})(1,2);
(let* ((a 1) (b 2) (c 3)) 4)
->
(function(a){var b=2;var c=3;return(4);})(1);
(make-regexp "[^a-b0-9]" "g")
->
/[^a-b0-9]/g;
(new obj)
->
new obj();
(new obj 3 5)
->
new obj(3,5);
(not 1)
->
!1;
(object)
->
{};
(object a 2 b-c 3 "d" 4)
->
{a:2,b_c:3,"d":4};
(object* a b c)
->
{a:a,b:b,c:c};
(return)
->
return;
(return 1 2)
->
return(1,2);
(ses-comment "test" "comment")
->
/* test
comment */
(ses-insert "var a = 3")
->
var a = 3;
(set a 1)
->
a=1;
(set a 1 b 2 c 3)
->
a=1;b=2;c=3;
- support docstrings as is already implemented in sc
- port the macro system from sc
- es6 syntax: support new syntax (class, string templates, default parameters, object destructuring, async/await, import/export, const, let) and/or replace old syntax with new one (arrow functions for lambdas, still need a way to use the function keyword, coffeescript has -> => for that)
- translate scheme comments. scheme comments dont appear in the output, only
(ses-comment "comment string")
or ses-insert can be used. could use guile-reader but because that is a difficult to handle dependency it might be better to preprocess and replace all comments with ses-comment expressions - add a command-line option to load custom syntax extensions from a file
- more syntax checks and error messages