Hey guys,
I'm thinking about a product I want to develop in the future, and I think a crucial point will be to convince non-Scheme developers to use it, and possibly convert them to Scheme programmers. I want to include a "scripting" language in my product which has the syntax of Javascript. I want to compile this language to Scheme.
This is exactly what SIX does in Gambit, but SIX doesn't quite have the grammar I want and is incomplete (I think "return" does nothing?).
Is anyone else interested in working on this? I need to look at the SIX compiler in Gambit. I could either extend it, or write a parser from scratch using something like SILex. I love the idea of SIX (including a built-in infix grammar), but is it used anywhere? Is anyone interested in improving SIX to make it more usable as an actual language?
- James
Afficher les réponses par date
Hi James
On Mon, 22 Mar 2010 16:30:56 -0400 James Long longster@gmail.com wrote:
I'm thinking about a product I want to develop in the future, and I think a crucial point will be to convince non-Scheme developers to use it, and possibly convert them to Scheme programmers. I want to include a "scripting" language in my product which has the syntax of Javascript. I want to compile this language to Scheme.
This is exactly what SIX does in Gambit, but SIX doesn't quite have the grammar I want and is incomplete (I think "return" does nothing?).
Is anyone else interested in working on this? I need to look at the SIX compiler in Gambit. I could either extend it, or write a parser from scratch using something like SILex. I love the idea of SIX (including a built-in infix grammar), but is it used anywhere? Is anyone interested in improving SIX to make it more usable as an actual language?
Not directly related, but an alternative approach would be something like http://chicken.wiki.br/eggref/3/lua (i.e., embedding an implementation of a non-parenthesis-oriented-syntax language into your application and binding it to Gambit).
Best wishes. Mario
On Mon, Mar 22, 2010 at 4:38 PM, Mario Domenech Goulart < mario.goulart@gmail.com> wrote:
Not directly related, but an alternative approach would be something like http://chicken.wiki.br/eggref/3/lua (i.e., embedding an implementation of a non-parenthesis-oriented-syntax language into your application and binding it to Gambit).
That would work, but it would really be nice to avoid having two of everything (garbage collectors, VMs, etc.) and embedding another interpreter into an already dynamic language. I just want to compile a basic syntax into sexprs, and not even implement a lot of the Javascript runtime (like prototypes) and just rely on Scheme.
On Mon, Mar 22, 2010 at 4:41 PM, Marc Feeley feeley@iro.umontreal.ca wrote:
I looked around and apparently there is a PLT package which implements a JavaScript parser and evaluator. Maybe that would be a good starting point.
I saw the PLT package too. That might be a good package to start with. Are you interested in working on this soon?
On Mon, Mar 22, 2010 at 4:46 PM, Grant Rettke grettke@acm.org wrote:
http://wingolog.org/archives/2009/02/22/ecmascript-for-guile
Thanks Grantt, I hadn't seen that one. I'll poke around it.
On 2010-03-22, at 4:30 PM, James Long wrote:
Hey guys,
I'm thinking about a product I want to develop in the future, and I think a crucial point will be to convince non-Scheme developers to use it, and possibly convert them to Scheme programmers. I want to include a "scripting" language in my product which has the syntax of Javascript. I want to compile this language to Scheme.
This is exactly what SIX does in Gambit, but SIX doesn't quite have the grammar I want and is incomplete (I think "return" does nothing?).
Is anyone else interested in working on this? I need to look at the SIX compiler in Gambit. I could either extend it, or write a parser from scratch using something like SILex. I love the idea of SIX (including a built-in infix grammar), but is it used anywhere? Is anyone interested in improving SIX to make it more usable as an actual language?
Funny you ask! I'm interested in implementing a JavaScript parser generating S-expressions as AST. By writing appropriate macros for the nodes of the AST, the semantics of JavaScript could be implemented (or by a simple code-walker if macros are not powerful enough). I looked around and apparently there is a PLT package which implements a JavaScript parser and evaluator. Maybe that would be a good starting point.
Marc
On Mon, Mar 22, 2010 at 3:30 PM, James Long longster@gmail.com wrote:
I'm thinking about a product I want to develop in the future, and I think a crucial point will be to convince non-Scheme developers to use it, and possibly convert them to Scheme programmers. I want to include a "scripting" language in my product which has the syntax of Javascript.
http://wingolog.org/archives/2009/02/22/ecmascript-for-guile
Hi James,
On Mon, Mar 22, 2010 at 8:30 PM, James Long longster@gmail.com wrote:
Is anyone else interested in working on this?
I've kicking a similar idea around for a while; I'd like to help.
What I've been thinking of is basically a parser for a nearly-JS syntax that generated s-expressions targeting some lightweight macro layer. Where JS and Scheme semantics or runtime environments diverged, it'd be fine to use Scheme's. Instead of implementing a JS interpreter, it'd be a JS-like syntax for the Scheme interpreter.
For example:
function adder(n) { return function(a) { return n + a; } }
Could be parsed into something like:
(function adder (n) (function #f (a) (+ n a)))
And with the aid of something like:
(define-macro (function name params . body) (if name `(define ,name (function #f ,params ,@body)) `(lambda ,params ,@body)))
Get something like:
(define adder (lambda (n) (lambda (a) (+ n a ))))
If you've got something different in mind, I'd be up for helping anyway. I think a JS syntax for Scheme is a great way to introduce people to Scheme that wouldn't be interested otherwise.
Thanks,
-Ben
Hi,
Just to shed light on some of the potential pitfalls that I see could arise in this kind of project:
22 mar 2010 kl. 23.11 Ben Weaver wrote:
What I've been thinking of is basically a parser for a nearly-JS syntax that generated s-expressions targeting some lightweight macro layer. Where JS and Scheme semantics or runtime environments diverged, it'd be fine to use Scheme's. Instead of implementing a JS interpreter, it'd be a JS-like syntax for the Scheme interpreter.
For example:
function adder(n) { return function(a) { return n + a; } }
Could be parsed into something like:
(function adder (n) (function #f (a) (+ n a)))
I don't think it's trivial to parse like that if you want return statements to behave like they do in C-like languages. You'd have to parse to
(function adder (n) (return (function #f (a) (return (+ n a))))
which would compile into something like
(define adder (lambda (n) (call/cc (lambda (return) (return (lambda (a) (call/cc (lambda (return) (return (+ n a))))))))))
Otherwise return wouldn't be able to exit in the middle of a function call, which would destroy the purpose of having the keyword at all, and only confuse people who expect it to work like it does in C. Of course, it's possible to compile away most call/cc invocations, but that's not completely trivial to do.
And with the aid of something like:
(define-macro (function name params . body) (if name `(define ,name (function #f ,params ,@body)) `(lambda ,params ,@body)))
Get something like:
(define adder (lambda (n) (lambda (a) (+ n a ))))
I would strongly recommend to be careful with expanding to define forms. IME define forms are one of the more fragile parts of Scheme, and when you push it to its limits it doesn't really behave like you'd expect it to. Something as simple as
function() { function a() { return "a"; } document.write(a()); function b() { return "b"; } return b(); }
wouldn't work, because the definition of b is after the document.write expression. The kind of code in the previous example, where you mix function definitions and expressions, is very common in Javascript and is crucial to be able to write good-looking and idiomatic code. I would consider expanding it to let forms instead, as in
(lambda () (call/cc (lambda (return) (let ((a (lambda () (call/cc (lambda (return) (return "a")))))) (document.write (a)) (let ((b (lambda () (call/cc (lambda (return) (return "b")))))) (return (b))))))))
This would result in different scoping rules than Javascript, though, since this is valid Javascript:
function () { a = 5; // Set a to be 5 var a; // Define that a is a local variable. It doesn't matter where this declaration is, as long as it is inside of this scope (in this case the function) return a; }
(You can of course argue that these scoping rules of Javascript are a mistake and/or historical cruft) Overall, I would be really careful in the design phase of this piece of software, and I would not expect the code transformation to be trivial unless you can live with having a very leaky abstraction. But that would ruin most of the point of convincing newbies to write Scheme.
Also, I would study the implications of the differences between the basic data structure of Scheme and Javascript, and their implications for writing everyday code. Scheme's core type is the cons cell. Javascript's core datatype is the hashtable. This does not only have implications to how you should try to write a compiler that generates efficient code. I believe that Javascript's syntax is designed to be good at manipulating hash tables, while Scheme's syntax is designed to be good at manipulating lists. Even if you'd write a good Javascript to Scheme interpreter/compiler, it would still be difficult to integrate good Javascript code with good Lisp, because idiomatic and beautiful Javascript uses hash tables in a way that would be clunky and stupid to do in Scheme, just like good Scheme code uses lists in a way that would be stupid to do in JS.
It is true that Javascript's semantics are very similar to Scheme's, but the fact that Javascript primarily manipulates hash tables combined with its syntax makes Javascript code surprisingly different to Scheme code doing the same thing. The problem is, as soon as you move away from having lists as a core data structure you will also go away from recursion as a such natural tool and many of the other characteristics of Lisp. But if you stay with lists as a core data structure, a C-like syntax will be horribly clunky.
I hope that this will help you to avoid some of the mistakes that I have made in related projects.
Good luck!
/Per
On Mon, Mar 22, 2010 at 6:11 PM, Ben Weaver ben@orangesoda.net wrote:
What I've been thinking of is basically a parser for a nearly-JS syntax that
generated s-expressions targeting some lightweight macro layer. Where JS and Scheme semantics or runtime environments diverged, it'd be fine to use Scheme's. Instead of implementing a JS interpreter, it'd be a JS-like syntax for the Scheme interpreter.
Yep, that's exactly what I was thinking. It might require a little more than a lightweight macro layer, though. I would like to translate "return" statements into calls to continuations, and make sure the code flow is as expressive as javascript's. You are right in that there is little difficulty in mapping Javascript-like syntax to Scheme.
If you've got something different in mind, I'd be up for helping anyway. I
think a JS syntax for Scheme is a great way to introduce people to Scheme that wouldn't be interested otherwise.
Great! We should talk more about it soon. What do you think about lexers like SILex? Or maybe we can pull a Javascript parser from an existing library. It's tempting to try to write something from scratch though. I'll probably start doing some research over the next couple of weeks. (btw, I'll probably see you soon Ben in your office!)
- James
On Tue, Mar 23, 2010 at 12:07 AM, James Long longster@gmail.com wrote:
Yep, that's exactly what I was thinking. It might require a little more
than a lightweight macro layer, though. I would like to translate "return" statements into calls to continuations, and make sure the code flow is as expressive as javascript's.
You're right, we'd definitely need continuations to make return work (among the other things that Per pointed out ;-)
Great! We should talk more about it soon. What do you think about lexers like SILex?
Sounds good. I'd be up for trying SILex. The ecmascript-for-guile project seems worth looking into as well.
Talk to you soon,
-Ben
On 2010-03-22, at 11:41 PM, Ben Weaver wrote:
On Tue, Mar 23, 2010 at 12:07 AM, James Long longster@gmail.com wrote:
Yep, that's exactly what I was thinking. It might require a little more than a lightweight macro layer, though. I would like to translate "return" statements into calls to continuations, and make sure the code flow is as expressive as javascript's.
You're right, we'd definitely need continuations to make return work (among the other things that Per pointed out ;-)
Great! We should talk more about it soon. What do you think about lexers like SILex?
Sounds good. I'd be up for trying SILex. The ecmascript-for-guile project seems worth looking into as well.
I've started playing around with the Guile ecmascript parser. When using LALR-SCM I unfortunately get many parser generator errors (shift/reduce and reduce/reduce conflicts). I'm not sure how hard it is to fix.
Another approach would be to use OMeta (http://tinlizzie.org/ometa/), for which there is a Scheme version (http://www.lshift.net/blog/2008/07/01/ometa-for-scheme). The OMeta project includes a parser for JavaScript (http://www.tinlizzie.org/ometa-js/#JavaScript_Compiler) which basically produces S-expression based ASTs.
Here is an overview of OMeta: http://tinlizzie.org/ometa/dls07-slides.pdf .
Marc
I do like coffee-script. Basically, it's JavaScript, but properly defined.
I'm pretty sure that this would be 1/ no pain for JS users to use 2/ a lot more attractive
On the other hand, you are likely not to be able to use all previous JS libraries…
More at : http://jashkenas.github.com/coffee-script/
P!
Another approach would be to use OMeta (http://tinlizzie.org/ometa/), for which there is a Scheme version (http://www.lshift.net/blog/2008/07/01/ometa-for-scheme). The OMeta project includes a parser for JavaScript (http://www.tinlizzie.org/ometa-js/#JavaScript_Compiler) which basically produces S-expression based ASTs.