[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:"
http://www2.parc.com/spl/groups/eca/pubs/papers/Lamping-IMSA92/for-web.pdf
"What a Metaobject Protocol Based Compiler Can Do For Lisp:"
http://www2.parc.com/csl/groups/sda/publications/papers/Kiczales-MOPs-for-Lisp/for-web.pdf
> 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
versions.
>> ;; 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:
thing.parenscriptUser_property
I think this is the correct behavior, but it is confusing. A solution
is to introduce a "global" package that compiles without identifier
prefixes:
(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)
`(progn
(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
stuck.
Red
More information about the parenscript-devel
mailing list