Commit | Line | Data |
---|---|---|
cf1e6300 | 1 | (in-package :ps) |
8e198a08 MB |
2 | ;;;# Introduction |
3 | ;;; | |
4 | ;;; ParenScript is a simple language that looks a lot like Lisp, but | |
5 | ;;; actually is JavaScript in disguise. Actually, it is JavaScript | |
6 | ;;; embedded in a host Lisp. This way, JavaScript programs can be | |
7 | ;;; seamlessly integrated in a Lisp web application. The programmer | |
8 | ;;; doesn't have to resort to a different syntax, and JavaScript code | |
9 | ;;; can easily be generated without having to resort to complicated | |
10 | ;;; string generation or `FORMAT' expressions. | |
11 | ;;; | |
12 | ;;; An example is worth more than a thousand words. The following Lisp | |
13 | ;;; expression is a call to the ParenScript "compiler". The | |
14 | ;;; ParenScript "compiler" transforms the expression in ParenScript | |
15 | ;;; into an equivalent, human-readable expression in JavaScript. | |
16 | ||
cf1e6300 | 17 | (ps |
8e198a08 MB |
18 | (defun foobar (a b) |
19 | (return (+ a b)))) | |
20 | ||
21 | ;;; The resulting javascript is: | |
1e92094a | 22 | " |
8e198a08 MB |
23 | function foobar(a, b) { |
24 | return a + b; | |
25 | } | |
1e92094a | 26 | " |
8e198a08 MB |
27 | ;;; Great care has been given to the indentation and overall |
28 | ;;; readability of the generated JavaScript code. | |
29 | ||
30 | ;;;# Features | |
31 | ;;; | |
32 | ;;; ParenScript supports all the statements and expressions defined by | |
33 | ;;; the EcmaScript 262 standard. Lisp symbols are converted to | |
34 | ;;; camelcase, javascript-compliant syntax. This idea is taken from | |
35 | ;;; Linj by Antonio Menezes Leitao. Here are a few examples of Lisp | |
36 | ;;; symbol to JavaScript name conversion: | |
37 | ||
38 | (js-to-string 'foobar) => "foobar" | |
39 | (js-to-string 'foo-bar) => "fooBar" | |
40 | (js-to-string 'foo-b-@-r) => "fooBAtR" | |
41 | (js-to-string 'foo-b@r) => "fooBatr" | |
42 | (js-to-string '*array) => "Array" | |
43 | (js-to-string '*math.floor) => "Math.floor" | |
44 | ||
45 | ;;; It also supports additional iteration constructs, relieving the | |
46 | ;;; programmer of the burden of iterating over arrays. | |
d777a405 | 47 | ;;; `for' loops can be written using the customary `DO*' syntax. |
8e198a08 | 48 | |
cf1e6300 | 49 | (ps |
d777a405 TC |
50 | (do* ((i 0 (incf i)) |
51 | (j (aref arr i) (aref arr i))) | |
52 | ((>= i 10)) | |
8e198a08 MB |
53 | (alert (+ "i is " i " and j is " j)))) |
54 | ||
45c9f9c2 | 55 | ;; compiles to |
1e92094a | 56 | " |
8e198a08 | 57 | for (var i = 0, j = arr[i]; i < 10; i = ++i, j = arr[i]) { |
1e92094a | 58 | alert('i is ' + i + ' and j is ' + j); |
d777a405 | 59 | }; |
1e92094a | 60 | " |
8e198a08 | 61 | ;;; ParenScript uses the Lisp reader, allowing for reader macros. It |
cf1e6300 VS |
62 | ;;; also comes with its own macro environment, allowing host Lisp |
63 | ;;; macros and ParenScript macros to coexist without interfering with | |
64 | ;;; each other. For example, the `1+' construct is implemented using | |
65 | ;;; a ParenScript macro: | |
66 | ||
67 | (defpsmacro 1+ (form) | |
8e198a08 MB |
68 | `(+ ,form 1)) |
69 | ||
70 | ;;; ParenScript allows the creation of JavaScript objects in a Lispy | |
71 | ;;; way, using keyword arguments. | |
72 | ||
cf1e6300 | 73 | (ps |
8e198a08 MB |
74 | (create :foo "foo" |
75 | :bla "bla")) | |
76 | ||
45c9f9c2 | 77 | ;; compiles to |
1e92094a | 78 | " |
94a05cdf | 79 | { foo : 'foo', |
1e92094a HH |
80 | bla : 'bla' } |
81 | " | |
8e198a08 | 82 | ;;; ParenScript features a HTML generator. Using the same syntax as |
cf1e6300 | 83 | ;;; the HTMLGEN package of Franz, Inc., it can generate JavaScript |
8e198a08 MB |
84 | ;;; string expressions. This allows for a clean integration of HTML in |
85 | ;;; ParenScript code, instead of writing the tedious and error-prone | |
86 | ;;; string generation code generally found in JavaScript. | |
87 | ||
cf1e6300 | 88 | (ps |
8e198a08 MB |
89 | (defun add-div (name href link-text) |
90 | (document.write | |
cf1e6300 VS |
91 | (ps-html ((:div :id name) |
92 | "The link is: " | |
93 | ((:a :href href) link-text)))))) | |
8e198a08 | 94 | |
45c9f9c2 | 95 | ;; compiles to |
1e92094a | 96 | " |
8e198a08 | 97 | function addDiv(name, href, linkText) { |
1e92094a HH |
98 | document.write('<div id=\"' + name + '\">The link is: <a href=\"' |
99 | + href + '\">' | |
100 | + linkText + '</a></div>'); | |
8e198a08 | 101 | } |
1e92094a | 102 | " |
8e198a08 MB |
103 | ;;; In order to have a complete web application framework available in |
104 | ;;; Lisp, ParenScript also provides a sexp-based syntax for CSS | |
cf1e6300 VS |
105 | ;;; stylesheets. Thus, a complete web application featuring HTML, CSS |
106 | ;;; and JavaScript documents can be generated using Lisp syntax, | |
107 | ;;; allowing the programmer to use Lisp macros to factor out the | |
108 | ;;; redundancies and complexities of Web syntax. For example, to | |
109 | ;;; generate a CSS inline node in a HTML document using the | |
110 | ;;; AllegroServe HTMLGEN library: | |
8e198a08 | 111 | |
94a05cdf | 112 | (html-stream *standard-output* |
8e198a08 MB |
113 | (html |
114 | (:html | |
115 | (:head | |
116 | (css (* :border "1px solid black") | |
117 | (div.bl0rg :font-family "serif") | |
118 | (("a:active" "a:hoover") :color "black" :size "200%")))))) | |
119 | ||
45c9f9c2 | 120 | ;; which produces |
8e198a08 MB |
121 | |
122 | <html><head><style type="text/css"> | |
123 | <!-- | |
124 | * { | |
125 | border:1px solid black; | |
126 | } | |
127 | ||
128 | div.bl0rg { | |
129 | font-family:serif; | |
130 | } | |
131 | ||
132 | a:active,a:hoover { | |
133 | color:black; | |
134 | size:200%; | |
135 | } | |
136 | ||
137 | --> | |
138 | </style> | |
139 | </head> | |
140 | </html> |