##// END OF EJS Templates
Bugfixes
naryl -
r22:d1c8a2bd default
parent child Browse files
Show More
@@ -1,11 +1,15 b''
1
1
2 * Remove cl-uglify-js (no support for ES6 at all and no way to monkey-patch it reliably)
3 * Use Parenscript's async/await
4 * Use Parenscript's minifier
5 * WAIT and MENU with async/await
2 * Special locations
6 * Special locations
3 * Special variables
7 * Special variables
4 * CLI build for Linux
8 * CLI build for Linux
5 * CLI build for Windows
9 * CLI build for Windows
6
10
7 * Build Istreblenie
11 * Build Istreblenie
8 * Windows GUI (for the compiler)
12 * Windows GUI (for the compiler)
9 * Save-load game in slots
13 * Save-load game in slots
10 * Resizable frames
14 * Resizable frames
11 ** modifying it to suit compiler specifics No newline at end of file
15 ** modifying it to suit compiler specifics
@@ -1,387 +1,390 b''
1
1
2 (in-package sugar-qsp)
2 (in-package sugar-qsp)
3
3
4 ;;; API deals with DOM manipulation and some bookkeeping for the
4 ;;; API deals with DOM manipulation and some bookkeeping for the
5 ;;; intrinsics, namely variables
5 ;;; intrinsics, namely variables
6 ;;; API is an implementation detail and has no QSP documentation. It
6 ;;; API is an implementation detail and has no QSP documentation. It
7 ;;; doesn't call intrinsics
7 ;;; doesn't call intrinsics
8
8
9 (setf (root api) (ps:create))
9 (setf (root api) (ps:create))
10
10
11 ;;; Utils
11 ;;; Utils
12
12
13 (defm (root api make-act-html) (title img)
13 (defm (root api make-act-html) (title img)
14 (+ "<a class='qsp-act' href='#' onclick='SugarQSP.acts[\"" title "\"].act();'>"
14 (+ "<a class='qsp-act' href='#' onclick='SugarQSP.acts[\"" title "\"].act();'>"
15 title
15 title
16 "</a>"))
16 "</a>"))
17
17
18 (defm (root api make-menu-item-html) (num title img loc)
18 (defm (root api make-menu-item-html) (num title img loc)
19 (+ "<a href='#' onclick='SugarQSP.api.runMenu(" num ", \"" loc "\")();'>"
19 (+ "<a href='#' onclick='SugarQSP.api.runMenu(" num ", \"" loc "\")();'>"
20 "<img src='" img "'>"
20 "<img src='" img "'>"
21 title
21 title
22 "</a>"))
22 "</a>"))
23
23
24 (defm (root api report-error) (text)
24 (defm (root api report-error) (text)
25 (alert text))
25 (alert text))
26
26
27 (defm (root api init-dom) ()
27 (defm (root api init-dom) ()
28 ;; Save/load buttons
28 ;; Save/load buttons
29 (let ((btn (document.get-element-by-id "qsp-btn-save")))
29 (let ((btn (document.get-element-by-id "qsp-btn-save")))
30 (setf (ps:@ btn onclick) this.savegame)
30 (setf (ps:@ btn onclick) this.savegame)
31 (setf (ps:@ btn href) "#"))
31 (setf (ps:@ btn href) "#"))
32 (let ((btn (document.get-element-by-id "qsp-btn-open")))
32 (let ((btn (document.get-element-by-id "qsp-btn-open")))
33 (setf (ps:@ btn onclick) this.opengame)
33 (setf (ps:@ btn onclick) this.opengame)
34 (setf (ps:@ btn href) "#"))
34 (setf (ps:@ btn href) "#"))
35 ;; Close image on click
35 ;; Close image on click
36 (setf (ps:@ (document.get-element-by-id "qsp-image-container") onclick)
36 (setf (ps:@ (document.get-element-by-id "qsp-image-container") onclick)
37 (this.show-image nil))
37 (this.show-image nil))
38 ;; Close the dropdown on any click
38 ;; Close the dropdown on any click
39 (setf window.onclick
39 (setf window.onclick
40 (lambda (event)
40 (lambda (event)
41 (setf (ps:@ (api-call get-frame :dropdown) style display) "none"))))
41 (setf (ps:@ (api-call get-frame :dropdown) style display) "none"))))
42
42
43 (defm (root api call-serv-loc) (var-name &rest args)
43 (defm (root api call-serv-loc) (var-name &rest args)
44 (let ((loc-name (api-call get-var name 0 :str)))
44 (let ((loc-name (api-call get-var name 0 :str)))
45 (when loc-name
45 (when loc-name
46 (let ((loc (ps:getprop (root locs) loc-name)))
46 (let ((loc (ps:getprop (root locs) loc-name)))
47 (when loc
47 (when loc
48 (funcall loc args))))))
48 (funcall loc args))))))
49
49
50 ;;; Misc
50 ;;; Misc
51
51
52 (defm (root api newline) (key)
53 (this.append-id (this.key-to-id key) "<br>" t))
54
52 (defm (root api clear-id) (id)
55 (defm (root api clear-id) (id)
53 (setf (ps:chain document (get-element-by-id id) inner-text) ""))
56 (setf (ps:chain document (get-element-by-id id) inner-h-t-m-l) ""))
57
58 (setf (root api text-escaper) (document.create-element :textarea))
59
60 (defm (root api prepare-contents) (s &optional force-html)
61 (if (or force-html (var "USEHTML" 0 :num))
62 s
63 (progn
64 (setf (ps:@ (root api text-escaper) text-content) s)
65 (ps:@ (root api text-escaper) inner-h-t-m-l))))
54
66
55 (defm (root api get-id) (id &optional force-html)
67 (defm (root api get-id) (id &optional force-html)
56 (if (or force-html (var "USEHTML" 0 :num))
68 (ps:chain (document.get-element-by-id id) inner-h-t-m-l))
57 (ps:chain (document.get-element-by-id id) inner-h-t-m-l)
58 (ps:chain (document.get-element-by-id id) inner-text)))
59
69
60 (defm (root api set-id) (id contents &optional force-html)
70 (defm (root api set-id) (id contents &optional force-html)
61 (if (or force-html (var "USEHTML" 0 :num))
71 (setf (ps:chain (document.get-element-by-id id) inner-h-t-m-l) (this.prepare-contents contents force-html)))
62 (setf (ps:chain (document.get-element-by-id id) inner-h-t-m-l) contents)
63 (setf (ps:chain (document.get-element-by-id id) inner-text) contents)))
64
72
65 (defm (root api append-id) (id contents &optional force-html)
73 (defm (root api append-id) (id contents &optional force-html)
66 (if (or force-html (var "USEHTML" 0 :num))
74 (when contents
67 (incf (ps:chain (document.get-element-by-id id) inner-h-t-m-l) contents)
75 (incf (ps:chain (document.get-element-by-id id) inner-h-t-m-l) (this.prepare-contents contents force-html))))
68 (incf (ps:chain (document.get-element-by-id id) inner-text) contents)))
69
76
70 ;;; Function calls
77 ;;; Function calls
71
78
72 (defm (root api init-args) (args)
79 (defm (root api init-args) (args)
73 (dotimes (i (length args))
80 (dotimes (i (length args))
74 (let ((arg (elt args i)))
81 (let ((arg (elt args i)))
75 (if (numberp arg)
82 (if (numberp arg)
76 (this.set-var args i :num arg)
83 (this.set-var args i :num arg)
77 (this.set-var args i :str arg)))))
84 (this.set-var args i :str arg)))))
78
85
79 (defm (root api get-result) ()
86 (defm (root api get-result) ()
80 (if (not (equal "" (var result 0 :str)))
87 (if (not (equal "" (var result 0 :str)))
81 (var result 0 :str)
88 (var result 0 :str)
82 (var result 0 :num)))
89 (var result 0 :num)))
83
90
84 (defm (root api call-loc) (name args)
91 (defm (root api call-loc) (name args)
85 (funcall (ps:getprop (root locs) name) args))
92 (funcall (ps:getprop (root locs) name) args))
86
93
87 ;;; Text windows
94 ;;; Text windows
88
95
89 (defm (root api key-to-id) (key)
96 (defm (root api key-to-id) (key)
90 (case key
97 (case key
91 (:main "qsp-main")
98 (:main "qsp-main")
92 (:stat "qsp-stat")
99 (:stat "qsp-stat")
93 (:objs "qsp-objs")
100 (:objs "qsp-objs")
94 (:acts "qsp-acts")
101 (:acts "qsp-acts")
95 (:input "qsp-input")
102 (:input "qsp-input")
96 (:dropdown "qsp-dropdown")
103 (:dropdown "qsp-dropdown")
97 (t (this.report-error "Internal error!"))))
104 (t (this.report-error "Internal error!"))))
98
105
99 (defm (root api get-frame) (key)
106 (defm (root api get-frame) (key)
100 (document.get-element-by-id (this.key-to-id key)))
107 (document.get-element-by-id (this.key-to-id key)))
101
108
102 (defm (root api add-text) (key text)
109 (defm (root api add-text) (key text)
103 (this.append-id (this.key-to-id key) text))
110 (this.append-id (this.key-to-id key) text))
104
111
105 (defm (root api get-text) (key)
112 (defm (root api get-text) (key)
106 (this.get-id (this.key-to-id key)))
113 (this.get-id (this.key-to-id key)))
107
114
108 (defm (root api clear-text) (key)
115 (defm (root api clear-text) (key)
109 (this.clear-id (this.key-to-id key)))
116 (this.clear-id (this.key-to-id key)))
110
117
111 (defm (root api newline) (key)
112 (let ((div (this.get-frame key)))
113 (ps:chain div (append-child (document.create-element "br")))))
114
115 (defm (root api enable-frame) (key enable)
118 (defm (root api enable-frame) (key enable)
116 (let ((obj (this.get-frame key)))
119 (let ((obj (this.get-frame key)))
117 (setf obj.style.display (if enable "block" "none"))
120 (setf obj.style.display (if enable "block" "none"))
118 (values)))
121 (values)))
119
122
120 ;;; Actions
123 ;;; Actions
121
124
122 (defm (root api add-act) (title img act)
125 (defm (root api add-act) (title img act)
123 (setf (ps:getprop (root acts) title)
126 (setf (ps:getprop (root acts) title)
124 (ps:create :img img :act act))
127 (ps:create :img img :act act))
125 (this.update-acts))
128 (this.update-acts))
126
129
127 (defm (root api del-act) (title)
130 (defm (root api del-act) (title)
128 (delete (ps:getprop (root acts) title))
131 (delete (ps:getprop (root acts) title))
129 (this.update-acts))
132 (this.update-acts))
130
133
131 (defm (root api clear-act) ()
134 (defm (root api clear-act) ()
132 (setf (root acts) (ps:create))
135 (setf (root acts) (ps:create))
133 (this.clear-id "qsp-acts"))
136 (this.clear-id "qsp-acts"))
134
137
135 (defm (root api update-acts) ()
138 (defm (root api update-acts) ()
136 (this.clear-id "qsp-acts")
139 (this.clear-id "qsp-acts")
137 (let ((elt (document.get-element-by-id "qsp-acts")))
140 (let ((elt (document.get-element-by-id "qsp-acts")))
138 (ps:for-in (title (root acts))
141 (ps:for-in (title (root acts))
139 (let ((obj (ps:getprop (root acts) title)))
142 (let ((obj (ps:getprop (root acts) title)))
140 (incf elt.inner-h-t-m-l (this.make-act-html title (ps:getprop obj :img)))))))
143 (incf elt.inner-h-t-m-l (this.make-act-html title (ps:getprop obj :img)))))))
141
144
142
145
143 ;;; "Syntax"
146 ;;; "Syntax"
144
147
145 (defm (root api qspfor) (name index from to step body)
148 (defm (root api qspfor) (name index from to step body)
146 (block nil
149 (block nil
147 (ps:for ((i from))
150 (ps:for ((i from))
148 ((< i to))
151 ((< i to))
149 ((incf i step))
152 ((incf i step))
150 (this.set-var name index :num i)
153 (this.set-var name index :num i)
151 (unless (funcall body)
154 (unless (funcall body)
152 (return)))))
155 (return)))))
153
156
154 ;;; Variable class
157 ;;; Variable class
155
158
156 (defm (root api *var) (name)
159 (defm (root api *var) (name)
157 ;; From strings to numbers
160 ;; From strings to numbers
158 (setf this.indexes (ps:create))
161 (setf this.indexes (ps:create))
159 ;; From numbers to {num: 0, str: ""} objects
162 ;; From numbers to {num: 0, str: ""} objects
160 (setf this.values (list))
163 (setf this.values (list))
161 (values))
164 (values))
162
165
163 (defm (root api *var prototype new-value) ()
166 (defm (root api *var prototype new-value) ()
164 (ps:create :num 0 :str ""))
167 (ps:create :num 0 :str ""))
165
168
166 (defm (root api *var prototype index-num) (index)
169 (defm (root api *var prototype index-num) (index)
167 (let ((num-index
170 (let ((num-index
168 (if (stringp index)
171 (if (stringp index)
169 (if (in index this.indexes)
172 (if (in index this.indexes)
170 (ps:getprop this.indexes index)
173 (ps:getprop this.indexes index)
171 (let ((n (length this.values)))
174 (let ((n (length this.values)))
172 (setf (ps:getprop this.indexes index) n)
175 (setf (ps:getprop this.indexes index) n)
173 n))
176 n))
174 index)))
177 index)))
175 (unless (in num-index this.values)
178 (unless (in num-index this.values)
176 (setf (elt this.values num-index) (this.new-value)))
179 (setf (elt this.values num-index) (this.new-value)))
177 num-index))
180 num-index))
178
181
179 (defm (root api *var prototype get) (index slot)
182 (defm (root api *var prototype get) (index slot)
180 (unless (or index (= 0 index))
183 (unless (or index (= 0 index))
181 (setf index (1- (length this.values))))
184 (setf index (1- (length this.values))))
182 (ps:getprop this.values (this.index-num index) slot))
185 (ps:getprop this.values (this.index-num index) slot))
183
186
184 (defm (root api *var prototype set) (index slot value)
187 (defm (root api *var prototype set) (index slot value)
185 (unless (or index (= 0 index))
188 (unless (or index (= 0 index))
186 (setf index (length store)))
189 (setf index (length store)))
187 (case slot
190 (case slot
188 (:num (setf value (ps:chain *number (parse-int value))))
191 (:num (setf value (ps:chain *number (parse-int value))))
189 (:str (setf value (ps:chain value (to-string)))))
192 (:str (setf value (ps:chain value (to-string)))))
190 (setf (ps:getprop this.values (this.index-num index) slot) value)
193 (setf (ps:getprop this.values (this.index-num index) slot) value)
191 (values))
194 (values))
192
195
193 (defm (root api *var prototype kill) (index)
196 (defm (root api *var prototype kill) (index)
194 (setf (elt this.values (this.index-num index)) (this.new-value)))
197 (setf (elt this.values (this.index-num index)) (this.new-value)))
195
198
196 ;;; Variables
199 ;;; Variables
197
200
198 (defm (root api var-real-name) (name)
201 (defm (root api var-real-name) (name)
199 (if (= (ps:@ name 0) #\$)
202 (if (= (ps:@ name 0) #\$)
200 (values (ps:chain name (substr 1)) :str)
203 (values (ps:chain name (substr 1)) :str)
201 (values name :num)))
204 (values name :num)))
202
205
203 (defm (root api ensure-var) (name)
206 (defm (root api ensure-var) (name)
204 (let ((store (this.var-ref name)))
207 (let ((store (this.var-ref name)))
205 (unless store
208 (unless store
206 (setf store (ps:new (this.-var name)))
209 (setf store (ps:new (this.-var name)))
207 (setf (ps:getprop (root vars) name) store))
210 (setf (ps:getprop (root vars) name) store))
208 store))
211 store))
209
212
210 (defm (root api var-ref) (name)
213 (defm (root api var-ref) (name)
211 (let ((local-store (this.current-local-frame)))
214 (let ((local-store (this.current-local-frame)))
212 (cond ((and local-store (in name local-store))
215 (cond ((and local-store (in name local-store))
213 (ps:getprop local-store name))
216 (ps:getprop local-store name))
214 ((in name (root vars))
217 ((in name (root vars))
215 (ps:getprop (root vars) name))
218 (ps:getprop (root vars) name))
216 (t nil))))
219 (t nil))))
217
220
218 (defm (root api get-var) (name index slot)
221 (defm (root api get-var) (name index slot)
219 (ps:chain (this.ensure-var name) (get index slot)))
222 (ps:chain (this.ensure-var name) (get index slot)))
220
223
221 (defm (root api set-var) (name index slot value)
224 (defm (root api set-var) (name index slot value)
222 (ps:chain (this.ensure-var name) (set index slot value))
225 (ps:chain (this.ensure-var name) (set index slot value))
223 (values))
226 (values))
224
227
225 (defm (root api get-array) (name)
228 (defm (root api get-array) (name)
226 (this.var-ref name))
229 (this.var-ref name))
227
230
228 (defm (root api set-array) (name value)
231 (defm (root api set-array) (name value)
229 (let ((store (this.var-ref name)))
232 (let ((store (this.var-ref name)))
230 (setf (ps:@ store values) (ps:@ value values))
233 (setf (ps:@ store values) (ps:@ value values))
231 (setf (ps:@ store indexes) (ps:@ value indexes)))
234 (setf (ps:@ store indexes) (ps:@ value indexes)))
232 (values))
235 (values))
233
236
234 (defm (root api kill-var) (name &optional index)
237 (defm (root api kill-var) (name &optional index)
235 (if (and index (not (= 0 index)))
238 (if (and index (not (= 0 index)))
236 (ps:chain (ps:getprop (root vars) name) (kill index))
239 (ps:chain (ps:getprop (root vars) name) (kill index))
237 (ps:delete (ps:getprop (root vars) name)))
240 (ps:delete (ps:getprop (root vars) name)))
238 (values))
241 (values))
239
242
240 (defm (root api array-size) (name)
243 (defm (root api array-size) (name)
241 (ps:getprop (this.var-ref name) 'length))
244 (ps:getprop (this.var-ref name) 'length))
242
245
243 ;;; Locals
246 ;;; Locals
244
247
245 (defm (root api push-local-frame) ()
248 (defm (root api push-local-frame) ()
246 (ps:chain (root locals) (push (ps:create)))
249 (ps:chain (root locals) (push (ps:create)))
247 (values))
250 (values))
248
251
249 (defm (root api pop-local-frame) ()
252 (defm (root api pop-local-frame) ()
250 (ps:chain (root locals) (pop))
253 (ps:chain (root locals) (pop))
251 (values))
254 (values))
252
255
253 (defm (root api current-local-frame) ()
256 (defm (root api current-local-frame) ()
254 (elt (root locals) (1- (length (root locals)))))
257 (elt (root locals) (1- (length (root locals)))))
255
258
256 (defm (root api new-local) (name)
259 (defm (root api new-local) (name)
257 (let ((frame (this.current-local-frame)))
260 (let ((frame (this.current-local-frame)))
258 (unless (in name frame)
261 (unless (in name frame)
259 (setf (ps:getprop frame name) (ps:create)))
262 (setf (ps:getprop frame name) (ps:create)))
260 (values)))
263 (values)))
261
264
262 ;;; Objects
265 ;;; Objects
263
266
264 (defm (root api update-objs) ()
267 (defm (root api update-objs) ()
265 (let ((elt (document.get-element-by-id "qsp-objs")))
268 (let ((elt (document.get-element-by-id "qsp-objs")))
266 (setf elt.inner-h-t-m-l "<ul>")
269 (setf elt.inner-h-t-m-l "<ul>")
267 (loop :for obj :in (root objs)
270 (loop :for obj :in (root objs)
268 :do (incf elt.inner-h-t-m-l (+ "<li>" obj)))
271 :do (incf elt.inner-h-t-m-l (+ "<li>" obj)))
269 (incf elt.inner-h-t-m-l "</ul>")))
272 (incf elt.inner-h-t-m-l "</ul>")))
270
273
271 ;;; Menu
274 ;;; Menu
272
275
273 (defm (root api menu) (menu-data)
276 (defm (root api menu) (menu-data)
274 (let ((elt (document.get-element-by-id "qsp-dropdown"))
277 (let ((elt (document.get-element-by-id "qsp-dropdown"))
275 (i 0))
278 (i 0))
276 (setf elt.inner-h-t-m-l "")
279 (setf elt.inner-h-t-m-l "")
277 (loop :for item :in menu-data
280 (loop :for item :in menu-data
278 :do (incf i)
281 :do (incf i)
279 :do (incf elt.inner-h-t-m-l (this.make-menu-item-html i item.text item.icon item.loc)))
282 :do (incf elt.inner-h-t-m-l (this.make-menu-item-html i item.text item.icon item.loc)))
280 (setf elt.style.display "block")))
283 (setf elt.style.display "block")))
281
284
282 ;;; Content
285 ;;; Content
283
286
284 (defm (root api clean-audio) ()
287 (defm (root api clean-audio) ()
285 (loop :for k :in (*object.keys (root playing))
288 (loop :for k :in (*object.keys (root playing))
286 :for v := (ps:getprop (root playing) k)
289 :for v := (ps:getprop (root playing) k)
287 :do (when (ps:@ v ended)
290 :do (when (ps:@ v ended)
288 (ps:delete (ps:@ (root playing) k)))))
291 (ps:delete (ps:@ (root playing) k)))))
289
292
290 (defm (root api show-image) (path)
293 (defm (root api show-image) (path)
291 (let ((img (document.get-element-by-id "qsp-image")))
294 (let ((img (document.get-element-by-id "qsp-image")))
292 (cond (path
295 (cond (path
293 (setf img.src path)
296 (setf img.src path)
294 (setf img.style.display "flex"))
297 (setf img.style.display "flex"))
295 (t
298 (t
296 (setf img.src "")
299 (setf img.src "")
297 (setf img.style.display "hidden")))))
300 (setf img.style.display "hidden")))))
298
301
299 ;;; Saves
302 ;;; Saves
300
303
301 (defm (root api opengame) ()
304 (defm (root api opengame) ()
302 (let ((element (document.create-element :input)))
305 (let ((element (document.create-element :input)))
303 (element.set-attribute :type :file)
306 (element.set-attribute :type :file)
304 (element.set-attribute :id :qsp-opengame)
307 (element.set-attribute :id :qsp-opengame)
305 (element.set-attribute :tabindex -1)
308 (element.set-attribute :tabindex -1)
306 (element.set-attribute "aria-hidden" t)
309 (element.set-attribute "aria-hidden" t)
307 (setf element.style.display :block)
310 (setf element.style.display :block)
308 (setf element.style.visibility :hidden)
311 (setf element.style.visibility :hidden)
309 (setf element.style.position :fixed)
312 (setf element.style.position :fixed)
310 (setf element.onchange
313 (setf element.onchange
311 (lambda (event)
314 (lambda (event)
312 (let* ((file (elt event.target.files 0))
315 (let* ((file (elt event.target.files 0))
313 (reader (ps:new (*file-reader))))
316 (reader (ps:new (*file-reader))))
314 (setf reader.onload
317 (setf reader.onload
315 (lambda (ev)
318 (lambda (ev)
316 (block nil
319 (block nil
317 (let ((target ev.current-target))
320 (let ((target ev.current-target))
318 (unless target.result
321 (unless target.result
319 (return))
322 (return))
320 (api-call base64-to-state target.result)
323 (api-call base64-to-state target.result)
321 (api-call unstash-state)))))
324 (api-call unstash-state)))))
322 (reader.read-as-text file))))
325 (reader.read-as-text file))))
323 (document.body.append-child element)
326 (document.body.append-child element)
324 (element.click)
327 (element.click)
325 (document.body.remove-child element)))
328 (document.body.remove-child element)))
326
329
327 (defm (root api savegame) ()
330 (defm (root api savegame) ()
328 (let ((element (document.create-element :a)))
331 (let ((element (document.create-element :a)))
329 (element.set-attribute :href (+ "data:text/plain;charset=utf-8," (api-call state-to-base64)))
332 (element.set-attribute :href (+ "data:text/plain;charset=utf-8," (api-call state-to-base64)))
330 (element.set-attribute :download "savegame.sav")
333 (element.set-attribute :download "savegame.sav")
331 (setf element.style.display :none)
334 (setf element.style.display :none)
332 (document.body.append-child element)
335 (document.body.append-child element)
333 (element.click)
336 (element.click)
334 (document.body.remove-child element)))
337 (document.body.remove-child element)))
335
338
336 (defm (root api stash-state) (args)
339 (defm (root api stash-state) (args)
337 (api-call call-serv-loc "ONGSAVE")
340 (api-call call-serv-loc "ONGSAVE")
338 (setf (root state-stash)
341 (setf (root state-stash)
339 (*j-s-o-n.stringify
342 (*j-s-o-n.stringify
340 (ps:create vars (root vars)
343 (ps:create vars (root vars)
341 objs (root objs)
344 objs (root objs)
342 loc-args args
345 loc-args args
343 msecs (- (*date.now) (root started-at))
346 msecs (- (*date.now) (root started-at))
344 main-html (ps:@
347 main-html (ps:@
345 (document.get-element-by-id :qsp-main)
348 (document.get-element-by-id :qsp-main)
346 inner-h-t-m-l)
349 inner-h-t-m-l)
347 stat-html (ps:@
350 stat-html (ps:@
348 (document.get-element-by-id :qsp-stat)
351 (document.get-element-by-id :qsp-stat)
349 inner-h-t-m-l)
352 inner-h-t-m-l)
350 next-location (root current-location))))
353 next-location (root current-location))))
351 (values))
354 (values))
352
355
353 (defm (root api unstash-state) ()
356 (defm (root api unstash-state) ()
354 (let ((data (*j-s-o-n.parse (root state-stash))))
357 (let ((data (*j-s-o-n.parse (root state-stash))))
355 (this.clear-act)
358 (this.clear-act)
356 (setf (root vars) (ps:@ data vars))
359 (setf (root vars) (ps:@ data vars))
357 (loop :for k :in (*object.keys (root vars))
360 (loop :for k :in (*object.keys (root vars))
358 :do (*object.set-prototype-of (ps:getprop (root vars) k)
361 :do (*object.set-prototype-of (ps:getprop (root vars) k)
359 (root api *var prototype)))
362 (root api *var prototype)))
360 (setf (root started-at) (- (*date.now) (ps:@ data msecs)))
363 (setf (root started-at) (- (*date.now) (ps:@ data msecs)))
361 (setf (root objs) (ps:@ data objs))
364 (setf (root objs) (ps:@ data objs))
362 (setf (root current-location) (ps:@ data next-location))
365 (setf (root current-location) (ps:@ data next-location))
363 (setf (ps:@ (document.get-element-by-id :qsp-main) inner-h-t-m-l)
366 (setf (ps:@ (document.get-element-by-id :qsp-main) inner-h-t-m-l)
364 (ps:@ data main-html))
367 (ps:@ data main-html))
365 (setf (ps:@ (document.get-element-by-id :qsp-stat) inner-h-t-m-l)
368 (setf (ps:@ (document.get-element-by-id :qsp-stat) inner-h-t-m-l)
366 (ps:@ data stat-html))
369 (ps:@ data stat-html))
367 (this.update-objs)
370 (this.update-objs)
368 (api-call call-serv-loc "ONGLOAD")
371 (api-call call-serv-loc "ONGLOAD")
369 (api-call call-loc (root current-location) (ps:@ data loc-args))
372 (api-call call-loc (root current-location) (ps:@ data loc-args))
370 (values)))
373 (values)))
371
374
372 (defm (root api state-to-base64) ()
375 (defm (root api state-to-base64) ()
373 (btoa (encode-u-r-i-component (root state-stash))))
376 (btoa (encode-u-r-i-component (root state-stash))))
374
377
375 (defm (root api base64-to-state) (data)
378 (defm (root api base64-to-state) (data)
376 (setf (root state-stash) (decode-u-r-i-component (atob data))))
379 (setf (root state-stash) (decode-u-r-i-component (atob data))))
377
380
378 ;;; Timers
381 ;;; Timers
379
382
380 (defm (root api set-timer) (interval)
383 (defm (root api set-timer) (interval)
381 (setf (root timer-interval) interval)
384 (setf (root timer-interval) interval)
382 (clear-interval (root timer-obj))
385 (clear-interval (root timer-obj))
383 (setf (root timer-obj)
386 (setf (root timer-obj)
384 (set-interval
387 (set-interval
385 (lambda ()
388 (lambda ()
386 (api-call call-serv-loc "COUNTER"))
389 (api-call call-serv-loc "COUNTER"))
387 interval)))
390 interval)))
@@ -1,302 +1,307 b''
1
1
2 (in-package sugar-qsp)
2 (in-package sugar-qsp)
3
3
4 ;;;; Functions and procedures defined by the QSP language.
4 ;;;; Functions and procedures defined by the QSP language.
5 ;;;; They can call api and deal with locations and other data directly.
5 ;;;; They can call api and deal with locations and other data directly.
6 ;;;; Except vars. Use VAR and SET or GET-VAR and SET-VAR api calls.
6 ;;;; Except vars. Use VAR and SET or GET-VAR and SET-VAR api calls.
7
7
8 (setf (root lib) (ps:create))
8 (setf (root lib) (ps:create))
9
9
10 ;;; 1loc
10 ;;; 1loc
11
11
12 (defm (root lib goto) (target args)
12 (defm (root lib goto) (target args)
13 (api-call clear-text :main)
13 (api-call clear-text :main)
14 (funcall (root lib xgoto) target (or args (list)))
14 (funcall (root lib xgoto) target (or args (list)))
15 (values))
15 (values))
16
16
17 (defm (root lib xgoto) (target args)
17 (defm (root lib xgoto) (target args)
18 (api-call clear-act)
18 (api-call clear-act)
19 (setf (root current-location) (ps:chain target (to-upper-case)))
19 (setf (root current-location) (ps:chain target (to-upper-case)))
20 (api-call stash-state args)
20 (api-call stash-state args)
21 (funcall (ps:getprop (root locs) (root current-location))
21 (funcall (ps:getprop (root locs) (root current-location))
22 (or args (list)))
22 (or args (list)))
23 (values))
23 (values))
24
24
25 ;;; 2var
25 ;;; 2var
26
26
27 ;;; 3expr
27 ;;; 3expr
28
28
29 ;;; 4code
29 ;;; 4code
30
30
31 (defm (root lib rand) (a &optional (b 1))
31 (defm (root lib rand) (a &optional (b 1))
32 (let ((min (min a b))
32 (let ((min (min a b))
33 (max (max a b)))
33 (max (max a b)))
34 (+ min (ps:chain *math (random (- max min))))))
34 (+ min (ps:chain *math (random (- max min))))))
35
35
36 ;;; 5arrays
36 ;;; 5arrays
37
37
38 (defm (root lib copyarr) (to from start count)
38 (defm (root lib copyarr) (to from start count)
39 (multiple-value-bind (to-name to-slot)
39 (multiple-value-bind (to-name to-slot)
40 (api-call var-real-name to)
40 (api-call var-real-name to)
41 (multiple-value-bind (from-name from-slot)
41 (multiple-value-bind (from-name from-slot)
42 (api-call var-real-name from)
42 (api-call var-real-name from)
43 (ps:for ((i start))
43 (ps:for ((i start))
44 ((< i (min (api-call array-size from-name)
44 ((< i (min (api-call array-size from-name)
45 (+ start count))))
45 (+ start count))))
46 ((incf i))
46 ((incf i))
47 (api-call set-var to-name (+ start i) to-slot
47 (api-call set-var to-name (+ start i) to-slot
48 (api-call get-var from-name (+ start i) from-slot))))))
48 (api-call get-var from-name (+ start i) from-slot))))))
49
49
50 (defm (root lib arrpos) (name value &optional (start 0))
50 (defm (root lib arrpos) (name value &optional (start 0))
51 (multiple-value-bind (real-name slot)
51 (multiple-value-bind (real-name slot)
52 (api-call var-real-name name)
52 (api-call var-real-name name)
53 (ps:for ((i start)) ((< i (api-call array-size name))) ((incf i))
53 (ps:for ((i start)) ((< i (api-call array-size name))) ((incf i))
54 (when (eq (api-call get-var real-name i slot) value)
54 (when (eq (api-call get-var real-name i slot) value)
55 (return i))))
55 (return i))))
56 -1)
56 -1)
57
57
58 (defm (root lib arrcomp) (name pattern &optional (start 0))
58 (defm (root lib arrcomp) (name pattern &optional (start 0))
59 (multiple-value-bind (real-name slot)
59 (multiple-value-bind (real-name slot)
60 (api-call var-real-name name)
60 (api-call var-real-name name)
61 (ps:for ((i start)) ((< i (api-call array-size name))) ((incf i))
61 (ps:for ((i start)) ((< i (api-call array-size name))) ((incf i))
62 (when (funcall (ps:getprop (api-call get-var real-name i slot) 'match) pattern)
62 (when (funcall (ps:getprop (api-call get-var real-name i slot) 'match) pattern)
63 (return i))))
63 (return i))))
64 -1)
64 -1)
65
65
66 ;;; 6str
66 ;;; 6str
67
67
68 (defm (root lib instr) (s subs &optional (start 1))
68 (defm (root lib instr) (s subs &optional (start 1))
69 (+ start (ps:chain s (substring (- start 1)) (search subs))))
69 (+ start (ps:chain s (substring (- start 1)) (search subs))))
70
70
71 (defm (root lib isnum) (s)
71 (defm (root lib isnum) (s)
72 (if (is-na-n s)
72 (if (is-na-n s)
73 0
73 0
74 -1))
74 -1))
75
75
76 (defm (root lib strcomp) (s pattern)
76 (defm (root lib strcomp) (s pattern)
77 (if (s.match pattern)
77 (if (s.match pattern)
78 -1
78 -1
79 0))
79 0))
80
80
81 (defm (root lib strfind) (s pattern group)
81 (defm (root lib strfind) (s pattern group)
82 (let* ((re (ps:new (*reg-exp pattern)))
82 (let* ((re (ps:new (*reg-exp pattern)))
83 (match (re.exec s)))
83 (match (re.exec s)))
84 (match.group group)))
84 (match.group group)))
85
85
86 (defm (root lib strpos) (s pattern &optional (group 0))
86 (defm (root lib strpos) (s pattern &optional (group 0))
87 (let* ((re (ps:new (*reg-exp pattern)))
87 (let* ((re (ps:new (*reg-exp pattern)))
88 (match (re.exec s))
88 (match (re.exec s))
89 (found (match.group group)))
89 (found (match.group group)))
90 (if found
90 (if found
91 (s.search found)
91 (s.search found)
92 0)))
92 0)))
93
93
94 ;;; 7if
94 ;;; 7if
95
95
96 ;; Has to be a function because it always evaluates all three of its
96 ;; Has to be a function because it always evaluates all three of its
97 ;; arguments
97 ;; arguments
98 (defm (root lib iif) (cond-expr then-expr else-expr)
98 (defm (root lib iif) (cond-expr then-expr else-expr)
99 (if cond-expr then-expr else-expr))
99 (if cond-expr then-expr else-expr))
100
100
101 ;;; 8sub
101 ;;; 8sub
102
102
103 (defm (root lib gosub) (target &rest args)
103 (defm (root lib gosub) (target &rest args)
104 (funcall (ps:getprop (root locs) target) args)
104 (funcall (ps:getprop (root locs) target) args)
105 (values))
105 (values))
106
106
107 (defm (root lib func) (target &rest args)
107 (defm (root lib func) (target &rest args)
108 (funcall (ps:getprop (root locs) target) args))
108 (funcall (ps:getprop (root locs) target) args))
109
109
110 ;;; 9loops
110 ;;; 9loops
111
111
112 ;;; 10dynamic
112 ;;; 10dynamic
113
113
114 (defm (root lib dynamic) (block &rest args)
114 (defm (root lib dynamic) (block &rest args)
115 (when (stringp block)
115 (when (stringp block)
116 (api-call report-error "DYNAMIC can't evaluate arbitrary strings.\nUse {braces} to create blocks for DYNAMIC."))
116 (api-call report-error "DYNAMIC can't evaluate arbitrary strings.\nUse {braces} to create blocks for DYNAMIC."))
117 (funcall block args)
117 (funcall block args)
118 (values))
118 (values))
119
119
120 (defm (root lib dyneval) (block &rest args)
120 (defm (root lib dyneval) (block &rest args)
121 (when (stringp block)
121 (when (stringp block)
122 (api-call report-error "DYNEVAL can't evaluate arbitrary strings.\nUse {braces} to create blocks for DYNEVAL."))
122 (api-call report-error "DYNEVAL can't evaluate arbitrary strings.\nUse {braces} to create blocks for DYNEVAL."))
123 (funcall block args))
123 (funcall block args))
124
124
125 ;;; 11main
125 ;;; 11main
126
126
127 (defm (root lib main-p) (s)
127 (defm (root lib main-p) (s)
128 (api-call add-text :main s)
128 (api-call add-text :main s)
129 (values))
129 (values))
130
130
131 (defm (root lib main-pl) (s)
131 (defm (root lib main-pl) (s)
132 (api-call add-text :main s)
132 (api-call add-text :main s)
133 (api-call newline :main)
133 (api-call newline :main)
134 (values))
134 (values))
135
135
136 (defm (root lib main-nl) (s)
136 (defm (root lib main-nl) (s)
137 (api-call newline :main)
137 (api-call newline :main)
138 (api-call add-text :main s)
138 (api-call add-text :main s)
139 (values))
139 (values))
140
140
141 (defm (root lib maintxt) (s)
141 (defm (root lib maintxt) (s)
142 (api-call get-text :main)
142 (api-call get-text :main)
143 (values))
143 (values))
144
144
145 ;; For clarity (it leaves a lib.desc() call in JS)
145 ;; For clarity (it leaves a lib.desc() call in JS)
146 (defm (root lib desc) (s)
146 (defm (root lib desc) (s)
147 "")
147 "")
148
148
149 (defm (root lib main-clear) ()
149 (defm (root lib main-clear) ()
150 (api-call clear-text :main)
150 (api-call clear-text :main)
151 (values))
151 (values))
152
152
153 ;;; 12stat
153 ;;; 12stat
154
154
155 (defm (root lib stat-p) (s)
155 (defm (root lib stat-p) (s)
156 (api-call add-text :stat s)
156 (api-call add-text :stat s)
157 (values))
157 (values))
158
158
159 (defm (root lib stat-pl) (s)
159 (defm (root lib stat-pl) (s)
160 (api-call add-text :stat s)
160 (api-call add-text :stat s)
161 (api-call newline :stat)
161 (api-call newline :stat)
162 (values))
162 (values))
163
163
164 (defm (root lib stat-nl) (s)
164 (defm (root lib stat-nl) (s)
165 (api-call newline :stat)
165 (api-call newline :stat)
166 (api-call add-text :stat s)
166 (api-call add-text :stat s)
167 (values))
167 (values))
168
168
169 (defm (root lib stattxt) (s)
169 (defm (root lib stattxt) (s)
170 (api-call get-text :stat)
170 (api-call get-text :stat)
171 (values))
171 (values))
172
172
173 (defm (root lib stat-clear) ()
173 (defm (root lib stat-clear) ()
174 (api-call clear-text :stat)
174 (api-call clear-text :stat)
175 (values))
175 (values))
176
176
177 (defm (root lib cls) ()
177 (defm (root lib cls) ()
178 (funcall (root lib stat-clear))
178 (funcall (root lib stat-clear))
179 (funcall (root lib main-clear))
179 (funcall (root lib main-clear))
180 (funcall (root lib cla))
180 (funcall (root lib cla))
181 (funcall (root lib cmdclear))
181 (funcall (root lib cmdclear))
182 (values))
182 (values))
183
183
184 ;;; 13diag
184 ;;; 13diag
185
185
186 ;;; 14act
186 ;;; 14act
187
187
188 (defm (root lib curacts) ()
188 (defm (root lib curacts) ()
189 (let ((acts (root acts)))
189 (let ((acts (root acts)))
190 (lambda ()
190 (lambda ()
191 (setf (root acts) acts)
191 (setf (root acts) acts)
192 (values))))
192 (values))))
193
193
194 ;;; 15objs
194 ;;; 15objs
195
195
196 (defm (root lib addobj) (name)
196 (defm (root lib addobj) (name)
197 (ps:chain (root objs) (push name))
197 (ps:chain (root objs) (push name))
198 (api-call update-objs)
198 (api-call update-objs)
199 (values))
199 (values))
200
200
201 (defm (root lib delobj) (name)
201 (defm (root lib delobj) (name)
202 (let ((index (ps:chain (root objs) (index-of name))))
202 (let ((index (ps:chain (root objs) (index-of name))))
203 (when (> index -1)
203 (when (> index -1)
204 (funcall (root lib killobj) (1+ index))))
204 (funcall (root lib killobj) (1+ index))))
205 (values))
205 (values))
206
206
207 (defm (root lib killobj) (&optional (num nil))
207 (defm (root lib killobj) (&optional (num nil))
208 (if (eq nil num)
208 (if (eq nil num)
209 (setf (root objs) (list))
209 (setf (root objs) (list))
210 (ps:chain (root objs) (splice (1- num) 1)))
210 (ps:chain (root objs) (splice (1- num) 1)))
211 (api-call update-objs)
211 (api-call update-objs)
212 (values))
212 (values))
213
213
214 ;;; 16menu
214 ;;; 16menu
215
215
216 (defm (root lib menu) (menu-name)
216 (defm (root lib menu) (menu-name)
217 (let ((menu-data (list)))
217 (let ((menu-data (list)))
218 (loop :for item :in (api-call get-array (api-call var-real-name menu-name))
218 (loop :for item :in (api-call get-array (api-call var-real-name menu-name))
219 :do (cond ((string= item "")
219 :do (cond ((string= item "")
220 (break))
220 (break))
221 ((string= item "-:-")
221 ((string= item "-:-")
222 (ps:chain menu-data (push :delimiter)))
222 (ps:chain menu-data (push :delimiter)))
223 (t
223 (t
224 (let* ((tokens (ps:chain item (split ":"))))
224 (let* ((tokens (ps:chain item (split ":"))))
225 (when (= (length tokens) 2)
225 (when (= (length tokens) 2)
226 (tokens.push ""))
226 (tokens.push ""))
227 (let* ((text (ps:chain tokens (splice 0 (- tokens.length 2)) (join ":")))
227 (let* ((text (ps:chain tokens (splice 0 (- tokens.length 2)) (join ":")))
228 (loc (ps:getprop tokens (- tokens.length 2)))
228 (loc (ps:getprop tokens (- tokens.length 2)))
229 (icon (ps:getprop tokens (- tokens.length 1))))
229 (icon (ps:getprop tokens (- tokens.length 1))))
230 (ps:chain menu-data
230 (ps:chain menu-data
231 (push (ps:create text text
231 (push (ps:create text text
232 loc loc
232 loc loc
233 icon icon))))))))
233 icon icon))))))))
234 (api-call menu menu-data)
234 (api-call menu menu-data)
235 (values)))
235 (values)))
236
236
237 ;;; 17sound
237 ;;; 17sound
238
238
239 (defm (root lib play) (filename &optional (volume 100))
239 (defm (root lib play) (filename &optional (volume 100))
240 (let ((audio (ps:new (*audio filename))))
240 (let ((audio (ps:new (*audio filename))))
241 (setf (ps:getprop (root playing) filename) audio)
241 (setf (ps:getprop (root playing) filename) audio)
242 (setf (ps:@ audio volume) (* volume 0.01))
242 (setf (ps:@ audio volume) (* volume 0.01))
243 (ps:chain audio (play))))
243 (ps:chain audio (play))))
244
244
245 (defm (root lib close) (filename)
245 (defm (root lib close) (filename)
246 (funcall (root playing filename) stop)
246 (funcall (root playing filename) stop)
247 (ps:delete (root playing filename)))
247 (ps:delete (root playing filename)))
248
248
249 (defm (root lib closeall) ()
249 (defm (root lib closeall) ()
250 (loop :for k :in (*object.keys (root playing))
250 (loop :for k :in (*object.keys (root playing))
251 :for v := (ps:getprop (root playing) k)
251 :for v := (ps:getprop (root playing) k)
252 :do (funcall v stop))
252 :do (funcall v stop))
253 (setf (root playing) (ps:create)))
253 (setf (root playing) (ps:create)))
254
254
255 ;;; 18img
255 ;;; 18img
256
256
257 (defm (root lib refint) ()
257 (defm (root lib refint) ()
258 ;; "Force interface update" Uh... what exactly do we do here?
258 ;; "Force interface update" Uh... what exactly do we do here?
259 (api-call report-error "REFINT is not supported")
259 (api-call report-error "REFINT is not supported")
260 )
260 )
261
261
262 ;;; 19input
262 ;;; 19input
263
263
264 (defm (root lib usertxt) ()
264 (defm (root lib usertxt) ()
265 (let ((input (document.get-element-by-id "qsp-input")))
265 (let ((input (document.get-element-by-id "qsp-input")))
266 (ps:@ input value)))
266 (ps:@ input value)))
267
267
268 (defm (root lib cmdclear) ()
268 (defm (root lib cmdclear) ()
269 (let ((input (document.get-element-by-id "qsp-input")))
269 (let ((input (document.get-element-by-id "qsp-input")))
270 (setf (ps:@ input value) "")))
270 (setf (ps:@ input value) "")))
271
271
272 (defm (root lib input) (text)
272 (defm (root lib input) (text)
273 (window.prompt text))
273 (window.prompt text))
274
274
275 ;;; 20time
275 ;;; 20time
276
276
277 ;; I wonder if there's a better solution than busy-wait
277 ;; I wonder if there's a better solution than busy-wait
278 (defm (root lib wait) (msec)
278 (defm (root lib wait) (msec)
279 (let* ((now (ps:new (*date)))
279 (let* ((now (ps:new (*date)))
280 (exit-time (+ (funcall now.get-time) msec)))
280 (exit-time (+ (funcall now.get-time) msec)))
281 (loop :while (< (funcall now.get-time) exit-time))))
281 (loop :while (< (funcall now.get-time) exit-time))))
282
282
283 (defm (root lib msecscount) ()
283 (defm (root lib msecscount) ()
284 (- (*date.now) (root started-at)))
284 (- (*date.now) (root started-at)))
285
285
286 ;;; 21local
286 ;;; 21local
287
287
288 ;;; 22for
288 ;;; 22for
289
289
290 ;;; misc
290 ;;; misc
291
291
292 (defm (root lib rgb) ()
292 (defm (root lib rgb) (red green blue)
293 (api-call report-error "RGB is not implemented."))
293 (flet ((rgb-to-hex (comp)
294 (let ((hex (ps:chain (*number comp) (to-string 16))))
295 (if (< (length hex) 2)
296 (+ "0" hex)
297 hex))))
298 (+ "#" (rgb-to-hex red) (rgb-to-hex green) (rgb-to-hex red))))
294
299
295 (defm (root lib openqst) ()
300 (defm (root lib openqst) ()
296 (api-call report-error "OPENQST is not supported."))
301 (api-call report-error "OPENQST is not supported."))
297
302
298 (defm (root lib addqst) ()
303 (defm (root lib addqst) ()
299 (api-call report-error "ADDQST is not supported. Bundle the library with the main game."))
304 (api-call report-error "ADDQST is not supported. Bundle the library with the main game."))
300
305
301 (defm (root lib killqst) ()
306 (defm (root lib killqst) ()
302 (api-call report-error "KILLQST is not supported."))
307 (api-call report-error "KILLQST is not supported."))
@@ -1,13 +1,14 b''
1
1
2 (defsystem sugar-qsp
2 (defsystem sugar-qsp
3 :description "QSP compiler to monolithic HTML page"
3 :description "QSP compiler to monolithic HTML page"
4 :depends-on (:alexandria :esrap
4 :depends-on (:alexandria :esrap
5 :parenscript :parse-js :cl-uglify-js :flute)
5 :parenscript :parse-js :cl-uglify-js :flute)
6 :pathname "src/"
6 :pathname "src/"
7 :serial t
7 :serial t
8 :components ((:file "package")
8 :components ((:file "package")
9 (:file "patches")
9 (:file "ps-macros")
10 (:file "ps-macros")
10 (:file "intrinsic-macros")
11 (:file "intrinsic-macros")
11 (:file "class")
12 (:file "class")
12 (:file "main")
13 (:file "main")
13 (:file "parser")))
14 (:file "parser")))
General Comments 0
You need to be logged in to leave comments. Login now