[parenscript-devel] Proposal: Package System

Red Daly reddaly at stanford.edu
Sat Jun 30 18:34:34 UTC 2007

Please read on for my plea for help formalizing the semantics of 
Parenscript identifiers.

John Fremlin wrote:
> ...
> Perhaps compiler macros (or something more powerful like SBCL's
> deftransform) could be included?
I am not intimately familiar with either of these features, though I 
would appreciate an explanation.

I am certainly interested in opening up and advancing the compilation 
architecture.  Since I am not exactly a seasoned compiler programmer I 
do not know exactly how to do this effectively.  I have found a few 
articles about the subject:

"An Architecture for an Open Compiler:" 
"What a Metaobject Protocol Based Compiler Can Do For Lisp:" 

> I'd quite like the ability to delay the emission of JavaScript code,
> so that definitions can be emitted only when the call tree explicitly
> draws in a particular function or variable. I guess the information
> for these delayed definitions would belong in the compilation
> environment. (Maybe a later version ;-)
This certainly seems like a reasonable feature to include in future 
>> ;; enter the user package
>> ; changes current package in compilation environment
>> (in-package :parenscript-user)
> As Henrik said, some people might want to consider a ParenScript
> package to be JavaScript object. So that here one might emit
>            with (parenscript-user) {
>            ...
>            }
> (Just throwing out random ideas with complicated
> ramifications. Personally I prefer the prefixed name approach but some
> JavaScript megalibraries do stash everything in one object.)
> [...]
with() opens up a can of worms, but placing function/variable 
definitions into a single object is in the game plan.  Right now, while 
I try to get something working, I am using a strategy that prefixes 
variable names.

ATTN: I would like to request some help figuring out how exactly 
Parenscript identifiers will work.  A Parenscript identifier is exactly 
a lisp symbol.  Lisp symbols have associated Lisp packages.  Likewise, 
identifiers should have an associated Parenscript package.

There are two problems right now that make it unclear how to implement 
identifiers: (1) issues with serialization and (2) complications trying 
to map lisp symbols to Parenscript identifiers.

1.  Serialization-wise, it is unclear what the best semantics are for 
Parenscript identifiers sometimes.  Consider the following code:

(in-package :parenscript-user)
(slot-value thing 'property)

If identifiers are to be prefixed before compilation, then this may 
compile to something like:


I think this is the correct behavior, but it is confusing.  A solution 
is to introduce a "global" package that compiles without identifier 

(in-package :parenscript-user)
(slot-value thing 'global::property) ; => thing.property

Some syntax sugar might make this more manageable.  For example, using 
keywords instead of global symbols:

(in-package :parenscript-user)
(slot-value thing :property) ; => thing.property

If we go the other way and have quoted identifiers serialize without 
prefixes, we might end up with other confusing semantics:

(setf (slot-value maple 'tree:root) "sprawling.")
(setf (slot-value maple 'etymology:root) "Old English.")
(alert (slot-value maple 'tree-root)) ; expected: "sprawling"

This would be a confusing compilation:

maple.root = "sprawling"
maple.root = "Old English."
alert (maple.root)

2.  Determining the Parenscript package associated with a given Lisp 
symbol seems difficult.  This is as a result of the ability of Lisp 
packages to import symbols.  Here is the basic functionality for 
determining the Script package of a Lisp symbol:

(defun *lisp-to-paren-package-table* (make-hash-table)
   "Maps a lisp package to a script package.")

(defun lisp-to-paren-package (lisp-package)
   "Gets a script package corresponding to the given Lisp package."
   (gethash lisp-package *lisp-to-paren-package-table*))

(defun symbol-paren-package (symbol)
   "Gets the Parenscript package associated with a Lisp symbol."
   (lisp-to-paren-package (symbol-package symbol))

To me this could introduce some confusing circumstances when a Script 
package's Lisp package uses symbols from another package.  The most 
common are conflicts from the common-lisp package.  Imagine a 
Parenscript package "paren-psos" has a (defclass) macro--a symbol 
imported from common-lisp.  The standard "parenscript" package has many 
forms associated with (e.g. defvar, defun)

;; parenscript code: package definitions
(defpackage parenscript
   (:lisp-package :parenscript)
   (:second-lisp-packages :common-lisp))

(defpackage paren-psos
   (:lisp-package :paren-psos))

;; lisp code:
(in-package :parenscript)
(defjsmacro defhappyclass (name slots &rest options)
       (paren-psos:defclass ,name ,slots , at options)
       (parenscript:setf (slot-value happy-classes ,(string name)) ,name)))

The compiler will need to resolve the script package of the 
paren-psos:defclass symbol, but will run into problems if that lisp 
symbol is imported from the common-lisp package.  (In lisp, 
(symbol-package 'paren-psos:defclass) returns COMMON-LISP.)  It will end 
up thinking that defclass is an identifier from the "parenscript" script 
package.  This is confusing.  One way to get around it is to make 
paren-psos shadow some symbols from the packages it uses.  This might be 
sufficient, especially if we add compiler warnings when a parenscript 
macro is defined and the lisp package of its symbol is different from 
the current package.

Package resolution is not a problem using a separate Parenscript reader 
(in fact I have already done it), but using when defining Parenscript 
macros in Lisp we are confined to the standard Lisp reader.

Any thoughts on these two problems would be appreciated.  I am sort of 


More information about the parenscript-devel mailing list