Below is a DEFUN-JS macro for defining PS functions at the Lisp top-level. It creates a Lisp stub with the same signature whose body simply throws an error telling you that you tried to call a PS function from Lisp. Why is that useful? Because now your PS functions are fully integrated with Slime. You can jump around with M-., get arglist info in the minibuffer, and so on.
After a week of using this, I can't believe how much of a difference it makes.
In PS, DEFUN-JS translates trivially to DEFUN. Of course you still need a way to collect the JS emitted by all these forms, but PS is agnostic on how that should be done.
A side note: we also converted nearly all our ps macros to DEFMACRO+PS forms at the toplevel. This has the neat property that you can now look at expansions using the highly convenient Slime macroexpand. I doubt that this is a perfect solution (no doubt you can trip yourself up on differences between the CL and PS macro environments), but it's sure handier than calling PS::PS-MACROEXPAND from the REPL.
Daniel
p.s. The following has been stripped of a couple of functions specific to our project. I tested it a bit, but if I missed anything, let me know.
(defmacro defun-js (name lambda-list &body body) (declare (ignore body)) (labels ((sym% (argspec) (if (symbolp argspec) argspec (car argspec)))) (multiple-value-bind (required optionals restp rest keyp keys allowp auxp aux morep more-context more-count beyond-requireds? key-object) (ps::parse-lambda-list lambda-list) (declare (ignore restp keyp allowp auxp aux morep more-context more-count beyond-requireds? key-object)) ;; get rid of init forms, which can't be evaluated in Lisp. (setf optionals (mapcar #'sym% optionals) keys (mapcar #'sym% keys)) `(defun ,name (,@required ,@(when optionals `(&optional ,@optionals)) ,@(when rest `(&rest ,rest)) ,@(when keys `(&key ,@keys))) (declare (ignore ,@required ,@optionals ,@(when rest (list rest)) ,@keys)) (error "The ~s function is js-only and cannot be called from Lisp." ',name)))))
(defpsmacro defun-js (name lambda-list &body body) `(defun ,name ,lambda-list ,@body))
That's a good way of doing things for now. I didn't realize DEFMACRO+PS could be used that way either.
The hypothetical Parenscript-SLIME is supposed to do this (and more). Andrey Moskvitin has a fork of SLIME that supports feature and protocol extensions (http://github.com/archimag/slime-archimag - strangely enough the current SLIME maintainers don't seem to be interested in things like protocol versioning) and I'm planning to see if I can do things like xref support for Parenscript forms there.
Vladimir
2010/6/17 Daniel Gackle danielgackle@gmail.com:
Below is a DEFUN-JS macro for defining PS functions at the Lisp top-level. It creates a Lisp stub with the same signature whose body simply throws an error telling you that you tried to call a PS function from Lisp. Why is that useful? Because now your PS functions are fully integrated with Slime. You can jump around with M-., get arglist info in the minibuffer, and so on. After a week of using this, I can't believe how much of a difference it makes. In PS, DEFUN-JS translates trivially to DEFUN. Of course you still need a way to collect the JS emitted by all these forms, but PS is agnostic on how that should be done. A side note: we also converted nearly all our ps macros to DEFMACRO+PS forms at the toplevel. This has the neat property that you can now look at expansions using the highly convenient Slime macroexpand. I doubt that this is a perfect solution (no doubt you can trip yourself up on differences between the CL and PS macro environments), but it's sure handier than calling PS::PS-MACROEXPAND from the REPL. Daniel p.s. The following has been stripped of a couple of functions specific to our project. I tested it a bit, but if I missed anything, let me know.
(defmacro defun-js (name lambda-list &body body) (declare (ignore body)) (labels ((sym% (argspec) (if (symbolp argspec) argspec (car argspec)))) (multiple-value-bind (required optionals restp rest keyp keys allowp auxp aux morep more-context more-count beyond-requireds? key-object) (ps::parse-lambda-list lambda-list) (declare (ignore restp keyp allowp auxp aux morep more-context more-count beyond-requireds? key-object)) ;; get rid of init forms, which can't be evaluated in Lisp. (setf optionals (mapcar #'sym% optionals) keys (mapcar #'sym% keys)) `(defun ,name (,@required ,@(when optionals `(&optional ,@optionals)) ,@(when rest `(&rest ,rest)) ,@(when keys `(&key ,@keys))) (declare (ignore ,@required ,@optionals ,@(when rest (list rest)) ,@keys)) (error "The ~s function is js-only and cannot be called from Lisp." ',name))))) (defpsmacro defun-js (name lambda-list &body body) `(defun ,name ,lambda-list ,@body)) _______________________________________________ parenscript-devel mailing list parenscript-devel@common-lisp.net http://common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel
I have a SLIME branch that extends slime to support almost the same features without the hack of defining a lisp stub for Parenscript functions. Missing is the xref support--if somebody could add this in it would be fantastic.
Unfortunately this code is for a rather old version of Parenscript because I am afraid of the recent changes breaking my non-unit-tested code. Nonetheless, you should be able to check out my version of Parenscript just to see how it works.
In any case, the branch of Parenscript and SLIME you will need are in my github account:
http://github.com/gonzojive/slime -- slime extension is pretty much up to date the the current SLIME. adds some extensions that let you plug Parenscript into slime's minibuffer completion. See http://github.com/gonzojive/slime/commit/40a84e1e5ea07f5068de61863bb00c22e7c... for the main diff
http://github.com/gonzojive/parenscript -- compatible version of Parenscript. See swank-parenscript.lisp and the compiler for how the hooks work. See http://github.com/gonzojive/parenscript/commit/5223c628d788750fa9ebac2682cf5... for the main diff that adds in SLIME support. Note I also added it for PSOS (see paren-psos repo)
Hope this helps the aspiring SLIME-Parenscripter. Kudos to the person who adds in xref support
Red
On Thu, Jun 17, 2010 at 1:03 PM, Vladimir Sedach vsedach@gmail.com wrote:
That's a good way of doing things for now. I didn't realize DEFMACRO+PS could be used that way either.
The hypothetical Parenscript-SLIME is supposed to do this (and more). Andrey Moskvitin has a fork of SLIME that supports feature and protocol extensions (http://github.com/archimag/slime-archimag - strangely enough the current SLIME maintainers don't seem to be interested in things like protocol versioning) and I'm planning to see if I can do things like xref support for Parenscript forms there.
Vladimir
2010/6/17 Daniel Gackle danielgackle@gmail.com:
Below is a DEFUN-JS macro for defining PS functions at the Lisp top-level. It creates a Lisp stub with the same signature whose body simply throws an error telling you that you tried to call a PS function from Lisp. Why is that useful? Because now your PS functions are fully integrated with Slime. You can jump around with M-., get arglist info in the minibuffer, and so on. After a week of using this, I can't believe how much of a difference it makes. In PS, DEFUN-JS translates trivially to DEFUN. Of course you still need a way to collect the JS emitted by all these forms, but PS is agnostic on how that should be done. A side note: we also converted nearly all our ps macros to DEFMACRO+PS forms at the toplevel. This has the neat property that you can now look at expansions using the highly convenient Slime macroexpand. I doubt that this is a perfect solution (no doubt you can trip yourself up on differences between the CL and PS macro environments), but it's sure handier than calling PS::PS-MACROEXPAND from the REPL. Daniel p.s. The following has been stripped of a couple of functions specific to our project. I tested it a bit, but if I missed anything, let me know.
(defmacro defun-js (name lambda-list &body body) (declare (ignore body)) (labels ((sym% (argspec) (if (symbolp argspec) argspec (car argspec)))) (multiple-value-bind (required optionals restp rest keyp keys allowp auxp aux morep more-context more-count beyond-requireds? key-object) (ps::parse-lambda-list lambda-list) (declare (ignore restp keyp allowp auxp aux morep more-context more-count beyond-requireds? key-object)) ;; get rid of init forms, which can't be evaluated in Lisp. (setf optionals (mapcar #'sym% optionals) keys (mapcar #'sym% keys)) `(defun ,name (,@required ,@(when optionals `(&optional ,@optionals)) ,@(when rest `(&rest ,rest)) ,@(when keys `(&key ,@keys))) (declare (ignore ,@required ,@optionals ,@(when rest (list rest)) ,@keys)) (error "The ~s function is js-only and cannot be called from Lisp." ',name))))) (defpsmacro defun-js (name lambda-list &body body) `(defun ,name ,lambda-list ,@body)) _______________________________________________ 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
Somewhat related, I came across this project recently:
http://github.com/3b/slime-proxy
Apparently you can use it with 3b's fork of Parenscript (http://github.com/3b/parenscript) to get a Parenscript-SLIME that gives you a REPL to your browser from Emacs.
Completely unrelated, but he/she also has a CL to Flash bytecode compiler:
Vladimir
2010/6/17 Red Daly reddaly@gmail.com:
I have a SLIME branch that extends slime to support almost the same features without the hack of defining a lisp stub for Parenscript functions. Missing is the xref support--if somebody could add this in it would be fantastic.
Unfortunately this code is for a rather old version of Parenscript because I am afraid of the recent changes breaking my non-unit-tested code. Nonetheless, you should be able to check out my version of Parenscript just to see how it works.
In any case, the branch of Parenscript and SLIME you will need are in my github account:
http://github.com/gonzojive/slime -- slime extension is pretty much up to date the the current SLIME. adds some extensions that let you plug Parenscript into slime's minibuffer completion. See http://github.com/gonzojive/slime/commit/40a84e1e5ea07f5068de61863bb00c22e7c... for the main diff
http://github.com/gonzojive/parenscript -- compatible version of Parenscript. See swank-parenscript.lisp and the compiler for how the hooks work. See http://github.com/gonzojive/parenscript/commit/5223c628d788750fa9ebac2682cf5... for the main diff that adds in SLIME support. Note I also added it for PSOS (see paren-psos repo)
Hope this helps the aspiring SLIME-Parenscripter. Kudos to the person who adds in xref support
Red
On Thu, Jun 17, 2010 at 1:03 PM, Vladimir Sedach vsedach@gmail.com wrote:
That's a good way of doing things for now. I didn't realize DEFMACRO+PS could be used that way either.
The hypothetical Parenscript-SLIME is supposed to do this (and more). Andrey Moskvitin has a fork of SLIME that supports feature and protocol extensions (http://github.com/archimag/slime-archimag - strangely enough the current SLIME maintainers don't seem to be interested in things like protocol versioning) and I'm planning to see if I can do things like xref support for Parenscript forms there.
Vladimir
2010/6/17 Daniel Gackle danielgackle@gmail.com:
Below is a DEFUN-JS macro for defining PS functions at the Lisp top-level. It creates a Lisp stub with the same signature whose body simply throws an error telling you that you tried to call a PS function from Lisp. Why is that useful? Because now your PS functions are fully integrated with Slime. You can jump around with M-., get arglist info in the minibuffer, and so on. After a week of using this, I can't believe how much of a difference it makes. In PS, DEFUN-JS translates trivially to DEFUN. Of course you still need a way to collect the JS emitted by all these forms, but PS is agnostic on how that should be done. A side note: we also converted nearly all our ps macros to DEFMACRO+PS forms at the toplevel. This has the neat property that you can now look at expansions using the highly convenient Slime macroexpand. I doubt that this is a perfect solution (no doubt you can trip yourself up on differences between the CL and PS macro environments), but it's sure handier than calling PS::PS-MACROEXPAND from the REPL. Daniel p.s. The following has been stripped of a couple of functions specific to our project. I tested it a bit, but if I missed anything, let me know.
(defmacro defun-js (name lambda-list &body body) (declare (ignore body)) (labels ((sym% (argspec) (if (symbolp argspec) argspec (car argspec)))) (multiple-value-bind (required optionals restp rest keyp keys allowp auxp aux morep more-context more-count beyond-requireds? key-object) (ps::parse-lambda-list lambda-list) (declare (ignore restp keyp allowp auxp aux morep more-context more-count beyond-requireds? key-object)) ;; get rid of init forms, which can't be evaluated in Lisp. (setf optionals (mapcar #'sym% optionals) keys (mapcar #'sym% keys)) `(defun ,name (,@required ,@(when optionals `(&optional ,@optionals)) ,@(when rest `(&rest ,rest)) ,@(when keys `(&key ,@keys))) (declare (ignore ,@required ,@optionals ,@(when rest (list rest)) ,@keys)) (error "The ~s function is js-only and cannot be called from Lisp." ',name))))) (defpsmacro defun-js (name lambda-list &body body) `(defun ,name ,lambda-list ,@body)) _______________________________________________ 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
parenscript-devel mailing list parenscript-devel@common-lisp.net http://common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel
parenscript-devel@common-lisp.net