##// END OF EJS Templates
WAIT with async
naryl -
r24:2cc68984 default
parent child Browse files
Show More
@@ -1,14 +1,16 b''
1
1
2 * Use async/await
2 * Use Parenscript's packages
3 * Use Parenscript's minifier
3 * Use Parenscript's minifier
4 * WAIT and MENU with async/await
4 * Remove dots
5 * MENU with async/await
6 * Find a way to minify syntax (extra returns at least)
5 * Special locations
7 * Special locations
6 * Special variables
8 * Special variables
7 * CLI build for Linux
9 * CLI build for Linux
8 * CLI build for Windows
10 * CLI build for Windows
9
11
10 * Build Istreblenie
12 * Build Istreblenie
11 * Windows GUI (for the compiler)
13 * Windows GUI (for the compiler)
12 * Save-load game in slots
14 * Save-load game in slots
13 * Resizable frames
15 * Resizable frames
14 ** modifying it to suit compiler specifics
16 ** modifying it to suit compiler specifics
@@ -1,393 +1,396 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.api.callAct(\"" title "\");'>"
14 (+ "<a class='qsp-act' href='#' onclick='SugarQSP.api.callAct(\"" title "\");'>"
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 sleep) (msec)
28 (ps:new (*promise (ps:=> resolve (set-timeout resolve msec)))))
29
27 (defm (root api init-dom) ()
30 (defm (root api init-dom) ()
28 ;; Save/load buttons
31 ;; Save/load buttons
29 (let ((btn (document.get-element-by-id "qsp-btn-save")))
32 (let ((btn (document.get-element-by-id "qsp-btn-save")))
30 (setf (ps:@ btn onclick) this.savegame)
33 (setf (ps:@ btn onclick) this.savegame)
31 (setf (ps:@ btn href) "#"))
34 (setf (ps:@ btn href) "#"))
32 (let ((btn (document.get-element-by-id "qsp-btn-open")))
35 (let ((btn (document.get-element-by-id "qsp-btn-open")))
33 (setf (ps:@ btn onclick) this.opengame)
36 (setf (ps:@ btn onclick) this.opengame)
34 (setf (ps:@ btn href) "#"))
37 (setf (ps:@ btn href) "#"))
35 ;; Close image on click
38 ;; Close image on click
36 (setf (ps:@ (document.get-element-by-id "qsp-image-container") onclick)
39 (setf (ps:@ (document.get-element-by-id "qsp-image-container") onclick)
37 (this.show-image nil))
40 (this.show-image nil))
38 ;; Close the dropdown on any click
41 ;; Close the dropdown on any click
39 (setf window.onclick
42 (setf window.onclick
40 (lambda (event)
43 (lambda (event)
41 (setf (ps:@ (api-call get-frame :dropdown) style display) "none"))))
44 (setf (ps:@ (api-call get-frame :dropdown) style display) "none"))))
42
45
43 (defm (root api call-serv-loc) (var-name &rest args)
46 (defm (root api call-serv-loc) (var-name &rest args)
44 (let ((loc-name (api-call get-var name 0 :str)))
47 (let ((loc-name (api-call get-var name 0 :str)))
45 (when loc-name
48 (when loc-name
46 (let ((loc (ps:getprop (root locs) loc-name)))
49 (let ((loc (ps:getprop (root locs) loc-name)))
47 (when loc
50 (when loc
48 (funcall loc args))))))
51 (funcall loc args))))))
49
52
50 ;;; Misc
53 ;;; Misc
51
54
52 (defm (root api newline) (key)
55 (defm (root api newline) (key)
53 (this.append-id (this.key-to-id key) "<br>" t))
56 (this.append-id (this.key-to-id key) "<br>" t))
54
57
55 (defm (root api clear-id) (id)
58 (defm (root api clear-id) (id)
56 (setf (ps:inner-html (document.get-element-by-id id)) ""))
59 (setf (ps:inner-html (document.get-element-by-id id)) ""))
57
60
58 (setf (root api text-escaper) (document.create-element :textarea))
61 (setf (root api text-escaper) (document.create-element :textarea))
59
62
60 (defm (root api prepare-contents) (s &optional force-html)
63 (defm (root api prepare-contents) (s &optional force-html)
61 (if (or force-html (var "USEHTML" 0 :num))
64 (if (or force-html (var "USEHTML" 0 :num))
62 s
65 s
63 (progn
66 (progn
64 (setf (ps:@ (root api text-escaper) text-content) s)
67 (setf (ps:@ (root api text-escaper) text-content) s)
65 (ps:inner-html (root api text-escaper)))))
68 (ps:inner-html (root api text-escaper)))))
66
69
67 (defm (root api get-id) (id &optional force-html)
70 (defm (root api get-id) (id &optional force-html)
68 (ps:inner-html (document.get-element-by-id id)))
71 (ps:inner-html (document.get-element-by-id id)))
69
72
70 (defm (root api set-id) (id contents &optional force-html)
73 (defm (root api set-id) (id contents &optional force-html)
71 (setf (ps:inner-html (document.get-element-by-id id)) (this.prepare-contents contents force-html)))
74 (setf (ps:inner-html (document.get-element-by-id id)) (this.prepare-contents contents force-html)))
72
75
73 (defm (root api append-id) (id contents &optional force-html)
76 (defm (root api append-id) (id contents &optional force-html)
74 (when contents
77 (when contents
75 (incf (ps:inner-html (document.get-element-by-id id)) (this.prepare-contents contents force-html))))
78 (incf (ps:inner-html (document.get-element-by-id id)) (this.prepare-contents contents force-html))))
76
79
77 ;;; Function calls
80 ;;; Function calls
78
81
79 (defm (root api init-args) (args)
82 (defm (root api init-args) (args)
80 (dotimes (i (length args))
83 (dotimes (i (length args))
81 (let ((arg (elt args i)))
84 (let ((arg (elt args i)))
82 (if (numberp arg)
85 (if (numberp arg)
83 (this.set-var args i :num arg)
86 (this.set-var args i :num arg)
84 (this.set-var args i :str arg)))))
87 (this.set-var args i :str arg)))))
85
88
86 (defm (root api get-result) ()
89 (defm (root api get-result) ()
87 (if (not (equal "" (var result 0 :str)))
90 (if (not (equal "" (var result 0 :str)))
88 (var result 0 :str)
91 (var result 0 :str)
89 (var result 0 :num)))
92 (var result 0 :num)))
90
93
91 (defm (root api call-loc) (name args)
94 (defm (root api call-loc) (name args)
92 (with-frame
95 (with-frame
93 (funcall (ps:getprop (root locs) name) args)))
96 (funcall (ps:getprop (root locs) name) args)))
94
97
95 (defm (root api call-act) (title)
98 (defm (root api call-act) (title)
96 (with-frame
99 (with-frame
97 (funcall (ps:getprop (root acts) title))))
100 (funcall (ps:getprop (root acts) title))))
98
101
99 ;;; Text windows
102 ;;; Text windows
100
103
101 (defm (root api key-to-id) (key)
104 (defm (root api key-to-id) (key)
102 (case key
105 (case key
103 (:main "qsp-main")
106 (:main "qsp-main")
104 (:stat "qsp-stat")
107 (:stat "qsp-stat")
105 (:objs "qsp-objs")
108 (:objs "qsp-objs")
106 (:acts "qsp-acts")
109 (:acts "qsp-acts")
107 (:input "qsp-input")
110 (:input "qsp-input")
108 (:dropdown "qsp-dropdown")
111 (:dropdown "qsp-dropdown")
109 (t (this.report-error "Internal error!"))))
112 (t (this.report-error "Internal error!"))))
110
113
111 (defm (root api get-frame) (key)
114 (defm (root api get-frame) (key)
112 (document.get-element-by-id (this.key-to-id key)))
115 (document.get-element-by-id (this.key-to-id key)))
113
116
114 (defm (root api add-text) (key text)
117 (defm (root api add-text) (key text)
115 (this.append-id (this.key-to-id key) text))
118 (this.append-id (this.key-to-id key) text))
116
119
117 (defm (root api get-text) (key)
120 (defm (root api get-text) (key)
118 (this.get-id (this.key-to-id key)))
121 (this.get-id (this.key-to-id key)))
119
122
120 (defm (root api clear-text) (key)
123 (defm (root api clear-text) (key)
121 (this.clear-id (this.key-to-id key)))
124 (this.clear-id (this.key-to-id key)))
122
125
123 (defm (root api enable-frame) (key enable)
126 (defm (root api enable-frame) (key enable)
124 (let ((obj (this.get-frame key)))
127 (let ((obj (this.get-frame key)))
125 (setf obj.style.display (if enable "block" "none"))
128 (setf obj.style.display (if enable "block" "none"))
126 (values)))
129 (values)))
127
130
128 ;;; Actions
131 ;;; Actions
129
132
130 (defm (root api add-act) (title img act)
133 (defm (root api add-act) (title img act)
131 (setf (ps:getprop (root acts) title)
134 (setf (ps:getprop (root acts) title)
132 (ps:create :img img :act act))
135 (ps:create :img img :act act))
133 (this.update-acts))
136 (this.update-acts))
134
137
135 (defm (root api del-act) (title)
138 (defm (root api del-act) (title)
136 (delete (ps:getprop (root acts) title))
139 (delete (ps:getprop (root acts) title))
137 (this.update-acts))
140 (this.update-acts))
138
141
139 (defm (root api clear-act) ()
142 (defm (root api clear-act) ()
140 (setf (root acts) (ps:create))
143 (setf (root acts) (ps:create))
141 (this.clear-id "qsp-acts"))
144 (this.clear-id "qsp-acts"))
142
145
143 (defm (root api update-acts) ()
146 (defm (root api update-acts) ()
144 (this.clear-id "qsp-acts")
147 (this.clear-id "qsp-acts")
145 (let ((elt (document.get-element-by-id "qsp-acts")))
148 (let ((elt (document.get-element-by-id "qsp-acts")))
146 (ps:for-in (title (root acts))
149 (ps:for-in (title (root acts))
147 (let ((obj (ps:getprop (root acts) title)))
150 (let ((obj (ps:getprop (root acts) title)))
148 (incf (ps:inner-html elt) (this.make-act-html title (ps:getprop obj :img)))))))
151 (incf (ps:inner-html elt) (this.make-act-html title (ps:getprop obj :img)))))))
149
152
150
153
151 ;;; "Syntax"
154 ;;; "Syntax"
152
155
153 (defm (root api qspfor) (name index from to step body)
156 (defm (root api qspfor) (name index from to step body)
154 (block nil
157 (block nil
155 (ps:for ((i from))
158 (ps:for ((i from))
156 ((< i to))
159 ((< i to))
157 ((incf i step))
160 ((incf i step))
158 (this.set-var name index :num i)
161 (this.set-var name index :num i)
159 (unless (funcall body)
162 (unless (funcall body)
160 (return)))))
163 (return)))))
161
164
162 ;;; Variable class
165 ;;; Variable class
163
166
164 (defm (root api *var) (name)
167 (defm (root api *var) (name)
165 ;; From strings to numbers
168 ;; From strings to numbers
166 (setf this.indexes (ps:create))
169 (setf this.indexes (ps:create))
167 ;; From numbers to {num: 0, str: ""} objects
170 ;; From numbers to {num: 0, str: ""} objects
168 (setf this.values (list))
171 (setf this.values (list))
169 (values))
172 (values))
170
173
171 (defm (root api *var prototype new-value) ()
174 (defm (root api *var prototype new-value) ()
172 (ps:create :num 0 :str ""))
175 (ps:create :num 0 :str ""))
173
176
174 (defm (root api *var prototype index-num) (index)
177 (defm (root api *var prototype index-num) (index)
175 (let ((num-index
178 (let ((num-index
176 (if (stringp index)
179 (if (stringp index)
177 (if (in index this.indexes)
180 (if (in index this.indexes)
178 (ps:getprop this.indexes index)
181 (ps:getprop this.indexes index)
179 (let ((n (length this.values)))
182 (let ((n (length this.values)))
180 (setf (ps:getprop this.indexes index) n)
183 (setf (ps:getprop this.indexes index) n)
181 n))
184 n))
182 index)))
185 index)))
183 (unless (in num-index this.values)
186 (unless (in num-index this.values)
184 (setf (elt this.values num-index) (this.new-value)))
187 (setf (elt this.values num-index) (this.new-value)))
185 num-index))
188 num-index))
186
189
187 (defm (root api *var prototype get) (index slot)
190 (defm (root api *var prototype get) (index slot)
188 (unless (or index (= 0 index))
191 (unless (or index (= 0 index))
189 (setf index (1- (length this.values))))
192 (setf index (1- (length this.values))))
190 (ps:getprop this.values (this.index-num index) slot))
193 (ps:getprop this.values (this.index-num index) slot))
191
194
192 (defm (root api *var prototype set) (index slot value)
195 (defm (root api *var prototype set) (index slot value)
193 (unless (or index (= 0 index))
196 (unless (or index (= 0 index))
194 (setf index (length store)))
197 (setf index (length store)))
195 (case slot
198 (case slot
196 (:num (setf value (ps:chain *number (parse-int value))))
199 (:num (setf value (ps:chain *number (parse-int value))))
197 (:str (setf value (ps:chain value (to-string)))))
200 (:str (setf value (ps:chain value (to-string)))))
198 (setf (ps:getprop this.values (this.index-num index) slot) value)
201 (setf (ps:getprop this.values (this.index-num index) slot) value)
199 (values))
202 (values))
200
203
201 (defm (root api *var prototype kill) (index)
204 (defm (root api *var prototype kill) (index)
202 (setf (elt this.values (this.index-num index)) (this.new-value)))
205 (setf (elt this.values (this.index-num index)) (this.new-value)))
203
206
204 ;;; Variables
207 ;;; Variables
205
208
206 (defm (root api var-real-name) (name)
209 (defm (root api var-real-name) (name)
207 (if (= (ps:@ name 0) #\$)
210 (if (= (ps:@ name 0) #\$)
208 (values (ps:chain name (substr 1)) :str)
211 (values (ps:chain name (substr 1)) :str)
209 (values name :num)))
212 (values name :num)))
210
213
211 (defm (root api ensure-var) (name)
214 (defm (root api ensure-var) (name)
212 (let ((store (this.var-ref name)))
215 (let ((store (this.var-ref name)))
213 (unless store
216 (unless store
214 (setf store (ps:new (this.-var name)))
217 (setf store (ps:new (this.-var name)))
215 (setf (ps:getprop (root vars) name) store))
218 (setf (ps:getprop (root vars) name) store))
216 store))
219 store))
217
220
218 (defm (root api var-ref) (name)
221 (defm (root api var-ref) (name)
219 (let ((local-store (this.current-local-frame)))
222 (let ((local-store (this.current-local-frame)))
220 (cond ((and local-store (in name local-store))
223 (cond ((and local-store (in name local-store))
221 (ps:getprop local-store name))
224 (ps:getprop local-store name))
222 ((in name (root vars))
225 ((in name (root vars))
223 (ps:getprop (root vars) name))
226 (ps:getprop (root vars) name))
224 (t nil))))
227 (t nil))))
225
228
226 (defm (root api get-var) (name index slot)
229 (defm (root api get-var) (name index slot)
227 (ps:chain (this.ensure-var name) (get index slot)))
230 (ps:chain (this.ensure-var name) (get index slot)))
228
231
229 (defm (root api set-var) (name index slot value)
232 (defm (root api set-var) (name index slot value)
230 (ps:chain (this.ensure-var name) (set index slot value))
233 (ps:chain (this.ensure-var name) (set index slot value))
231 (values))
234 (values))
232
235
233 (defm (root api get-array) (name)
236 (defm (root api get-array) (name)
234 (this.var-ref name))
237 (this.var-ref name))
235
238
236 (defm (root api set-array) (name value)
239 (defm (root api set-array) (name value)
237 (let ((store (this.var-ref name)))
240 (let ((store (this.var-ref name)))
238 (setf (ps:@ store values) (ps:@ value values))
241 (setf (ps:@ store values) (ps:@ value values))
239 (setf (ps:@ store indexes) (ps:@ value indexes)))
242 (setf (ps:@ store indexes) (ps:@ value indexes)))
240 (values))
243 (values))
241
244
242 (defm (root api kill-var) (name &optional index)
245 (defm (root api kill-var) (name &optional index)
243 (if (and index (not (= 0 index)))
246 (if (and index (not (= 0 index)))
244 (ps:chain (ps:getprop (root vars) name) (kill index))
247 (ps:chain (ps:getprop (root vars) name) (kill index))
245 (ps:delete (ps:getprop (root vars) name)))
248 (ps:delete (ps:getprop (root vars) name)))
246 (values))
249 (values))
247
250
248 (defm (root api array-size) (name)
251 (defm (root api array-size) (name)
249 (ps:getprop (this.var-ref name) 'length))
252 (ps:getprop (this.var-ref name) 'length))
250
253
251 ;;; Locals
254 ;;; Locals
252
255
253 (defm (root api push-local-frame) ()
256 (defm (root api push-local-frame) ()
254 (ps:chain (root locals) (push (ps:create)))
257 (ps:chain (root locals) (push (ps:create)))
255 (values))
258 (values))
256
259
257 (defm (root api pop-local-frame) ()
260 (defm (root api pop-local-frame) ()
258 (ps:chain (root locals) (pop))
261 (ps:chain (root locals) (pop))
259 (values))
262 (values))
260
263
261 (defm (root api current-local-frame) ()
264 (defm (root api current-local-frame) ()
262 (elt (root locals) (1- (length (root locals)))))
265 (elt (root locals) (1- (length (root locals)))))
263
266
264 (defm (root api new-local) (name)
267 (defm (root api new-local) (name)
265 (let ((frame (this.current-local-frame)))
268 (let ((frame (this.current-local-frame)))
266 (unless (in name frame)
269 (unless (in name frame)
267 (setf (ps:getprop frame name) (ps:create)))
270 (setf (ps:getprop frame name) (ps:create)))
268 (values)))
271 (values)))
269
272
270 ;;; Objects
273 ;;; Objects
271
274
272 (defm (root api update-objs) ()
275 (defm (root api update-objs) ()
273 (let ((elt (document.get-element-by-id "qsp-objs")))
276 (let ((elt (document.get-element-by-id "qsp-objs")))
274 (setf (ps:inner-html elt) "<ul>")
277 (setf (ps:inner-html elt) "<ul>")
275 (loop :for obj :in (root objs)
278 (loop :for obj :in (root objs)
276 :do (incf (ps:inner-html elt) (+ "<li>" obj)))
279 :do (incf (ps:inner-html elt) (+ "<li>" obj)))
277 (incf (ps:inner-html elt) "</ul>")))
280 (incf (ps:inner-html elt) "</ul>")))
278
281
279 ;;; Menu
282 ;;; Menu
280
283
281 (defm (root api menu) (menu-data)
284 (defm (root api menu) (menu-data)
282 (let ((elt (document.get-element-by-id "qsp-dropdown"))
285 (let ((elt (document.get-element-by-id "qsp-dropdown"))
283 (i 0))
286 (i 0))
284 (setf (ps:inner-html elt) "")
287 (setf (ps:inner-html elt) "")
285 (loop :for item :in menu-data
288 (loop :for item :in menu-data
286 :do (incf i)
289 :do (incf i)
287 :do (incf (ps:inner-html elt) (this.make-menu-item-html i item.text item.icon item.loc)))
290 :do (incf (ps:inner-html elt) (this.make-menu-item-html i item.text item.icon item.loc)))
288 (setf elt.style.display "block")))
291 (setf elt.style.display "block")))
289
292
290 ;;; Content
293 ;;; Content
291
294
292 (defm (root api clean-audio) ()
295 (defm (root api clean-audio) ()
293 (loop :for k :in (*object.keys (root playing))
296 (loop :for k :in (*object.keys (root playing))
294 :for v := (ps:getprop (root playing) k)
297 :for v := (ps:getprop (root playing) k)
295 :do (when (ps:@ v ended)
298 :do (when (ps:@ v ended)
296 (ps:delete (ps:@ (root playing) k)))))
299 (ps:delete (ps:@ (root playing) k)))))
297
300
298 (defm (root api show-image) (path)
301 (defm (root api show-image) (path)
299 (let ((img (document.get-element-by-id "qsp-image")))
302 (let ((img (document.get-element-by-id "qsp-image")))
300 (cond (path
303 (cond (path
301 (setf img.src path)
304 (setf img.src path)
302 (setf img.style.display "flex"))
305 (setf img.style.display "flex"))
303 (t
306 (t
304 (setf img.src "")
307 (setf img.src "")
305 (setf img.style.display "hidden")))))
308 (setf img.style.display "hidden")))))
306
309
307 ;;; Saves
310 ;;; Saves
308
311
309 (defm (root api opengame) ()
312 (defm (root api opengame) ()
310 (let ((element (document.create-element :input)))
313 (let ((element (document.create-element :input)))
311 (element.set-attribute :type :file)
314 (element.set-attribute :type :file)
312 (element.set-attribute :id :qsp-opengame)
315 (element.set-attribute :id :qsp-opengame)
313 (element.set-attribute :tabindex -1)
316 (element.set-attribute :tabindex -1)
314 (element.set-attribute "aria-hidden" t)
317 (element.set-attribute "aria-hidden" t)
315 (setf element.style.display :block)
318 (setf element.style.display :block)
316 (setf element.style.visibility :hidden)
319 (setf element.style.visibility :hidden)
317 (setf element.style.position :fixed)
320 (setf element.style.position :fixed)
318 (setf element.onchange
321 (setf element.onchange
319 (lambda (event)
322 (lambda (event)
320 (let* ((file (elt event.target.files 0))
323 (let* ((file (elt event.target.files 0))
321 (reader (ps:new (*file-reader))))
324 (reader (ps:new (*file-reader))))
322 (setf reader.onload
325 (setf reader.onload
323 (lambda (ev)
326 (lambda (ev)
324 (block nil
327 (block nil
325 (let ((target ev.current-target))
328 (let ((target ev.current-target))
326 (unless target.result
329 (unless target.result
327 (return))
330 (return))
328 (api-call base64-to-state target.result)
331 (api-call base64-to-state target.result)
329 (api-call unstash-state)))))
332 (api-call unstash-state)))))
330 (reader.read-as-text file))))
333 (reader.read-as-text file))))
331 (document.body.append-child element)
334 (document.body.append-child element)
332 (element.click)
335 (element.click)
333 (document.body.remove-child element)))
336 (document.body.remove-child element)))
334
337
335 (defm (root api savegame) ()
338 (defm (root api savegame) ()
336 (let ((element (document.create-element :a)))
339 (let ((element (document.create-element :a)))
337 (element.set-attribute :href (+ "data:text/plain;charset=utf-8," (api-call state-to-base64)))
340 (element.set-attribute :href (+ "data:text/plain;charset=utf-8," (api-call state-to-base64)))
338 (element.set-attribute :download "savegame.sav")
341 (element.set-attribute :download "savegame.sav")
339 (setf element.style.display :none)
342 (setf element.style.display :none)
340 (document.body.append-child element)
343 (document.body.append-child element)
341 (element.click)
344 (element.click)
342 (document.body.remove-child element)))
345 (document.body.remove-child element)))
343
346
344 (defm (root api stash-state) (args)
347 (defm (root api stash-state) (args)
345 (api-call call-serv-loc "ONGSAVE")
348 (api-call call-serv-loc "ONGSAVE")
346 (setf (root state-stash)
349 (setf (root state-stash)
347 (*j-s-o-n.stringify
350 (*j-s-o-n.stringify
348 (ps:create vars (root vars)
351 (ps:create vars (root vars)
349 objs (root objs)
352 objs (root objs)
350 loc-args args
353 loc-args args
351 msecs (- (*date.now) (root started-at))
354 msecs (- (*date.now) (root started-at))
352 main-html (ps:inner-html
355 main-html (ps:inner-html
353 (document.get-element-by-id :qsp-main))
356 (document.get-element-by-id :qsp-main))
354 stat-html (ps:inner-html
357 stat-html (ps:inner-html
355 (document.get-element-by-id :qsp-stat))
358 (document.get-element-by-id :qsp-stat))
356 next-location (root current-location))))
359 next-location (root current-location))))
357 (values))
360 (values))
358
361
359 (defm (root api unstash-state) ()
362 (defm (root api unstash-state) ()
360 (let ((data (*j-s-o-n.parse (root state-stash))))
363 (let ((data (*j-s-o-n.parse (root state-stash))))
361 (this.clear-act)
364 (this.clear-act)
362 (setf (root vars) (ps:@ data vars))
365 (setf (root vars) (ps:@ data vars))
363 (loop :for k :in (*object.keys (root vars))
366 (loop :for k :in (*object.keys (root vars))
364 :do (*object.set-prototype-of (ps:getprop (root vars) k)
367 :do (*object.set-prototype-of (ps:getprop (root vars) k)
365 (root api *var prototype)))
368 (root api *var prototype)))
366 (setf (root started-at) (- (*date.now) (ps:@ data msecs)))
369 (setf (root started-at) (- (*date.now) (ps:@ data msecs)))
367 (setf (root objs) (ps:@ data objs))
370 (setf (root objs) (ps:@ data objs))
368 (setf (root current-location) (ps:@ data next-location))
371 (setf (root current-location) (ps:@ data next-location))
369 (setf (ps:inner-html (document.get-element-by-id :qsp-main))
372 (setf (ps:inner-html (document.get-element-by-id :qsp-main))
370 (ps:@ data main-html))
373 (ps:@ data main-html))
371 (setf (ps:inner-html (document.get-element-by-id :qsp-stat))
374 (setf (ps:inner-html (document.get-element-by-id :qsp-stat))
372 (ps:@ data stat-html))
375 (ps:@ data stat-html))
373 (this.update-objs)
376 (this.update-objs)
374 (api-call call-serv-loc "ONGLOAD")
377 (api-call call-serv-loc "ONGLOAD")
375 (api-call call-loc (root current-location) (ps:@ data loc-args))
378 (api-call call-loc (root current-location) (ps:@ data loc-args))
376 (values)))
379 (values)))
377
380
378 (defm (root api state-to-base64) ()
381 (defm (root api state-to-base64) ()
379 (btoa (encode-u-r-i-component (root state-stash))))
382 (btoa (encode-u-r-i-component (root state-stash))))
380
383
381 (defm (root api base64-to-state) (data)
384 (defm (root api base64-to-state) (data)
382 (setf (root state-stash) (decode-u-r-i-component (atob data))))
385 (setf (root state-stash) (decode-u-r-i-component (atob data))))
383
386
384 ;;; Timers
387 ;;; Timers
385
388
386 (defm (root api set-timer) (interval)
389 (defm (root api set-timer) (interval)
387 (setf (root timer-interval) interval)
390 (setf (root timer-interval) interval)
388 (clear-interval (root timer-obj))
391 (clear-interval (root timer-obj))
389 (setf (root timer-obj)
392 (setf (root timer-obj)
390 (set-interval
393 (set-interval
391 (lambda ()
394 (lambda ()
392 (api-call call-serv-loc "COUNTER"))
395 (api-call call-serv-loc "COUNTER"))
393 interval)))
396 interval)))
@@ -1,171 +1,174 b''
1
1
2 (in-package sugar-qsp)
2 (in-package sugar-qsp)
3
3
4 ;;;; Macros implementing some intrinsics where it makes sense
4 ;;;; Macros implementing some intrinsics where it makes sense
5 ;;;; E.g. an equivalent JS function exists, or it's a direct API call
5 ;;;; E.g. an equivalent JS function exists, or it's a direct API call
6
6
7 ;;; 1loc
7 ;;; 1loc
8
8
9 ;;; 2var
9 ;;; 2var
10
10
11 (ps:defpsmacro killvar (varname &optional index)
11 (ps:defpsmacro killvar (varname &optional index)
12 `(api-call kill-var ,varname ,index))
12 `(api-call kill-var ,varname ,index))
13
13
14 (ps:defpsmacro killall ()
14 (ps:defpsmacro killall ()
15 `(api-call kill-all))
15 `(api-call kill-all))
16
16
17 ;;; 3expr
17 ;;; 3expr
18
18
19 (ps:defpsmacro obj (name)
19 (ps:defpsmacro obj (name)
20 `(funcall (root objs includes) ,name))
20 `(funcall (root objs includes) ,name))
21
21
22 (ps:defpsmacro loc (name)
22 (ps:defpsmacro loc (name)
23 `(funcall (root locs includes) ,name))
23 `(funcall (root locs includes) ,name))
24
24
25 (ps:defpsmacro no (arg)
25 (ps:defpsmacro no (arg)
26 `(- -1 ,arg))
26 `(- -1 ,arg))
27
27
28 ;;; 4code
28 ;;; 4code
29
29
30 (ps:defpsmacro qspver ()
30 (ps:defpsmacro qspver ()
31 "0.0.1")
31 "0.0.1")
32
32
33 (ps:defpsmacro curloc ()
33 (ps:defpsmacro curloc ()
34 `(root current-location))
34 `(root current-location))
35
35
36 (ps:defpsmacro rnd ()
36 (ps:defpsmacro rnd ()
37 `(funcall (root lib rand) 1 1000))
37 `(funcall (root lib rand) 1 1000))
38
38
39 (ps:defpsmacro qspmax (&rest args)
39 (ps:defpsmacro qspmax (&rest args)
40 (if (= 1 (length args))
40 (if (= 1 (length args))
41 `(*math.max.apply nil ,@args)
41 `(*math.max.apply nil ,@args)
42 `(*math.max ,@args)))
42 `(*math.max ,@args)))
43
43
44 (ps:defpsmacro qspmin (&rest args)
44 (ps:defpsmacro qspmin (&rest args)
45 (if (= 1 (length args))
45 (if (= 1 (length args))
46 `(*math.min.apply nil ,@args)
46 `(*math.min.apply nil ,@args)
47 `(*math.min ,@args)))
47 `(*math.min ,@args)))
48
48
49 ;;; 5arrays
49 ;;; 5arrays
50
50
51 (ps:defpsmacro arrsize (name)
51 (ps:defpsmacro arrsize (name)
52 `(api-call array-size ,name))
52 `(api-call array-size ,name))
53
53
54 ;;; 6str
54 ;;; 6str
55
55
56 (ps:defpsmacro len (s)
56 (ps:defpsmacro len (s)
57 `(length ,s))
57 `(length ,s))
58
58
59 (ps:defpsmacro mid (s from &optional count)
59 (ps:defpsmacro mid (s from &optional count)
60 `(ps:chain ,s (substring ,from ,count)))
60 `(ps:chain ,s (substring ,from ,count)))
61
61
62 (ps:defpsmacro ucase (s)
62 (ps:defpsmacro ucase (s)
63 `(ps:chain ,s (to-upper-case)))
63 `(ps:chain ,s (to-upper-case)))
64
64
65 (ps:defpsmacro lcase (s)
65 (ps:defpsmacro lcase (s)
66 `(ps:chain ,s (to-lower-case)))
66 `(ps:chain ,s (to-lower-case)))
67
67
68 (ps:defpsmacro trim (s)
68 (ps:defpsmacro trim (s)
69 `(ps:chain ,s (trim)))
69 `(ps:chain ,s (trim)))
70
70
71 (ps:defpsmacro replace (s from to)
71 (ps:defpsmacro replace (s from to)
72 `(ps:chain ,s (replace ,from ,to)))
72 `(ps:chain ,s (replace ,from ,to)))
73
73
74 (ps:defpsmacro val (s)
74 (ps:defpsmacro val (s)
75 `(parse-int ,s 10))
75 `(parse-int ,s 10))
76
76
77 (ps:defpsmacro qspstr (n)
77 (ps:defpsmacro qspstr (n)
78 `(ps:chain ,n (to-string)))
78 `(ps:chain ,n (to-string)))
79
79
80 ;;; 7if
80 ;;; 7if
81
81
82 ;;; 8sub
82 ;;; 8sub
83
83
84 ;;; 9loops
84 ;;; 9loops
85
85
86 ;; JUMP is in ps-macros.lisp (because it's a part of a huge kludge)
86 ;; JUMP is in ps-macros.lisp (because it's a part of a huge kludge)
87
87
88 (ps:defpsmacro exit ()
88 (ps:defpsmacro exit ()
89 `(return-from nil (values)))
89 `(return-from nil (values)))
90
90
91 ;;; 10dynamic
91 ;;; 10dynamic
92
92
93 ;;; 11main
93 ;;; 11main
94
94
95 (ps:defpsmacro desc (s)
95 (ps:defpsmacro desc (s)
96 (declare (ignore s))
96 (declare (ignore s))
97 "")
97 "")
98
98
99 ;;; 12stat
99 ;;; 12stat
100
100
101 (ps:defpsmacro showstat (enable)
101 (ps:defpsmacro showstat (enable)
102 `(api-call enable-frame :stat ,enable))
102 `(api-call enable-frame :stat ,enable))
103
103
104 ;;; 13diag
104 ;;; 13diag
105
105
106 (ps:defpsmacro msg (text)
106 (ps:defpsmacro msg (text)
107 `(alert ,text))
107 `(alert ,text))
108
108
109 ;;; 14act
109 ;;; 14act
110
110
111 (ps:defpsmacro showacts (enable)
111 (ps:defpsmacro showacts (enable)
112 `(api-call enable-frame :acts ,enable))
112 `(api-call enable-frame :acts ,enable))
113
113
114 (ps:defpsmacro delact (name)
114 (ps:defpsmacro delact (name)
115 `(api-call del-act ,name))
115 `(api-call del-act ,name))
116
116
117 (ps:defpsmacro cla ()
117 (ps:defpsmacro cla ()
118 `(api-call clear-act))
118 `(api-call clear-act))
119
119
120 ;;; 15objs
120 ;;; 15objs
121
121
122 (ps:defpsmacro showobjs (enable)
122 (ps:defpsmacro showobjs (enable)
123 `(api-call enable-frame :objs ,enable))
123 `(api-call enable-frame :objs ,enable))
124
124
125 (ps:defpsmacro countobj ()
125 (ps:defpsmacro countobj ()
126 `(length (root objs)))
126 `(length (root objs)))
127
127
128 (ps:defpsmacro getobj (index)
128 (ps:defpsmacro getobj (index)
129 `(or (elt (root objs) ,index) ""))
129 `(or (elt (root objs) ,index) ""))
130
130
131 ;;; 16menu
131 ;;; 16menu
132
132
133 ;;; 17sound
133 ;;; 17sound
134
134
135 (ps:defpsmacro isplay (filename)
135 (ps:defpsmacro isplay (filename)
136 `(funcall (root playing includes) ,filename))
136 `(funcall (root playing includes) ,filename))
137
137
138 ;;; 18img
138 ;;; 18img
139
139
140 (ps:defpsmacro view (&optional path)
140 (ps:defpsmacro view (&optional path)
141 `(api-call show-image ,path))
141 `(api-call show-image ,path))
142
142
143 ;;; 19input
143 ;;; 19input
144
144
145 (ps:defpsmacro showinput (enable)
145 (ps:defpsmacro showinput (enable)
146 `(api-call enable-frame :input ,enable))
146 `(api-call enable-frame :input ,enable))
147
147
148 ;;; 20time
148 ;;; 20time
149
149
150 (ps:defpsmacro wait (msec)
151 `(await (api-call sleep ,msec)))
152
150 (ps:defpsmacro settimer (interval)
153 (ps:defpsmacro settimer (interval)
151 `(api-call set-timer ,interval))
154 `(api-call set-timer ,interval))
152
155
153 ;;; 21local
156 ;;; 21local
154
157
155 (ps:defpsmacro local (var &optional expr)
158 (ps:defpsmacro local (var &optional expr)
156 `(progn
159 `(progn
157 (api-call new-local ,(string (second var)))
160 (api-call new-local ,(string (second var)))
158 ,@(when expr
161 ,@(when expr
159 `((set ,var ,expr)))))
162 `((set ,var ,expr)))))
160
163
161 ;;; 22for
164 ;;; 22for
162
165
163 ;;; misc
166 ;;; misc
164
167
165 (ps:defpsmacro opengame (&optional filename)
168 (ps:defpsmacro opengame (&optional filename)
166 (declare (ignore filename))
169 (declare (ignore filename))
167 `(api-call opengame))
170 `(api-call opengame))
168
171
169 (ps:defpsmacro savegame (&optional filename)
172 (ps:defpsmacro savegame (&optional filename)
170 (declare (ignore filename))
173 (declare (ignore filename))
171 `(api-call savegame))
174 `(api-call savegame))
@@ -1,307 +1,301 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
278 (defm (root lib wait) (msec)
279 (let* ((now (ps:new (*date)))
280 (exit-time (+ (funcall now.get-time) msec)))
281 (loop :while (< (funcall now.get-time) exit-time))))
282
283 (defm (root lib msecscount) ()
277 (defm (root lib msecscount) ()
284 (- (*date.now) (root started-at)))
278 (- (*date.now) (root started-at)))
285
279
286 ;;; 21local
280 ;;; 21local
287
281
288 ;;; 22for
282 ;;; 22for
289
283
290 ;;; misc
284 ;;; misc
291
285
292 (defm (root lib rgb) (red green blue)
286 (defm (root lib rgb) (red green blue)
293 (flet ((rgb-to-hex (comp)
287 (flet ((rgb-to-hex (comp)
294 (let ((hex (ps:chain (*number comp) (to-string 16))))
288 (let ((hex (ps:chain (*number comp) (to-string 16))))
295 (if (< (length hex) 2)
289 (if (< (length hex) 2)
296 (+ "0" hex)
290 (+ "0" hex)
297 hex))))
291 hex))))
298 (+ "#" (rgb-to-hex red) (rgb-to-hex green) (rgb-to-hex red))))
292 (+ "#" (rgb-to-hex red) (rgb-to-hex green) (rgb-to-hex red))))
299
293
300 (defm (root lib openqst) ()
294 (defm (root lib openqst) ()
301 (api-call report-error "OPENQST is not supported."))
295 (api-call report-error "OPENQST is not supported."))
302
296
303 (defm (root lib addqst) ()
297 (defm (root lib addqst) ()
304 (api-call report-error "ADDQST is not supported. Bundle the library with the main game."))
298 (api-call report-error "ADDQST is not supported. Bundle the library with the main game."))
305
299
306 (defm (root lib killqst) ()
300 (defm (root lib killqst) ()
307 (api-call report-error "KILLQST is not supported."))
301 (api-call report-error "KILLQST is not supported."))
@@ -1,203 +1,203 b''
1
1
2 (in-package sugar-qsp)
2 (in-package sugar-qsp)
3
3
4 ;;;; Parenscript macros which make the parser's intermediate
4 ;;;; Parenscript macros which make the parser's intermediate
5 ;;;; representation directly compilable by Parenscript
5 ;;;; representation directly compilable by Parenscript
6 ;;;; Some utility macros for other .ps sources too.
6 ;;;; Some utility macros for other .ps sources too.
7
7
8 ;;; Utils
8 ;;; Utils
9
9
10 (ps:defpsmacro defm (path args &body body)
10 (ps:defpsmacro defm (path args &body body)
11 `(setf ,path (lambda ,args ,@body)))
11 `(setf ,path (lambda ,args ,@body)))
12
12
13 (ps:defpsmacro root (&rest path)
13 (ps:defpsmacro root (&rest path)
14 `(ps:@ *sugar-q-s-p ,@path))
14 `(ps:@ *sugar-q-s-p ,@path))
15
15
16 (ps:defpsmacro in (key obj)
16 (ps:defpsmacro in (key obj)
17 `(ps:chain ,obj (has-own-property ,key)))
17 `(ps:chain ,obj (has-own-property ,key)))
18
18
19 (ps:defpsmacro with-frame (&body body)
19 (ps:defpsmacro with-frame (&body body)
20 `(progn
20 `(progn
21 (api-call push-local-frame)
21 (api-call push-local-frame)
22 (unwind-protect
22 (unwind-protect
23 ,@body
23 ,@body
24 (api-call pop-local-frame))))
24 (api-call pop-local-frame))))
25
25
26 ;;; Common
26 ;;; Common
27
27
28 (defmacro defpsintrinsic (name)
28 (defmacro defpsintrinsic (name)
29 `(ps:defpsmacro ,name (&rest args)
29 `(ps:defpsmacro ,name (&rest args)
30 `(funcall (root lib ,',name)
30 `(funcall (root lib ,',name)
31 ,@args)))
31 ,@args)))
32
32
33 (defmacro defpsintrinsics (() &rest names)
33 (defmacro defpsintrinsics (() &rest names)
34 `(progn ,@(loop :for name :in names
34 `(progn ,@(loop :for name :in names
35 :collect `(defpsintrinsic ,name))))
35 :collect `(defpsintrinsic ,name))))
36
36
37 (defpsintrinsics ()
37 (defpsintrinsics ()
38 rand copyarr arrpos arrcomp instr isnum strcomp strfind strpos iif gosub func dynamic dyneval main-p main-pl main-nl maintxt main-clear stat-p stat-pl stat-nl stattxt stat-clear cls curacts addobj delobj killobj menu play isplay close closeall refint view rgb showinput usertxt cmdclear input openqst addqst killqst opengame savegame wait msecscount settimer)
38 rand copyarr arrpos arrcomp instr isnum strcomp strfind strpos iif gosub func dynamic dyneval main-p main-pl main-nl maintxt main-clear stat-p stat-pl stat-nl stattxt stat-clear cls curacts addobj delobj killobj menu play isplay close closeall refint view rgb showinput usertxt cmdclear input openqst addqst killqst opengame savegame wait msecscount settimer)
39
39
40 (ps:defpsmacro api-call (func &rest args)
40 (ps:defpsmacro api-call (func &rest args)
41 `(funcall (root api ,func) ,@args))
41 `(funcall (root api ,func) ,@args))
42
42
43 (ps:defpsmacro label-block ((&key (locals t)) &body body)
43 (ps:defpsmacro label-block ((&key (locals t)) &body body)
44 (let ((has-labels (some #'keywordp body)))
44 (let ((has-labels (some #'keywordp body)))
45 `(block nil
45 `(block nil
46 ,@(when has-labels
46 ,@(when has-labels
47 '((defvar __labels)))
47 '((defvar __labels)))
48 ,@(if locals
48 ,@(if locals
49 `((tagbody
49 `((tagbody
50 ,@body))
50 ,@body))
51 `((tagbody
51 `((tagbody
52 ,@body))))))
52 ,@body))))))
53
53
54 (ps:defpsmacro str (&rest forms)
54 (ps:defpsmacro str (&rest forms)
55 (cond ((zerop (length forms))
55 (cond ((zerop (length forms))
56 "")
56 "")
57 ((and (= 1 (length forms))
57 ((and (= 1 (length forms))
58 (stringp (first forms)))
58 (stringp (first forms)))
59 (first forms))
59 (first forms))
60 (t
60 (t
61 `(& ,@forms))))
61 `(& ,@forms))))
62
62
63 ;;; 1loc
63 ;;; 1loc
64
64
65 (ps:defpsmacro location ((name) &body body)
65 (ps:defpsmacro location ((name) &body body)
66 `(setf (root locs ,name)
66 `(setf (root locs ,name)
67 (lambda (args)
67 (ps:async-lambda (args)
68 (label-block ()
68 (label-block ()
69 (api-call init-args args)
69 (api-call init-args args)
70 ,@body
70 ,@body
71 (api-call get-result)))))
71 (api-call get-result)))))
72
72
73 (ps:defpsmacro goto (target &rest args)
73 (ps:defpsmacro goto (target &rest args)
74 `(progn
74 `(progn
75 (funcall (root lib goto) ,target ,args)
75 (funcall (root lib goto) ,target ,args)
76 (exit)))
76 (exit)))
77
77
78 (ps:defpsmacro xgoto (target &rest args)
78 (ps:defpsmacro xgoto (target &rest args)
79 `(progn
79 `(progn
80 (funcall (root lib xgoto) ,target ,args)
80 (funcall (root lib xgoto) ,target ,args)
81 (exit)))
81 (exit)))
82
82
83 (ps:defpsmacro desc (target)
83 (ps:defpsmacro desc (target)
84 (declare (ignore target))
84 (declare (ignore target))
85 (report-error "DESC is not supported"))
85 (report-error "DESC is not supported"))
86
86
87 ;;; 2var
87 ;;; 2var
88
88
89 (ps:defpsmacro var (name index slot)
89 (ps:defpsmacro var (name index slot)
90 `(api-call get-var ,(string name) ,index ,slot))
90 `(api-call get-var ,(string name) ,index ,slot))
91
91
92 (ps:defpsmacro set ((var vname vindex vslot) value)
92 (ps:defpsmacro set ((var vname vindex vslot) value)
93 (assert (eq var 'var))
93 (assert (eq var 'var))
94 `(api-call set-var ,(string vname) ,vindex ,vslot ,value))
94 `(api-call set-var ,(string vname) ,vindex ,vslot ,value))
95
95
96 ;;; 3expr
96 ;;; 3expr
97
97
98 (ps:defpsmacro <> (op1 op2)
98 (ps:defpsmacro <> (op1 op2)
99 `(not (equal ,op1 ,op2)))
99 `(not (equal ,op1 ,op2)))
100
100
101 (ps:defpsmacro ! (op1 op2)
101 (ps:defpsmacro ! (op1 op2)
102 `(not (equal ,op1 ,op2)))
102 `(not (equal ,op1 ,op2)))
103
103
104 ;;; 4code
104 ;;; 4code
105
105
106 (ps:defpsmacro exec (&body body)
106 (ps:defpsmacro exec (&body body)
107 (format nil "javascript: ~{~A~^~%~}" (mapcar #'ps:ps* body)))
107 (format nil "javascript: ~{~A~^~%~}" (mapcar #'ps:ps* body)))
108
108
109 ;;; 5arrays
109 ;;; 5arrays
110
110
111 ;;; 6str
111 ;;; 6str
112
112
113 (ps:defpsmacro & (&rest args)
113 (ps:defpsmacro & (&rest args)
114 `(ps:chain "" (concat ,@args)))
114 `(ps:chain "" (concat ,@args)))
115
115
116 ;;; 7if
116 ;;; 7if
117
117
118 (ps:defpsmacro qspcond (&rest clauses)
118 (ps:defpsmacro qspcond (&rest clauses)
119 `(cond ,@(loop :for clause :in clauses
119 `(cond ,@(loop :for clause :in clauses
120 :collect (list (first clause)
120 :collect (list (first clause)
121 `(tagbody
121 `(tagbody
122 ,@(rest clause))))))
122 ,@(rest clause))))))
123
123
124 ;;; 8sub
124 ;;; 8sub
125
125
126 ;;; 9loops
126 ;;; 9loops
127 ;;; Yep, that's a huge kludge since Javascript doesn't support arbitrary labels
127 ;;; Yep, that's a huge kludge since Javascript doesn't support arbitrary labels
128
128
129 (ps:defpsmacro jump (target)
129 (ps:defpsmacro jump (target)
130 `(return-from ,(intern (string-upcase (second target)))
130 `(return-from ,(intern (string-upcase (second target)))
131 (funcall (ps:getprop __labels ,target))))
131 (funcall (ps:getprop __labels ,target))))
132
132
133 (ps:defpsmacro tagbody (&body body)
133 (ps:defpsmacro tagbody (&body body)
134 (let ((funcs (list nil :__nil)))
134 (let ((funcs (list nil :__nil)))
135 (dolist (form body)
135 (dolist (form body)
136 (cond ((keywordp form)
136 (cond ((keywordp form)
137 (setf (first funcs) (reverse (first funcs)))
137 (setf (first funcs) (reverse (first funcs)))
138 (push form funcs)
138 (push form funcs)
139 (push nil funcs))
139 (push nil funcs))
140 (t
140 (t
141 (push form (first funcs)))))
141 (push form (first funcs)))))
142 (setf (first funcs) (reverse (first funcs)))
142 (setf (first funcs) (reverse (first funcs)))
143 (setf funcs (reverse funcs))
143 (setf funcs (reverse funcs))
144 (if (= 2 (length funcs))
144 (if (= 2 (length funcs))
145 `(progn
145 `(progn
146 ,@body)
146 ,@body)
147 `(progn
147 `(progn
148 (setf ,@(loop :for f :on funcs :by #'cddr
148 (setf ,@(loop :for f :on funcs :by #'cddr
149 :append `((ps:@ __labels ,(first f))
149 :append `((ps:@ __labels ,(first f))
150 (block ,(intern (string-upcase (string (first f))))
150 (block ,(intern (string-upcase (string (first f))))
151 ,@(second f)
151 ,@(second f)
152 ,@(when (third f)
152 ,@(when (third f)
153 `((funcall
153 `((funcall
154 (ps:getprop __labels ,(third f)))))))))
154 (ps:getprop __labels ,(third f)))))))))
155 (jump (str "__nil"))))))
155 (jump (str "__nil"))))))
156
156
157 ;;; 10dynamic
157 ;;; 10dynamic
158
158
159 (ps:defpsmacro qspblock (&body body)
159 (ps:defpsmacro qspblock (&body body)
160 `(lambda (args)
160 `(lambda (args)
161 (label-block ()
161 (label-block ()
162 (api-call init-args args)
162 (api-call init-args args)
163 ,@body
163 ,@body
164 (api-call get-result))))
164 (api-call get-result))))
165
165
166 ;;; 11main
166 ;;; 11main
167
167
168 (ps:defpsmacro act (name img &body body)
168 (ps:defpsmacro act (name img &body body)
169 `(api-call add-act ,name ,img
169 `(api-call add-act ,name ,img
170 (lambda ()
170 (lambda ()
171 (label-block ()
171 (label-block ()
172 ,@body))))
172 ,@body))))
173
173
174 ;;; 12aux
174 ;;; 12aux
175
175
176 ;;; 13diag
176 ;;; 13diag
177
177
178 ;;; 14act
178 ;;; 14act
179
179
180 ;;; 15objs
180 ;;; 15objs
181
181
182 ;;; 16menu
182 ;;; 16menu
183
183
184 ;;; 17sound
184 ;;; 17sound
185
185
186 ;;; 18img
186 ;;; 18img
187
187
188 ;;; 19input
188 ;;; 19input
189
189
190 ;;; 20time
190 ;;; 20time
191
191
192 ;;; 21local
192 ;;; 21local
193
193
194 ;;; 22for
194 ;;; 22for
195
195
196 (ps:defpsmacro qspfor (var from to step &body body)
196 (ps:defpsmacro qspfor (var from to step &body body)
197 `(api-call qspfor
197 `(api-call qspfor
198 ,(string (second var)) ,(third var) ;; name and index
198 ,(string (second var)) ,(third var) ;; name and index
199 ,from ,to ,step
199 ,from ,to ,step
200 (lambda ()
200 (lambda ()
201 (block nil
201 (block nil
202 ,@body
202 ,@body
203 t))))
203 t))))
General Comments 0
You need to be logged in to leave comments. Login now