It could be a useful piece as part of a mechanism to allow end-users to have some sort of client-side scripting on their journal.
Here's the S2 file I was coding with. It tests a few things, but definitely not everything.
layerinfo "type" = "layout"; property int test_prop { des = "Stuff"; min = 5; max = 50; } property string string_prop { } class Sample { var int a; } class Child extends Sample { var int b; function new_stuff; } function function(string a1, int a2) { """testing $a1 and $a2"""; } function function(string c): int """ function overloading AND identifier overloading. exciting. """ { return 3*size $c; } function function(string{} d) { print size $d; } function function(string{}[]{} e, int[]{}[] f):int[]{} { print "yeah whateva."; return { "a" => [ 0, 1], "b" => [2,3] }; } function Child::new_stuff """ doc stuff. PH34R. (totally discarded for now.)""" { print "in new_stuff"; print "a = $.a and b= $.b"; } function Sample::lay_doStuff(int a, int b):string { return "SAMPLE:blah=["+$a+","+$b+"];"; } function Child::lay_doStuff(int a, int b):string { return "CHILD:blah=["+$a+","+$b+"];"; } function string::lay_len():int { "computing size of $this :"; return size $this; } function test() { function("test", 0); var Sample s = new Child; foreach var int a (1..3) { foreach var int b (5..7) { print $a+$b; } } ""+$s.a; print $s->lay_doStuff(4,5); var Child t = new Child; $t.a=37; $t->new_stuff(); print function("test"); var string test = "Metal"; foreach var string j ($test) { "gimme a "+$j; } var bool T = true; print $T?"true":"false"; var int[] ar1 = [ 1, 2, 3]; var int[] ar2 = reverse $ar1; foreach $s.a ($ar2) { print "ar2 contains $s.a"; } var string{} ha1 = { "a" => "65", "b" => "66", "c" => "67" }; print "size of ha1 = "+size $ha1; foreach $test ($ha1) { print "ha1["+$test+"] = "+$ha1{$test}; } if (not $T) { "1"; } elseif (2==3) { "2"; } else { "3"; } function($ha1); print safe size function({"a"=>[{"b"=>"c"}]},[{"d"=>[1,2]}]); $*test_prop=3; $*string_prop ="Whatever"; print $*string_prop->lay_len(); }
And here is the resulting javascript for it:
// auto-generated Javascript code from input S2 code function $S2P_range(a,b) { var r=[]; for (var i=a;i<=b;i++) r[r.length]=i; return r; } function $S2P_keys(a) { var r=[]; for (var i in a) { r[r.length]=i; } return r; } function $S2P_print(s) { document.writeln(s.toString().split('<').join("<")); } var $S2G_PROPS = {}; $S2G_PROPS.test_prop = 0; $S2G_PROPS.string_prop = ""; $S2C_Sample = function($$null) { this.a = 0; }; $S2C_Child = function($$null) { this.b = 0; }; $S2C_Child.prototype = new $S2C_Sample(); $S2_function_string_int = function ($a1, $a2) { $S2P_print(("testing " + $a1 + " and " + $a2)); } $S2_function_string = function ($c) { return 3 * ($c).length; } $S2_function_string$H = function ($d) { $S2P_print(($S2P_keys($d)).length); } $S2_function_string$H$A$H_int$A$H$A = function ($e, $f) { $S2P_print("yeah whateva."); return { "a" : [ 0, 1, ], "b" : [ 2, 3, ], }; } $S2C_Child.prototype.$S2_new_stuff = function () { $S2P_print("in new_stuff"); $S2P_print(("a = " + this.a + " and b= " + this.b)); } $S2C_Sample.prototype.$S2_lay_doStuff_int_int = function ($a, $b) { return "SAMPLE:blah=[" + $a + "," + $b + "];"; } $S2C_Child.prototype.$S2_lay_doStuff_int_int = function ($a, $b) { return "CHILD:blah=[" + $a + "," + $b + "];"; } String.prototype.$S2_lay_len = function () { $S2P_print(("computing size of " + this + " :")); return (this).length; } $S2_test = function () { $S2_function_string_int("test", 0); var $s = new $S2C_Child(); var $$tmp1 = ($S2P_range(1, 3)); for (var $$tmp2=0; $$tmp2<$$tmp1.length;$$tmp2++) { var $a = $$tmp1[$$tmp2]; var $$tmp3 = ($S2P_range(5, 7)); for (var $$tmp4=0; $$tmp4<$$tmp3.length;$$tmp4++) { var $b = $$tmp3[$$tmp4]; $S2P_print($a + $b); } } $S2P_print("" + $s.a); $S2P_print($s.$S2_lay_doStuff_int_int(4, 5)); var $t = new $S2C_Child(); $t.a = 37; $t.$S2_new_stuff(); $S2P_print($S2_function_string("test")); var $test = "Metal"; var $$tmp5 = ($test).split(''); for (var $$tmp6=0; $$tmp6<$$tmp5.length;$$tmp6++) { var $j = $$tmp5[$$tmp6]; $S2P_print("gimme a " + $j); } var $T = 1; $S2P_print(($T ? "true" : "false")); var $ar1 = [ 1, 2, 3, ]; var $ar2 = ($ar1).reverse(); var $$tmp7 = ($ar2); for (var $$tmp8=0; $$tmp8<$$tmp7.length;$$tmp8++) { $s.a = $$tmp7[$$tmp8]; $S2P_print(("ar2 contains " + $s.a)); } var $ha1 = { "a" : "65", "b" : "66", "c" : "67", }; $S2P_print("size of ha1 = " + ($S2P_keys($ha1)).length); for ($test in $ha1) { $S2P_print("ha1[" + $test + "] = " + $ha1[$test]); } if (! $T) { $S2P_print("1"); } else if (2 == 3) { $S2P_print("2"); } else { $S2P_print("3"); } $S2_function_string$H($ha1); $S2P_print(($S2P_keys($S2_function_string$H$A$H_int$A$H$A({ "a" : [ { "b" : "c", }, ], }, [ { "d" : [ 1, 2, ], }, ]))).length); $S2G_PROPS.test_prop = 3; $S2G_PROPS.string_prop = "Whatever"; $S2P_print($S2G_PROPS.string_prop.$S2_lay_len()); } // end.
A few notes in no particular order:
- the resulting javascript seems to parse and run correctly.
- one S2 object = one javascript object. This seems to work so far.
- prototyping is used as the mechanism to resolve S2 class inheritance
- there isn't a good equivalent for foreach in javascript, so 2 times out of 3, this gets implemented with a for(;;) and a couple of temporary variables.
- some S2 concept are not very relevant on the client-side, so property support is minimal, and things like builtins and readonly are non-existent.
- the current implementation is alpha and has many rough edges, just to set expectations a bit.
This would need some additional methods to allow safe outputing of html (right now, printing won't let any html through.), and some hooks into the javascript event model before starting to be useful.
Alrighty, flame away.