On Sun, Apr 26, 2009 at 8:03 AM, Vladimir Sedach <vsedach@gmail.com> wrote:
Hi Red,

> I have modified the behavior of keywords found in Parenscript source to be
> parsed into (PS-QUOTE keyword) instead of (JS-VARIABLE keyword).

The current behavior is (ps::compile-parenscript-form :baz) => :baz
(there's no quoting involved). The printer then outputs keyword
symbols as strings, since this is the closest analogue (a
self-evaluating object) to keywords among the native JavaScript
objects.

It appears that I had an old version.  I was using the darcs repo instead of the git repo.  There must have been a lot of changes as of August! (ps:ps :foo) used to output a variable reference to foo.

Nonetheless, here is a bug with the current implementation:

CL-USER>
(setf (ps:PS-PACKAGE-PREFIX :cl-user) "CL_USER_")
CL-USER> (ps:ps                                                                                                                                                                                                   
           (let* ((some-prop 'foo-sym)                                                                                              
                  (my-object (ps:create 'foo-sym "value!")))                                                                                   
             (slot-value my-object 'foo-sym)))                                                                                           
            
"var CL_USER_someProp = 'foo-sym';                                                                                                           
var CL_USER_myObject = { 'foo-sym' : 'value!' };                                                                                 
CL_USER_myObject.CL_USER_fooSym;"

The expected behavior would be for the (create ...) form to reference the same value as the (slot-value ...) form.

If there were any sort of Parenscript runtime, it would be easy to make a data structure for symbols.  For example, the above code could translate to something like...

function Symbol(string, prefix) {
  this.string = string;
  this.prefix = prefix;
  // .. add to symbol table, etc.
}
Symbol.prototype.toString = function() { if (this.prefix) return this.prefix + "::" + this.string; else return this.string; }
var someProp_symbol = new Symbol("someProp", "CL_USER");

var CL_USER_someProp = someProp_symbol;                                                                                                           
var CL_USER_myObject = { someProp_symbol : 'value!' };                                                                                 
CL_USER_myObject[someProp_symbol];

This would differentiate symbols and strings, and it would result in pointer comparisons between symbols, just as in lisp.

I understand the current approach is to avoid any runtime, but the runtime solution does seem like less of a hack in the end.

> This seems
> to make more sense because in Lisp, evaluating a keyword yields the keyword
> itself rather than the value bound to it.  As a result, the ability to paass
> keyword arguments to functions is now restored.
>
> CL-USER> (ps:ps (foo "bar" :quix "quo" :etc "etc..."))
> "foo('bar', { quix : 'quo', etc : 'etc...' });"
>
> Whereas this used to yield foo('bar', quix, 'quo', etc, 'etc...')

This is actually a fix to keyword argument handling: previously the PS
lambda-list handling code assumed that whenever it encountered a
keyword in the arglist of a function, it was the beginning of the
keyword portion of the lambda list, and started making the object at
that point. This of course may not be the case if you are trying to
use keywords as arguments to a function. With keywords compiled to
strings, you get self-evaluating objects and can do keyword handling
in the function body at runtime (which is what the current code does).

I see the latest implementation now processes keyword arguments differently, eliminating the old hash table approach.  This seems like an okay solution, but I suspect it adds a a little overhead for each call to a function with keyword arguments.

I also noticed a bug that resulted in improper handling of the following case:
(ps:ps                                                                                                                                                                                                   
           (defun hello-world (&key ((my-name-key my-name)))                                                    
             (print "hello, " + my-name))                                                                              
           (hello-world 'my-name-key "fred"))
                                                                                                                                                      
"function CL_USER_helloWorld() {                                                                                                                                                                                  
    var CL_USER_myName;                                                                                                                                             
    var _js54 = arguments.length;                                                                                                                           
    for (var n52 = 0; n52 < _js54; n52 += 2) {                                                                               
        switch (arguments[n52]) {                                                                                  
        case CL_USER_myNameKey:                                                                                                       
            {                                                                                                                             
                CL_USER_myName = arguments[n52 + 1];                                                                            
            };                                                                                                                                                                                                    
        };                                                                                                                                                                                                        
    };                                                                                                                                                                                                            
    if (CL_USER_myName === undefined) {                                                                                                     
        CL_USER_myName = null;                                                                                                    
    };                                                                                                             
    print('hello, ', plus, CL_USER_myName);                                                                                                                                                                       
};                                                                                                                                                                                                                
CL_USER_helloWorld('my-name-key', 'fred');"

the javascript should really use the following case:  case 'myNameKey' instead of case CL_USER_myNameKey.  a patch is attached


All the best,
Red



Thanks,
Vladimir

> In general, symbols occupy a strange place in Parenscript.  Javascript has
> no analogue of Lisp symbols, so there is no sensible translation of symbols
> that works for everyone.  Nonetheless, quoted symbols are used in many
> Parenscript macros to fake having real symbols in javascript.  We could
> build in the ability to translate symbols to some javascript form, e.g.
>
> (ps:ps (make-instance 'animal)) =>  makeInstance( symbolTable["ANIMAL"] )
>
> The latter part of this post is just food for thought.  I will go ahead and
> commit the patch for the former part of this post unless someone objects.
>
> Red
>
> _______________________________________________
> parenscript-devel mailing list
> parenscript-devel@common-lisp.net
> http://common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel
>
>

_______________________________________________
parenscript-devel mailing list
parenscript-devel@common-lisp.net
http://common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel