[parenscript-devel] ps-symbols (was Re: Conflict with % between Parenscript and CSS-Lite)

Vladimir Sedach vsedach at gmail.com
Sun Dec 7 21:33:13 UTC 2008

The issue here is what exactly do we want "Parenscript code" to be.
Right now Parenscript compilation looks like the following:

text (s-exp) --[CL reader]--> CL code (lists) --[PS compiler]-->
internal PS representation --[PS printer]--> text (JS)

By virtue of using the CL reader, we get Parenscript code that is also
Common Lisp code.

To introduce a PS package system and code representation, there are
two alternatives that I see:

1. text (s-exp) --[PS reader]--> PS code (CLOS objects?) --[PS
compiler]--> internal PS representation --[PS printer]--> text (JS)

2. text (s-exp) --[CL reader]--> CL code (lists) --[PS code
transformer]--> PS code (CLOS objects?) --[PS compiler]--> internal PS
representation --[PS printer]--> text (JS)

With 1, you lose the ability to transparently embed PS code in CL code
and vice-versa, and the ability to use all the CL macrology tools that
work on the assumption that your code is made up of lists and symbols.
With 2 you have to introduce some kind of external annotation
mechanism to provide the necessary information for transforming Lisp
symbols to Parenscript symbols, and assuming PS macros will continue
to operate on the CL code level, you'll still have to deal with CL

In practice I find that the most powerful aspect of Parenscript is
that PS code is CL code. I think that "Parenscript code is CL code"
needs to become a definition of the project. I don't see how any
benefits from a separate package system could be worth more than this.

> As a user of the PS compiler, I would expect that simply calling the PS
> compiler interface with syntactically correct PS code should produce
> correct JS output.  But it doesn't unless I import/use all the possible
> PS specials.  Simple example:
> cl-user> (require 'parenscript)
> cl-user> (ps:ps (new foo))
> "foo;" ;; wrong

This is an excellent argument for why using the CL package system is a
good idea. The behavior in this example had me stumped until I
discovered that the operator precedence mechanism strips the package
information from symbols! This is really a bug that makes the behavior
of Parenscript inconsistent with that of the CL package system (I've
pushed a fix). That was the surprise from my point of view.

The real issue behind this example is actually how do we handle a
small amount of reserved JavaScript keywords in Parenscript. Should
the symbol with the name "NEW" be treated as the JS operator no matter
which package it is in? Then the mental model of Parenscript code
becomes "PS symbols are just like CL symbols except for these reserved
JS keywords, and they get name-mangled and (unless otherwise
specified) stripped of package information when output," which
eliminates the surprise factor.

> The reason for this is simple really.  The PS/JS code has a different
> 'context' than the code in the lisp system.  The context for CL code is
> defined by the CL package system and lexical scoping rules -- the CL
> compiler.  The context for the JS output of PS, and hence for the PS
> code itself, is defined by how the output JS files are loaded into the
> browser.  If I compile:
> (in-package :foo)
> (output-ps-to-browser ;; made-up lisp function
>   (ps (defvar a))
> (in-package :bar)
> (output-ps-to-browser
>   (ps (let ((a 1))
>         (incf a))))
> Then the output will be subtly broken.  The variable 'a' should be
> treated by PS as special/global in BAR as well as FOO.  There should be
> a way to communicate to PS that both instances of JS output are going to
> be evaluated together -- that they should be treated in the same
> context.  CL packages are a lousy way to do this.  The CL package
> approach encourages the user (once they run head-on into these surprises
> a few times) to write all of the PS code for their application from a
> single CL package.  This discourages useful ways of emitting JS via PS
> from various places in one's application and libraries.

The behavior you describe here would ensure that the code would behave
differently in CL than it does in PS. I don't think we need a separate
package system to provide a compilation/loading context facility.


> I believe this is why ps-symbols keep getting introduced into the
> library -- using the CL package system for PS causes subtle and
> surprising behavior.  There are definitely improvements that we can make
> to the ps-symbol approach, but I believe it is a better basis from which
> to work.
> Cheers,
> -- Travis
> _______________________________________________
> parenscript-devel mailing list
> parenscript-devel at common-lisp.net
> http://common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel

More information about the parenscript-devel mailing list