build.sh for documentation
[clinton/parenscript.git] / docs / introduction.lisp
1 (in-package :js)
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
17 (js
18 (defun foobar (a b)
19 (return (+ a b))))
20
21 ;;; The resulting javascript is:
22 "
23 function foobar(a, b) {
24 return a + b;
25 }
26 "
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.
47 ;;; `for' loops can be written using the customary `DO' syntax.
48
49 (js
50 (do ((i 0 (incf i))
51 (j (aref arr i) (aref arr i)))
52 ((>= i 10))
53 (alert (+ "i is " i " and j is " j))))
54
55 ; compiles to
56 "
57 for (var i = 0, j = arr[i]; i < 10; i = ++i, j = arr[i]) {
58 alert('i is ' + i + ' and j is ' + j);
59 }
60 "
61 ;;; ParenScript uses the Lisp reader, allowing for reader macros. It
62 ;;; also comes with its own macro environment, allowing host macros
63 ;;; and ParenScript to coexist without interfering with each other.
64 ;;; Furthermore, ParenScript uses its own compiler macro system,
65 ;;; allowing for an even further customization of the generation of
66 ;;; JavaScript. For example, the `1+' construct is implemented using a
67 ;;; ParenScript macro:
68
69 (defjsmacro 1+ (form)
70 `(+ ,form 1))
71
72 ;;; ParenScript allows the creation of JavaScript objects in a Lispy
73 ;;; way, using keyword arguments.
74
75 (js
76 (create :foo "foo"
77 :bla "bla"))
78
79 ; compiles to
80 "
81 { foo : 'foo',
82 bla : 'bla' }
83 "
84 ;;; ParenScript features a HTML generator. Using the same syntax as
85 ;;; the `HTMLGEN' package of Franz, Inc., it can generate JavaScript
86 ;;; string expressions. This allows for a clean integration of HTML in
87 ;;; ParenScript code, instead of writing the tedious and error-prone
88 ;;; string generation code generally found in JavaScript.
89
90 (js
91 (defun add-div (name href link-text)
92 (document.write
93 (html ((:div :id name)
94 "The link is: "
95 ((:a :href href) link-text))))))
96
97 ; compiles to
98 "
99 function addDiv(name, href, linkText) {
100 document.write('<div id=\"' + name + '\">The link is: <a href=\"'
101 + href + '\">'
102 + linkText + '</a></div>');
103 }
104 "
105 ;;; In order to have a complete web application framework available in
106 ;;; Lisp, ParenScript also provides a sexp-based syntax for CSS
107 ;;; files. Thus, a complete web application featuring HTML, CSS and
108 ;;; JavaScript documents can be generated using Lisp syntax, allowing
109 ;;; the programmer to use Lisp macros to factor out the redundancies
110 ;;; and complexities of Web syntax. For example, to generate a CSS
111 ;;; inline node in a HTML document:
112
113 (html-stream *standard-output*
114 (html
115 (:html
116 (:head
117 (css (* :border "1px solid black")
118 (div.bl0rg :font-family "serif")
119 (("a:active" "a:hoover") :color "black" :size "200%"))))))
120
121 ; which produces
122
123 <html><head><style type="text/css">
124 <!--
125 * {
126 border:1px solid black;
127 }
128
129 div.bl0rg {
130 font-family:serif;
131 }
132
133 a:active,a:hoover {
134 color:black;
135 size:200%;
136 }
137
138 -->
139 </style>
140 </head>
141 </html>
142
143 ;;;# Getting ParenScript
144 ;;;
145 ;;; ParenScript can be obtained from the BKNR subversion repository at
146
147 svn://bknr.net/trunk/bknr/src/js
148
149 ;;; ParenScript does not depend on any part of BKNR though. You can
150 ;;; download snapshots of ParenScript at the webpage
151
152 http://bknr.net/parenscript
153
154 ;;; or using asdf-install.
155
156 (asdf-install:install 'parenscript)
157
158 ;;;
159 ;;; After downloading the ParenScript sourcecode, set up the ASDF
160 ;;; central registry by adding a symlink to "parenscript.asd". Then
161 ;;; use ASDF to load ParenScript. You may want to edit the ASDF file
162 ;;; to remove the dependency on the Allegroserve HTMLGEN facility.
163
164 (asdf:oos 'asdf:load-op :parenscript)
165
166 ;;; ParenScript was written by Manuel Odendahl. He can be reached at
167
168 manuel@bknr.net
169