On 2010-11-23, at 7:22 AM, Oleg Parashchenko wrote:
Hello Marc,
On Mon, 22 Nov 2010 14:10:46 -0500 Marc Feeley feeley@iro.umontreal.ca wrote:
...
I checked PHP, which I wasn't very familiar with, and it seems to have a similar syntax (in the sense of "program structure") as JavaScript. In particular they both have closures and GC, and don't have tail calls.
PHP made me a nasty surprise, I did not expect that a popular language implemented closures only recently:
http://stackoverflow.com/questions/4155254/anonymous-functions-lambdas-closu... `` Some changes have been made starting with PHP 5.3, but even there you don't have your expected variable scopes that would allow you to do what you have in your examples. ''
By the way, this is the reason why I stopped with CPSCM: this interesting project relies on the host language for implementing closures.
Sorry, I wasn't clear. The important thing is to have first-class functions (they don't have to be closures). You can "fake" closures by creating your own "closure" structure which contains the function and its free variables. That works because only the code generated by the compiler will call these fake closures, so it can implement a closure calling protocol (which passes a "self" parameter). In addition, if you want to make Scheme functions easily callable from PHP and vice-versa, you can wrap these "closure" structures with PHP's create_function. Unfortunately, PHP doesn't GC functions, so this is not a perfect solution.
So if you start writing a back-end, I suggest that you supports both languages. In fact, you could support other target languages with similar properties (including Python, Ruby, elisp, ...). It should be easy to abstract the superficial differences between these languages in the "code generator" of the back-end.
The idea is great, but right now I'm not the right person who is able to make such abstraction.
The abstraction I'm talking about is at the level of the syntax. For example, when an "if" needs to be generated for PHP, JavaScript and many other languages, the syntax "if (<test>) <true_branch> else <false_branch>" can be used (possibly with extra braces in the branches to avoid ambiguities). On the other hand, to generate a reference to the variable "x" in PHP you need to generate "$x" whereas in JavaScript and many other languages "x" is sufficient. So the abstractions of these code generators would go something like this:
(define (gen-if targ test true-branch false-branch) (string-append "if (" test ") " true-branch " else " false-branch))
(define (gen-ref targ var) (case (target-name targ) ((php) (string-append "$" var)) (else var)))
There's not much more to it than that! Note that for simplicity I used strings here. That's not particularly efficient because strings are repeatedly recopied by the string-append. It is better to build the resulting code with lists or vectors and use the "print" function to output the text (the print function prints each element, without the parentheses, spaces, etc). For example:
(define (gen-if targ test true-branch false-branch) (vector "if (" test ") " true-branch " else " false-branch))
(define (gen-ref targ var) (case (target-name targ) ((php) (vector "$" var)) (else var)))
(print (gen-if 'dummy "A" "B;" (gen-if 'dummy "C" "D;" "E;")))
;; outputs: if (A) B; else if (C) D; else E;
Marc