Commit | Line | Data |
---|---|---|
4525e3cd VS |
1 | (in-package "PARENSCRIPT") |
2 | ||
62ddca23 | 3 | (defparameter *js-target-version* 1.3) |
9da682ca | 4 | |
4a987e2b | 5 | (defmacro ps (&body body) |
cb8f8e58 VS |
6 | "Given Parenscript forms (an implicit progn), compiles those forms |
7 | to a JavaScript string at macro-expansion time." | |
5b87316b VS |
8 | (let ((s (gensym))) |
9 | `(with-output-to-string (,s) | |
10 | ,@(mapcar (lambda (x) | |
11 | `(write-string ,x ,s)) | |
12 | (parenscript-print | |
13 | (compile-parenscript-form `(progn ,@body) | |
14 | :expecting :statement)))))) | |
5a69278c VS |
15 | (defun ps* (&rest body) |
16 | "Compiles BODY to a JavaScript string. | |
17 | Body is evaluated." | |
18 | (compiled-form-to-string (compile-parenscript-form `(progn ,@body) :expecting :statement))) | |
19 | ||
c11d6a09 TC |
20 | (defmacro ps-doc (&body body) |
21 | "Expands Parenscript forms in a clean environment." | |
cb8f8e58 VS |
22 | (let ((*ps-gensym-counter* 0) |
23 | (*ps-special-variables* nil)) | |
24 | (macroexpand-1 `(ps ,@body)))) | |
25 | ||
157cb2d6 VS |
26 | (defun ps-doc* (ps-form) |
27 | (let ((*ps-gensym-counter* 0) | |
28 | (*ps-special-variables* nil)) | |
5a69278c | 29 | (ps* ps-form))) |
8877a380 VS |
30 | |
31 | (defun compiled-form-to-string (ps-compiled-form) | |
84338ee6 | 32 | (with-output-to-string (s) |
9831d514 VS |
33 | (dolist (x (parenscript-print ps-compiled-form)) |
34 | (write-string (if (stringp x) x (eval x)) s)))) | |
8877a380 | 35 | |
c639fe7f VS |
36 | (defvar *js-inline-string-delimiter* #\" |
37 | "Controls the string delimiter char used when compiling Parenscript in ps-inline.") | |
33c100f0 | 38 | |
c639fe7f | 39 | (defun ps-inline* (form &optional (*js-string-delimiter* *js-inline-string-delimiter*)) |
5a69278c | 40 | (concatenate 'string "javascript:" (ps* form))) |
c639fe7f | 41 | |
e69d0a12 VS |
42 | (defmacro/ps ps-inline (form &optional (string-delimiter *js-inline-string-delimiter*)) |
43 | `(concatenate 'string "javascript:" | |
44 | ,@(let ((*js-string-delimiter* string-delimiter)) | |
45 | (parenscript-print (compile-parenscript-form form :expecting :statement))))) | |
5a69278c VS |
46 | |
47 | (defvar *ps-read-function* #'read | |
48 | "This should be a function that takes the same inputs and returns the same | |
49 | outputs as the common lisp read function. We declare it as a variable to allow | |
50 | a user-supplied reader instead of the default lisp reader.") | |
51 | ||
52 | (defun ps-compile-stream (stream) | |
53 | "Compiles a source stream as if it were a file. Outputs a Javascript string." | |
54 | (let ((*ps-compilation-level* :toplevel) | |
55 | (*package* *package*) | |
56 | (end-read-form '#:unique)) | |
57 | (flet ((read-form () (funcall *ps-read-function* stream nil end-read-form))) | |
58 | (let* ((js-string | |
59 | ;; cons up the forms, compiling as we go, and print the result | |
60 | (do ((form (read-form) (read-form)) | |
61 | (compiled-forms nil)) | |
62 | ((eql form end-read-form) | |
63 | (format nil "~{~A~^;~%~}" | |
64 | (remove-if | |
65 | #'(lambda (x) (or (null x) (= 0 (length x)))) | |
66 | (mapcar 'compiled-form-to-string (nreverse compiled-forms))))) | |
67 | (push (compile-parenscript-form form :expecting :statement) compiled-forms)))) | |
68 | js-string)))) | |
69 | ||
70 | (defun ps-compile-file (source-file) | |
71 | "Compiles the given Parenscript source file and returns a Javascript string." | |
72 | (with-open-file (stream source-file :direction :input) | |
73 | (ps-compile-stream stream))) |