Added tests for previous script* eval bug.
[clinton/parenscript.git] / src / compilation-interface.lisp
CommitLineData
9da682ca
RD
1(in-package :parenscript)
2
3(defmacro with-new-compilation-environment ((var) &body body)
4 `(let* ((,var (make-basic-compilation-environment))
5 (*compilation-environment* ,var))
6 ,@body))
7
9da682ca
RD
8(defun translate-ast (compiled-expr
9 &key
10 (comp-env *compilation-environment*)
11 (output-stream *standard-output*)
12 (output-spec :javascript)
13 (pretty-print t))
14 "Translates a compiled Parenscript program (compiled with COMPILE-PAREN-FORM)
15to a Javascript string. Outputs to the stream OUTPUT-STREAM in the language given
16by OUTPUT-SPEC, pretty printing if PRETTY-PRINT is non-null.
17
18OUTPUT-SPEC must be :javascript at the moment."
5aa10005 19 (declare (ignore comp-env))
9da682ca
RD
20 (when (not (eql :javascript output-spec))
21 (error "Unsupported output-spec for translation: ~A" output-spec))
22 (when (eql :javascript output-spec)
5aa10005
RD
23; (if (not pretty-print)
24; (js-translate compiled-expr :statement output-stream)
25 (write-string (string-join
26 (ps-js::js-to-statement-strings compiled-expr 0)
27 (string #\Newline))
28 output-stream)))
9da682ca 29
a9fce0a7
RD
30(defun non-nil-comp-env ()
31 "Returns a sane compilation environment. Either the one currently bound or a new
32one."
33 (or *compilation-environment*
34 (make-basic-compilation-environment)))
35
36
9da682ca
RD
37(defun compile-script (script-form
38 &key
39 (output-spec :javascript)
40 (pretty-print t)
41 (output-stream nil)
a98e58ee 42 (toplevel-p t)
a9fce0a7 43 (comp-env (non-nil-comp-env)))
9da682ca
RD
44 "Compiles the Parenscript form SCRIPT-FORM into the language specified by OUTPUT-SPEC.
45Non-null PRETTY-PRINT values result in a pretty-printed output code. If OUTPUT-STREAM
46is NIL, then the result is a string; otherwise code is output to the OUTPUT-STREAM stream.
47COMP-ENV is the compilation environment in which to compile the form.
48
49This is the main function used by Parenscript users to compile their code to Javascript (and
50potentially other languages)."
51 (macrolet ((with-output-stream ((var) &body body)
52 `(if (null output-stream)
53 (with-output-to-string (,var)
54 ,@body)
55 (let ((,var output-stream))
56 ,@body))))
57 (with-output-stream (stream)
a98e58ee
RD
58 (let* ((*compilation-environment* comp-env)
59 (compiled
60 (if toplevel-p
61 (compile-parenscript-form
62 comp-env
63 (compile-parenscript-form comp-env script-form :toplevel-p t))
64 (compile-parenscript-form comp-env script-form :toplevel-p nil))))
65 (translate-ast
66 compiled
67; (compile-script-form script-form :comp-env comp-env)
68 :comp-env comp-env
69 :output-stream stream
70 :output-spec output-spec
71 :pretty-print pretty-print)))))
72
73(defun compile-script-file (source-file
74 &key
75 (output-spec :javascript)
a9fce0a7 76 (comp-env (non-nil-comp-env))
a98e58ee
RD
77 (pretty-print t)
78 (output-stream *standard-output*))
79 "Compiles the given Parenscript source file and outputs the results
80to the given output stream."
81 (setf (comp-env-compiling-toplevel-p comp-env) t)
171bbab3
RD
82 (with-open-file (input source-file :direction :input)
83 (let ((end-read-form '#:unique))
84 (flet ((read-form ()
85 (parenscript.reader:read input nil end-read-form)))
86 (macrolet ((with-output-stream ((var) &body body)
87 `(if (null output-stream)
88 (with-output-to-string (,var)
89 ,@body)
90 (let ((,var output-stream))
91 ,@body))))
92 (let* ((*compilation-environment* comp-env)
93 (compiled
94 (do ((form (read-form) (read-form))
95 (compiled-forms nil))
96 ((eql form end-read-form)
97 (compile-parenscript-form
98 comp-env
99 `(progn ,@(nreverse compiled-forms))
100 :toplevel-p nil))
101 (let ((tl-compiled-form
102 (compile-parenscript-form comp-env form :toplevel-p t)))
103 (push tl-compiled-form compiled-forms)))))
104 (with-output-stream (output)
105 (translate-ast
106 compiled
107 :comp-env comp-env
108 :output-stream output
109 :output-spec output-spec
110 :pretty-print pretty-print))))))))
a9fce0a7
RD
111
112(defun compile-script-system (system
113 &rest args
114 &key
115 (output-spec :javascript)
116 (pretty-print t)
117 (output-to-stream t)
118 (output-stream *standard-output*)
119 output-to-files ;; currently ignored
120 (comp-env (non-nil-comp-env)))
121 "Compiles a collection of parenscripts as described by an ASDF system into files or
122a specified output stream."
123 (asdf:operate 'asdf::parenscript-compile-op system
124 :output-spec output-spec
125 :pretty-print pretty-print
126; :output-to-stream t
127 :output-stream output-stream
128 :comp-env comp-env
129 :force-p t
130 ))
131
132
133;(defun compile-script-system-component (system-designator
134
a98e58ee
RD
135;(defun compile-script-file (script-src-file
136; &key
137; (output-spec :javascript)
138; (output-stream *standard-out*)
139; (comp-env *compilation-environment*))
140
9da682ca 141
a98e58ee 142;;; old file compilation functions:
171bbab3 143(defun compile-parenscript-file-to-string (source-file)
9da682ca
RD
144 "Compile SOURCE-FILE (a parenscript file) to a javascript string. (in-package ...) forms
145behave as expected and all other forms are evaluated according to the value of
146EVAL-FORMS-P. If the result of the evaluation is not nil then it's compiled with
147js:js* and written to the output."
171bbab3
RD
148 (compile-script-file source-file :output-stream nil))
149
9da682ca
RD
150(defun compile-parenscript-file (source-file &rest args &key destination-file &allow-other-keys)
151 "Compile SOURCE-FILE (a parenscript file) to a javascript file with
152compile-parenscript-file-to-string. When DESTINATION-FILE is omitted,
153then it will be named the same as SOURCE-FILE but with js extension."
154 (setf args (copy-list args))
155 (remf args :destination-file)
156 (unless destination-file
157 (setf destination-file (merge-pathnames (make-pathname :type "js")
158 source-file)))
159 (with-open-file (output destination-file :if-exists :supersede :direction :output)
160 (write-string (apply #'compile-parenscript-file-to-string source-file args) output)))
a9fce0a7
RD
161
162;;; SEXPs -> Javascript string functionality
163(defmacro script (&body body)
164 "A macro that returns a Javascript string of the supplied Parenscript forms."
165 `(script* '(progn ,@body)))
166
167(defmacro ps (&body body)
168 `(script ,@body))
169
4b5d1808 170(defun script* (&rest body)
a9fce0a7 171 "Return the javascript string representing BODY.
a9fce0a7 172Body is evaluated."
4b5d1808 173 (compile-script `(progn ,@body)))
a9fce0a7
RD
174
175(defmacro ps* (&body body)
4b5d1808 176 `(script* ,@body))