(* 1 (+ 2 3 4) 4 (/ 6 7))
=> 1 * (2 + 3 + 4) * 4 * (6 / 7)
-;;; The pre/post increment and decrement operators are also
+;;; The pre increment and decrement operators are also
;;; available. `INCF' and `DECF' are the pre-incrementing and
-;;; pre-decrementing operators, and `++' and `--' are the
-;;; post-decrementing version of the operators. These operators can
+;;; pre-decrementing operators. These operators can
;;; take only one argument.
-(++ i) => i++
-
-(-- i) => i--
-
(incf i) => ++i
(decf i) => --i
;;; Assignment is done using the `SETF' form, which is transformed
;;; into a series of assignments using the JavaScript `=' operator.
-(setf a 1) => a = 1
+(setf a 1) => a = 1;
(setf a 2 b 3 c 4 x (+ a b c))
=> a = 2;
;;; operator expression using this variable into a more "efficient"
;;; assignment operator form. For example:
-(setf a (1+ a)) => a++
+(setf a (1+ a)) => a++;
-(setf a (+ a 2 3 4 a)) => a += 2 + 3 + 4 + a
+(setf a (+ a 2 3 4 a)) => a += 2 + 3 + 4 + a;
-(setf a (- 1 a)) => a = 1 - a
+(setf a (- 1 a)) => a = 1 - a;
;;;# Single argument statements
;;;t \index{single-argument statement}
;;; Lisp. The `DEFVAR' is converted to "var ... = ..." form in
;;; JavaScript.
-(defvar *a* (array 1 2 3)) => var A = [ 1, 2, 3 ];
+(defvar *a* (array 1 2 3)) => var A = [ 1, 2, 3 ]
(if (= i 1)
(progn (defvar blorg "hallo")
;;; The `DOLIST' form is a shortcut for iterating over an array. Note
;;; that this form creates temporary variables using a function called
-;;; `JS-GENSYM', which is similar to its Lisp counterpart `GENSYM'.
+;;; `PS-GENSYM', which is similar to its Lisp counterpart `GENSYM'.
(dolist (l blorg)
(document.write (+ "L is " l)))
- => {
- var tmpArr1 = blorg;
+ => var tmpArr1 = blorg;
for (var tmpI2 = 0; tmpI2 < tmpArr1.length;
tmpI2 = tmpI2 + 1) {
var l = tmpArr1[tmpI2];
document.write('L is ' + l);
};
- }
-
;;; The `DOEACH' form is converted to a `for (var .. in ..)' form in
;;; JavaScript. It is used to iterate over the enumerable properties
(2 (alert "two"))
(t (alert "default clause")))
=> switch (blorg[i]) {
- case 1: ;
+ case 1:
case 'one':
alert('one');
break;
; (HTML html-expression)
-;;; The HTML generator of ParenScript is very similar to the HTML
-;;; generator included in AllegroServe. It accepts the same input
-;;; forms as the AllegroServer HTML generator. However, non-HTML
-;;; construct are compiled to JavaScript by the ParenScript
+;;; The HTML generator of ParenScript is very similar to the htmlgen
+;;; HTML generator library included with AllegroServe. It accepts the
+;;; same input forms as the AllegroServer HTML generator. However,
+;;; non-HTML construct are compiled to JavaScript by the ParenScript
;;; compiler. The resulting expression is a JavaScript expression.
-(html ((:a :href "foobar") "blorg"))
+(ps-html ((:a :href "foobar") "blorg"))
=> '<a href=\"foobar\">blorg</a>'
-(html ((:a :href (generate-a-link)) "blorg"))
+(ps-html ((:a :href (generate-a-link)) "blorg"))
=> '<a href=\"' + generateALink() + '\">blorg</a>'
;;; We can recursively call the JS compiler in a HTML expression.
(document.write
- (html ((:a :href "#"
- :onclick (js-inline (transport))) "link")))
- => document.write
- ('<a href=\"#\" onclick=\"' + 'javascript:transport();' + '\">link</a>')
+ (ps-html ((:a :href "#"
+ :onclick (lisp (ps-inline (transport)))) "link")))
+ => document.write('<a href=\"#\" onclick=\"' + 'javascript:transport();' + '\">link</a>')
;;; Forms may be used in attribute lists to conditionally generate
;;; the next attribute. In this example the textarea is sometimes disabled.
(let ((disabled nil)
(authorized t))
(setf element.inner-h-t-m-l
- (html ((:textarea (or disabled (not authorized)) :disabled "disabled")
+ (ps-html ((:textarea (or disabled (not authorized)) :disabled "disabled")
"Edit me"))))
- => {
- var disabled = null;
+ => var disabled = null;
var authorized = true;
element.innerHTML =
'<textarea'
+ (disabled || !authorized ? ' disabled=\"' + 'disabled' + '\"' : '')
+ '>Edit me</textarea>';
- }
; (CSS-INLINE css-expression)
=> 'color:red;font-size:x-small'
(defun make-color-div(color-name)
- (return (html ((:div :style (css-inline :color color-name))
+ (return (ps-html ((:div :style (css-inline :color color-name))
color-name " looks like this."))))
=> function makeColorDiv(colorName) {
return '<div style=\"' + ('color:' + colorName) + '\">' + colorName
;;; of the `DOLIST' form (note how `JS-GENSYM', the ParenScript of
;;; `GENSYM', is used to generate new ParenScript variable names):
-(defjsmacro dolist (i-array &rest body)
+(defpsmacro dolist (i-array &rest body)
(let ((var (first i-array))
(array (second i-array))
(arrvar (js-gensym "arr"))
(idx (js-gensym "i")))
`(let ((,arrvar ,array))
- (do ((,idx 0 (++ ,idx)))
+ (do ((,idx 0 (incf ,idx)))
((>= ,idx (slot-value ,arrvar 'length)))
(let ((,var (aref ,arrvar ,idx)))
,@body)))))
-;;; Macros can be added dynamically to the macro environment by using
-;;; the ParenScript `MACROLET' form (note that while `DEFJSMACRO' is a
-;;; Lisp form, `MACROLET' and `SYMBOL-MACROLET' are ParenScript forms).
+;;; Macros can be defined in ParenScript itself (as opposed to Lisp)
+;;; by using the ParenScript `MACROLET' and 'DEFMACRO' forms.
+
+;;; ParenScript also supports the use of macros defined in the
+;;; underlying Lisp. Existing Lisp macros can be imported into the
+;;; ParenScript macro environment by 'IMPORT-MACROS-FROM-LISP'. This
+;;; functionality enables code sharing between ParenScript and Lisp,
+;;; and is useful in debugging since the full power of Lisp
+;;; macroexpanders, editors and other supporting facilities can be
+;;; used. However, it is important to note that the macroexpansion of
+;;; Lisp macros and ParenScript macros takes place in their own
+;;; respective environments, and many Lisp macros (especially those
+;;; provided by the Lisp implementation) expand into code that is not
+;;; usable by ParenScript. To make it easy for users to take advantage
+;;; of these features, two additional macro definition facilities are
+;;; provided by ParenScript: 'DEFMACRO/JS' and
+;;; 'DEFMACRO+JS'. 'DEFMACRO/JS' defines a Lisp macro and then imports
+;;; it into the ParenScript macro environment, while 'DEFMACRO+JS'
+;;; defines two macros with the same name and expansion, one in
+;;; ParenScript and one in Lisp. 'DEFMACRO+JS' is used when the full
+;;; 'macroexpand' of the Lisp macro yields code that cannot be used by
+;;; ParenScript.
;;; ParenScript also supports symbol macros, which can be introduced
;;; using the ParenScript form `SYMBOL-MACROLET'. A new macro