##// END OF EJS Templates
FOR loop
naryl -
r17:44cead28 default
parent child Browse files
Show More
@@ -0,0 +1,18 b''
1
2 # for
3 FOR k1=0 TO 5:
4 *PL k1
5 IF k1=3: EXIT
6 END
7
8 FOR Π½ΠΎΠΌΠ΅Ρ€_Π½ΠΏΡ† = 1 TO количСство_Π½ΠΏΡ†: GS 'ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Π½ΠΏΡ†', Π½ΠΎΠΌΠ΅Ρ€_Π½ΠΏΡ†
9
10 ΡΡ‚ΠΎΠΈΠΌΠΎΡΡ‚ΡŒ['ΠΌΠ΅Ρ‡'] = 10
11 ΡΡ‚ΠΎΠΈΠΌΠΎΡΡ‚ΡŒ['доспСх'] = 250
12 ΡΡ‚ΠΎΠΈΠΌΠΎΡΡ‚ΡŒ['Ρ‰ΠΈΡ‚'] = 15
13 ΡΡ‚ΠΎΠΈΠΌΠΎΡΡ‚ΡŒ_снаряТСния = 0
14 FOR Π½ΠΎΠΌΠ΅Ρ€_ΠΏΡ€Π΅Π΄ΠΌΠ΅Ρ‚Π° = 0 TO ARRSIZE('ΡΡ‚ΠΎΠΈΠΌΠΎΡΡ‚ΡŒ')-1: ΡΡ‚ΠΎΠΈΠΌΠΎΡΡ‚ΡŒ_снаряТСния += ΡΡ‚ΠΎΠΈΠΌΠΎΡΡ‚ΡŒ[Π½ΠΎΠΌΠ΅Ρ€_ΠΏΡ€Π΅Π΄ΠΌΠ΅Ρ‚Π°]
15
16 FOR i = 1 TO 10 STEP 2: *PL i
17
18 -
@@ -1,6 +1,10 b''
1 1
2 * Finish lib
3 * CLI build for Linux
4 * CLI build for Windows
5
6 * Build Istreblenie
2 7 * Windows GUI (for the compiler)
3 8 * Save-load game in slots
4 9 * Resizable frames
5 * Build Istreblenie
6 10 ** modifying it to suit compiler specifics No newline at end of file
@@ -1,587 +1,612 b''
1 1
2 2 (in-package sugar-qsp)
3 3
4 4 ;;;; Parses TXT source to an intermediate representation
5 5
6 6 ;;; Utility
7 7
8 8 (defun remove-nth (list nth)
9 9 (append (subseq list 0 nth)
10 10 (subseq list (1+ nth))))
11 11
12 12 (defun not-quote (char)
13 13 (not (eql #\' char)))
14 14
15 15
16 16 (defun not-doublequote (char)
17 17 (not (eql #\" char)))
18 18
19 19 (defun not-brace (char)
20 20 (not (eql #\} char)))
21 21
22 22 (defun not-integer (string)
23 23 (when (find-if-not #'digit-char-p string)
24 24 t))
25 25
26 26 (defun not-newline (char)
27 27 (not (eql #\newline char)))
28 28
29 29 (defun id-any-char (char)
30 30 (and
31 31 (not (digit-char-p char))
32 32 (not (eql #\newline char))
33 33 (not (find char " !:&=<>+-*/,'\"()[]{}"))))
34 34
35 35 (defun intern-first (list)
36 36 (list* (intern (string-upcase (first list)))
37 37 (rest list)))
38 38
39 39 (eval-when (:compile-toplevel :load-toplevel :execute)
40 40 (defun remove-nil (list)
41 41 (remove nil list)))
42 42
43 43 (defun binop-rest (list)
44 44 (destructuring-bind (ws1 operator ws2 operand2)
45 45 list
46 46 (declare (ignore ws1 ws2))
47 47 (list (intern (string-upcase operator)) operand2)))
48 48
49 49 (defun do-binop% (left-op other-ops)
50 50 (if (null other-ops)
51 51 left-op
52 52 (destructuring-bind ((operator right-op) &rest rest-ops)
53 53 other-ops
54 54 (if (and (listp left-op)
55 55 (eq (first left-op)
56 56 operator))
57 57 (do-binop% (append left-op (list right-op)) rest-ops)
58 58 (do-binop% (list operator left-op right-op) rest-ops)))))
59 59
60 60 (defun do-binop (list)
61 61 (destructuring-bind (left-op rest-ops)
62 62 list
63 63 (do-binop% left-op
64 64 (mapcar #'binop-rest rest-ops))))
65 65
66 66 (p:defrule line-continuation (and #\_ #\newline)
67 67 (:constant nil))
68 68
69 69 (p:defrule text-spaces (+ (or #\space #\tab line-continuation))
70 70 (:text t))
71 71
72 72 (p:defrule spaces (+ (or #\space #\tab line-continuation))
73 73 (:constant nil))
74 74
75 75 (p:defrule spaces? (* (or #\space #\tab line-continuation))
76 76 (:constant nil))
77 77
78 78 (p:defrule colon #\:
79 79 (:constant nil))
80 80
81 (p:defrule equal #\=
82 (:constant nil))
83
81 84 (p:defrule alphanumeric (alphanumericp character))
82 85
83 86 (p:defrule not-newline (not-newline character))
84 87
85 88 (p:defrule squote-esc "''"
86 89 (:lambda (list)
87 90 (p:text (elt list 0))))
88 91
89 92 (p:defrule dquote-esc "\"\""
90 93 (:lambda (list)
91 94 (p:text (elt list 0))))
92 95
93 96 (p:defrule sstring-chars (+ (and (and (p:! "<<") (p:! (p:~ "\"exec:")))
94 97 (or squote-esc (not-quote character))))
95 98 (:lambda (list)
96 99 (p:text (mapcar #'second list))))
97 100
98 101 (p:defrule dstring-chars (+ (and (and (p:! "<<") (p:! (p:~ "'exec:")))
99 102 (or dquote-esc (not-doublequote character))))
100 103 (:lambda (list)
101 104 (p:text (mapcar #'second list))))
102 105
103 106 ;;; Identifiers
104 107
105 ;; From the official docs
106 (defparameter *keywords* '(act addlib addobj addqst and arrcomp arrpos arrsize cla clear *clear close clr *clr cls cmdclear cmdclr copyarr counter countobj curacts curloc debug delact dellib delobj desc disablescroll disablesubex dynamic dyneval else elseif end exit fcolor fname freelib fsize func getobj gosub goto gs gt if iif inclib input instr isnum isplay jump killall killobj killqst killvar lcase lcolor len let loc local maintxt max menu mid min mod msecscount msg nl *nl no nosave obj onactsel ongload ongsave onnewloc onobjadd onobjdel onobjsel opengame openqst or p *p pl *pl play qspver rand refint replace rgb rnd savegame selact selobj set settimer showacts showinput showobjs showstat stattxt str strcomp strfind strpos trim ucase unsel unselect usercom user_text usrtxt val view wait xgoto xgt))
108 (defparameter *keywords* '(act addlib addobj addqst and arrcomp arrpos arrsize cla clear *clear close clr *clr cls cmdclear cmdclr copyarr counter countobj curacts curloc debug delact dellib delobj desc disablescroll disablesubex dynamic dyneval else elseif end exit fcolor fname for freelib fsize func getobj gosub goto gs gt if iif inclib input instr isnum isplay jump killall killobj killqst killvar lcase lcolor len let loc local maintxt max menu mid min mod msecscount msg nl *nl no nosave obj onactsel ongload ongsave onnewloc onobjadd onobjdel onobjsel opengame openqst or p *p pl *pl play qspver rand refint replace rgb rnd savegame selact selobj set settimer showacts showinput showobjs showstat stattxt step str strcomp strfind strpos to trim ucase unsel unselect usercom user_text usrtxt val view wait xgoto xgt))
107 109
108 110 (defun trim-$ (str)
109 111 (if (char= #\$ (elt str 0))
110 112 (subseq str 1)
111 113 str))
112 114
113 115 (defun qsp-keyword-p (id)
114 116 (member (intern (trim-$ (string-upcase id))) *keywords*))
115 117
116 118 (defun not-qsp-keyword-p (id)
117 119 (not (member (intern (trim-$ (string-upcase id))) *keywords*)))
118 120
119 121 (p:defrule qsp-keyword (qsp-keyword-p identifier-raw))
120 122
121 123 (p:defrule id-first (id-any-char character))
122 124 (p:defrule id-next (or (id-any-char character)
123 125 (digit-char-p character)))
124 126 (p:defrule identifier-raw (and id-first (* id-next))
125 127 (:lambda (list)
126 128 (intern (string-upcase (p:text list)))))
127 129
128 130 (p:defrule identifier (not-qsp-keyword-p identifier-raw))
129 131
130 132 ;;; Strings
131 133
132 134 (p:defrule qsp-string (or normal-string brace-string))
133 135
134 136 (p:defrule normal-string (or sstring dstring)
135 137 (:lambda (str)
136 138 (list* 'str (or str (list "")))))
137 139
138 140 (p:defrule sstring (and #\' (* (or string-interpol
139 141 sstring-exec
140 142 sstring-chars))
141 143 #\')
142 144 (:function second))
143 145
144 146 (p:defrule dstring (and #\" (* (or string-interpol
145 147 dstring-exec
146 148 dstring-chars))
147 149 #\")
148 150 (:function second))
149 151
150 152 (p:defrule string-interpol (and "<<" expression ">>")
151 153 (:function second))
152 154
153 155 (p:defrule sstring-exec-body (+ (or squote-esc (not-doublequote character)))
154 156 (:text t))
155 157
156 158 (p:defrule dstring-exec-body (+ (or dquote-esc (not-quote character)))
157 159 (:text t))
158 160
159 161 (p:defrule sstring-exec (and (p:~ "\"exec:") sstring-exec-body #\")
160 162 (:lambda (list)
161 163 (list* 'exec (p:parse 'exec-body (second list)))))
162 164
163 165 (p:defrule dstring-exec (and (p:~ "'exec:") dstring-exec-body #\')
164 166 (:lambda (list)
165 167 (list* 'exec (p:parse 'exec-body (second list)))))
166 168
167 169 (p:defrule brace-string (and #\{ before-statement block-body #\})
168 170 (:lambda (list)
169 171 (list* 'qspblock (third list))))
170 172
171 173 ;;; Location
172 174
173 175 (p:defrule sugar-qsp-grammar (and (* (or spaces #\newline))
174 176 (* location))
175 177 (:function second))
176 178
177 179 (p:defrule location (and location-header block-body location-end)
178 180 (:destructure (header body end)
179 181 (declare (ignore end))
180 182 `(location (,header) ,@body)))
181 183
182 184 (p:defrule location-header (and #\#
183 185 (+ not-newline)
184 186 (and #\newline spaces? before-statement))
185 187 (:destructure (spaces1 name spaces2)
186 188 (declare (ignore spaces1 spaces2))
187 189 (string-upcase (string-trim " " (p:text name)))))
188 190
189 191 (p:defrule location-end (and #\- (* not-newline) #\newline before-statement)
190 192 (:constant nil))
191 193
192 194 ;;; Block body
193 195
194 196 (p:defrule newline-block-body (and #\newline spaces? block-body)
195 197 (:function third))
196 198
197 199 (p:defrule block-body (* statement)
198 200 (:function remove-nil))
199 201
200 202 ;; Just for <a href="exec:...'>
201 203 ;; Explicitly called from that rule's production
202 204 (p:defrule exec-body (and before-statement line-body)
203 205 (:function second))
204 206
205 207 (p:defrule line-body (and inline-statement (* next-inline-statement))
206 208 (:lambda (list)
207 209 (list* (first list) (second list))))
208 210
209 211 (p:defrule before-statement (* (or #\newline spaces))
210 212 (:constant nil))
211 213
212 214 (p:defrule statement-end (or statement-end-real statement-end-block-close))
213 215
214 216 (p:defrule statement-end-real (and (or #\newline
215 217 (and #\& spaces? (p:& statement%)))
216 218 before-statement)
217 219 (:constant nil))
218 220
219 221 (p:defrule statement-end-block-close (or (p:& #\}))
220 222 (:constant nil))
221 223
222 224 (p:defrule inline-statement (and statement% spaces?)
223 225 (:function first))
224 226
225 227 (p:defrule next-inline-statement (and #\& spaces? inline-statement)
226 228 (:function third))
227 229
228 230 (p:defrule not-a-non-statement (and (p:! (p:~ "elseif"))
229 231 (p:! (p:~ "else"))
230 232 (p:! (p:~ "end"))))
231 233
232 234 (p:defrule statement (and inline-statement statement-end)
233 235 (:function first))
234 236
235 237 (p:defrule statement% (and not-a-non-statement
236 238 (or label comment string-output
237 239 block non-returning-intrinsic local
238 240 assignment expression-output))
239 241 (:function second))
240 242
241 243 (p:defrule expr-stopper (or comment block non-returning-intrinsic))
242 244
243 245 (p:defrule string-output qsp-string
244 246 (:lambda (string)
245 247 (list 'main-pl string)))
246 248
247 249 (p:defrule expression-output expression
248 250 (:lambda (list)
249 251 (list 'main-pl list)))
250 252
251 253 (p:defrule label (and colon identifier)
252 254 (:lambda (list)
253 255 (intern (string (second list)) :keyword)))
254 256
255 257 (p:defrule comment (and #\! (* (or qsp-string brace-comment text-spaces not-newline)))
256 258 (:constant nil))
257 259
258 260 (p:defrule brace-comment (and #\{ (* (not-brace character)) #\})
259 261 (:constant nil))
260 262
261 263 (p:defrule local (and (p:~ "local") spaces variable (p:? (and spaces? #\= spaces? expression)))
262 264 (:lambda (list)
263 265 (list* 'local (third list)
264 266 (when (fourth list)
265 267 (list (fourth (fourth list)))))))
266 268
267 269 ;;; Blocks
268 270
269 (p:defrule block (or block-act block-if))
271 (p:defrule block (or block-act block-if block-for))
270 272
271 273 (p:defrule block-if (and block-if-head block-if-body)
272 274 (:destructure (head body)
273 275 `(qspcond (,@head ,@(first body))
274 276 ,@(rest body))))
275 277
276 278 (p:defrule block-if-head (and (p:~ "if") spaces expression spaces? colon spaces?)
277 279 (:function remove-nil)
278 280 (:function cdr))
279 281
280 282 (p:defrule block-if-body (or block-if-ml block-if-sl)
281 283 (:destructure (if-body elseifs else &rest ws)
282 284 (declare (ignore ws))
283 285 `(,(remove-nil if-body) ,@elseifs ,@(when else `((else ,@else))))))
284 286
285 287 (p:defrule block-if-sl (and line-body
286 288 (p:? block-if-elseif-inline)
287 289 (p:? block-if-else-inline)
288 290 spaces?))
289 291
290 292 (p:defrule block-if-ml (and (and #\newline spaces?)
291 293 block-body
292 294 (p:? block-if-elseif)
293 295 (p:? block-if-else)
294 296 block-if-end)
295 297 (:lambda (list)
296 298 (cdr list)))
297 299
298 300 (p:defrule block-if-elseif-inline (and block-if-elseif-head line-body (p:? block-if-elseif-inline))
299 301 (:destructure (head statements elseif)
300 302 `((,@(rest head) ,@(remove-nil statements)) ,@elseif)))
301 303
302 304 (p:defrule block-if-elseif (and block-if-elseif-head statement-end block-body (p:? block-if-elseif))
303 305 (:destructure (head ws statements elseif)
304 306 (declare (ignore ws))
305 307 `((,@(rest head) ,@(remove-nil statements)) ,@elseif)))
306 308
307 309 (p:defrule block-if-elseif-head (and (p:~ "elseif") spaces expression spaces? colon spaces?)
308 310 (:function remove-nil)
309 311 (:function intern-first))
310 312
311 313 (p:defrule block-if-else-inline (and block-if-else-head line-body)
312 314 (:function second))
313 315
314 316 (p:defrule block-if-else (and block-if-else-head #\newline spaces? block-body)
315 317 (:function fourth))
316 318
317 319 (p:defrule block-if-else-head (and (p:~ "else") spaces?)
318 320 (:constant nil))
319 321
320 322 (p:defrule block-if-end (and (p:~ "end")
321 323 (p:? (and spaces (p:~ "if"))))
322 324 (:constant nil))
323 325
324 326 (p:defrule block-act (and block-act-head (or block-act-ml block-act-sl))
325 327 (:lambda (list)
326 328 (apply #'append list)))
327 329
328 (p:defrule block-act-sl line-body)
329
330 (p:defrule block-act-ml (and newline-block-body block-act-end)
331 (:lambda (list)
332 (apply #'list* (butlast list))))
333
334 330 (p:defrule block-act-head (and (p:~ "act") spaces qsp-string spaces?
335 331 (p:? block-act-head-img)
336 332 colon spaces?)
337 333 (:lambda (list)
338 334 (intern-first (list (first list)
339 335 (third list)
340 336 (or (fifth list) '(str ""))))))
341 337
342 338 (p:defrule block-act-head-img (and #\, spaces? qsp-string spaces?)
343 339 (:lambda (list)
344 340 (or (third list) "")))
345 341
346 (p:defrule block-act-end (and (p:~ "end"))
342 (p:defrule block-for (and block-for-head (or block-ml block-sl))
343 (:lambda (list)
344 (apply #'append list)))
345
346 (p:defrule block-for-head (and (p:~ "for") spaces variable spaces? equal spaces? expression
347 (p:~ "to") spaces expression
348 block-for-head-step
349 colon spaces?)
350 (:lambda (list)
351 (unless (eq (fourth (third list)) :num)
352 (error "For counter variable must be numeric."))
353 (list 'qspfor
354 (elt list 2)
355 (elt list 6)
356 (elt list 9)
357 (elt list 10))))
358
359 (p:defrule block-for-head-step (p:? (and (p:~ "step") spaces expression spaces?))
360 (:lambda (list)
361 (if list
362 (third list)
363 1)))
364
365 (p:defrule block-sl line-body)
366
367 (p:defrule block-ml (and newline-block-body block-end)
368 (:lambda (list)
369 (apply #'list* (butlast list))))
370
371 (p:defrule block-end (and (p:~ "end"))
347 372 (:constant nil))
348 373
349 374 ;;; Calls
350 375
351 376 (p:defrule first-argument (and expression spaces?)
352 377 (:function first))
353 378 (p:defrule next-argument (and "," spaces? expression)
354 379 (:function third))
355 380 (p:defrule arguments (or parenthesized-arguments plain-arguments no-arguments))
356 381 (p:defrule parenthesized-arguments (and spaces? #\( base-arguments #\))
357 382 (:function third))
358 383 (p:defrule plain-arguments (and spaces base-arguments)
359 384 (:function second))
360 385 (p:defrule no-arguments (or (and spaces? (p:& #\newline))
361 386 (and spaces? (p:& #\&))
362 387 spaces?)
363 388 (:constant nil))
364 389 (p:defrule base-arguments (or (and first-argument (* next-argument)) spaces?)
365 390 (:lambda (list)
366 391 (if (null list)
367 392 nil
368 393 (list* (first list) (second list)))))
369 394
370 395 ;;; Intrinsics
371 396
372 397 (defmacro defintrinsics ((rule-name returning-rule-name non-returning-rule-name) &body clauses)
373 398 `(progn
374 399 ,@(loop :for clause :in clauses
375 400 :collect `(defintrinsic ,@clause))
376 401 (p:defrule ,returning-rule-name (or ,@(remove-nil
377 402 (mapcar (lambda (clause)
378 403 (when (second clause)
379 404 (alexandria:symbolicate
380 405 'intrinsic- (first clause))))
381 406 clauses))))
382 407 (p:defrule ,non-returning-rule-name (or ,@(remove-nil
383 408 (mapcar (lambda (clause)
384 409 (unless (second clause)
385 410 (alexandria:symbolicate
386 411 'intrinsic- (first clause))))
387 412 clauses))))
388 413 (p:defrule ,rule-name (or ,returning-rule-name ,non-returning-rule-name))))
389 414
390 415 (defmacro defintrinsic (sym returning &optional (min-arity 0) (max-arity 10) &rest names)
391 416 (declare (ignore returning))
392 417 (setf names
393 418 (if names
394 419 (mapcar #'string-upcase names)
395 420 (list (string sym))))
396 421 `(p:defrule ,(alexandria:symbolicate 'intrinsic- sym)
397 422 (and (p:? #\$) (or ,@(loop :for name :in names :collect `(p:~ ,name)))
398 423 arguments)
399 424 (:destructure (dollar name arguments)
400 425 (declare (ignore dollar))
401 426 (unless (<= ,min-arity (length arguments) ,max-arity)
402 427 (error "Intrinsic ~A expects between ~A and ~A arguments but ~A were provided:~%~S"
403 428 name ,min-arity ,max-arity (length arguments) arguments))
404 429 (list* ',sym arguments))))
405 430
406 431 (defintrinsics (intrinsic returning-intrinsic non-returning-intrinsic)
407 432 ;; Transitions
408 433 (goto nil 0 10 "gt" "goto")
409 434 (xgoto nil 0 10 "xgt" "xgoto")
410 435 ;; Variables
411 436 (killvar nil 0 2)
412 437 ;; Expressions
413 438 (obj t 1 1)
414 439 (loc t 1 1)
415 440 (no t 1 1)
416 441 ;; Basic
417 442 (qspver t 0 0)
418 443 (curloc t 0 0)
419 444 (rand t 1 2)
420 445 (rnd t 0 0)
421 446 (qspmax t 1 10 "max")
422 447 (qspmin t 1 10 "min")
423 448 ;; Arrays
424 449 (killall nil 0 0)
425 450 (copyarr nil 2 4)
426 451 (arrsize t 1 1)
427 452 (arrpos t 2 3)
428 453 (arrcomp t 2 3)
429 454 ;; Strings
430 455 (len t 1 1)
431 456 (mid t 2 3)
432 457 (ucase t 1 1)
433 458 (lcase t 1 1)
434 459 (trim t 1 1)
435 460 (replace t 2 3)
436 461 (instr t 2 3)
437 462 (isnum t 1 1)
438 463 (val t 1 1)
439 464 (qspstr t 1 1 "str")
440 465 (strcomp t 2 2)
441 466 (strfind t 2 3)
442 467 (strpos t 2 3)
443 468 ;; IF
444 469 (iif t 2 3)
445 470 ;; Subs
446 471 (gosub nil 1 10 "gosub" "gs")
447 472 (func t 1 10)
448 473 (exit nil 0 0)
449 474 ;; Jump
450 475 (jump nil 1 1)
451 476 ;; Dynamic
452 477 (dynamic nil 1 10)
453 478 (dyneval t 1 10)
454 479 ;; Main window
455 480 (main-pl nil 1 1 "*pl")
456 481 (main-nl nil 0 1 "*nl")
457 482 (main-p nil 1 1 "*p")
458 483 (maintxt t 0 0)
459 484 (desc t 1 1)
460 485 (main-clear nil 0 0 "*clear" "*clr")
461 486 ;; Aux window
462 487 (showstat nil 1 1)
463 488 (stat-pl nil 1 1 "pl")
464 489 (stat-nl nil 0 1 "nl")
465 490 (stat-p nil 1 1 "p")
466 491 (stattxt t 0 0)
467 492 (stat-clear nil 0 0 "clear" "clr")
468 493 (cls nil 0 0)
469 494 ;; Dialog
470 495 (msg nil 1 1)
471 496 ;; Acts
472 497 (showacts nil 1 1)
473 498 (delact nil 1 1 "delact" "del act")
474 499 (curacts t 0 0)
475 500 (cla nil 0 0)
476 501 ;; Objects
477 502 (showobjs nil 1 1)
478 503 (addobj nil 1 3 "addobj" "add obj")
479 504 (delobj nil 1 1 "delobj" "del obj")
480 505 (killobj nil 0 1)
481 506 (countobj t 0 0)
482 507 (getobj t 1 1)
483 508 ;; Menu
484 509 (menu nil 1 1)
485 510 ;; Sound
486 511 (play nil 1 2)
487 512 (isplay t 1 1)
488 513 (close nil 1 1)
489 514 (closeall nil 0 0 "close all")
490 515 ;; Images
491 516 (refint nil 0 0)
492 517 (view nil 0 1)
493 518 ;; Fonts
494 519 (rgb t 3 3)
495 520 ;; Input
496 521 (showinput nil 1 1)
497 522 (usertxt t 0 0 "user_text" "usrtxt")
498 523 (cmdclear nil 0 0 "cmdclear" "cmdclr")
499 524 (input t 1 1)
500 525 ;; Files
501 526 (openqst nil 1 1)
502 527 (addqst nil 1 1 "addqst" "addlib" "inclib")
503 528 (killqst nil 1 1 "killqst" "dellib" "freelib")
504 529 (opengame nil 0 0)
505 530 (savegame nil 0 0)
506 531 ;; Real time
507 532 (wait nil 1 1)
508 533 (msecscount t 0 0)
509 534 (settimer nil 1 1))
510 535
511 536 ;;; Expression
512 537
513 538 (p:defrule expression or-expr)
514 539
515 540 (p:defrule or-expr (and and-expr (* (and spaces? or-op spaces? and-expr)))
516 541 (:function do-binop))
517 542
518 543 (p:defrule and-expr (and eq-expr (* (and spaces? and-op spaces? eq-expr)))
519 544 (:function do-binop))
520 545
521 546 (p:defrule eq-expr (and sum-expr (* (and spaces? (or "<=" ">=" "=<" "=>" "<>"
522 547 "=" "<" ">" "!")
523 548 spaces? cat-expr)))
524 549 (:function do-binop))
525 550
526 551 (p:defrule sum-expr (and mod-expr (* (and spaces? (or #\+ #\-) spaces? mod-expr)))
527 552 (:function do-binop))
528 553
529 554 (p:defrule mod-expr (and mul-expr (* (and spaces? (p:~ "mod") spaces? mul-expr)))
530 555 (:function do-binop))
531 556
532 557 (p:defrule mul-expr (and unary-expr (* (and spaces? (or #\* #\/) spaces? unary-expr)))
533 558 (:function do-binop))
534 559
535 560 (p:defrule unary-expr (and (p:? (or #\+ #\-)) atom-expr)
536 561 (:lambda (list)
537 562 (let ((expr (remove-nil list)))
538 563 (if (= 1 (length expr))
539 564 (first expr)
540 565 (intern-first expr)))))
541 566
542 567 (p:defrule atom-expr (and (or variable literal returning-intrinsic paren-expr) spaces?)
543 568 (:function first))
544 569
545 570 (p:defrule paren-expr (and #\( spaces? expression spaces? #\))
546 571 (:function third))
547 572
548 573 (p:defrule or-op (p:~ "or")
549 574 (:constant "or"))
550 575
551 576 (p:defrule and-op (p:~ "and")
552 577 (:constant "and"))
553 578
554 579 ;;; Variables
555 580
556 581 (p:defrule variable (and identifier (p:? array-index))
557 582 (:destructure (id idx)
558 583 (if (char= #\$ (elt (string id) 0))
559 584 (list 'var (intern (subseq (string-upcase id) 1)) (or idx 0) :str)
560 585 (list 'var id (or idx 0) :num))))
561 586
562 587 (p:defrule array-index (and #\[ spaces? (p:? expression) spaces? #\])
563 588 (:function third))
564 589
565 590 (p:defrule assignment (or kw-assignment plain-assignment op-assignment)
566 591 (:destructure (var eq expr)
567 592 (declare (ignore eq))
568 593 (list 'set var expr)))
569 594
570 595 (p:defrule kw-assignment (and (or (p:~ "let") (p:~ "set")) spaces? (or op-assignment plain-assignment))
571 596 (:function third))
572 597
573 598 (p:defrule op-assignment (and variable spaces? (or "+" "-" "*" "/") #\= spaces? expression)
574 599 (:destructure (var ws1 op eq ws2 expr)
575 600 (declare (ignore ws1 ws2))
576 601 (list var eq (intern-first (list op var expr)))))
577 602
578 603 (p:defrule plain-assignment (and variable spaces? #\= spaces? expression)
579 604 (:function remove-nil))
580 605
581 606 ;;; Non-string literals
582 607
583 608 (p:defrule literal (or qsp-string brace-string number))
584 609
585 610 (p:defrule number (+ (or #\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9))
586 611 (:lambda (list)
587 612 (parse-integer (p:text list))))
@@ -1,193 +1,203 b''
1 1
2 2 (in-package sugar-qsp)
3 3
4 4 ;;;; Parenscript macros which make the parser's intermediate
5 5 ;;;; representation directly compilable by Parenscript
6 6 ;;;; Some utility macros for other .ps sources too.
7 7
8 8 ;;; Utils
9 9
10 10 (ps:defpsmacro defm (path args &body body)
11 11 `(setf ,path (lambda ,args ,@body)))
12 12
13 13 (ps:defpsmacro root (&rest path)
14 14 `(ps:@ *sugar-q-s-p ,@path))
15 15
16 16 (ps:defpsmacro in (key obj)
17 17 `(ps:chain ,obj (has-own-property ,key)))
18 18
19 19 (ps:defpsmacro with-frame (&body body)
20 20 `(progn
21 21 (api-call push-local-frame)
22 22 (unwind-protect
23 23 ,@body
24 24 (api-call pop-local-frame))))
25 25
26 26 ;;; Common
27 27
28 28 (defmacro defpsintrinsic (name)
29 29 `(ps:defpsmacro ,name (&rest args)
30 30 `(funcall (root lib ,',name)
31 31 ,@args)))
32 32
33 33 (defmacro defpsintrinsics (() &rest names)
34 34 `(progn ,@(loop :for name :in names
35 35 :collect `(defpsintrinsic ,name))))
36 36
37 37 (defpsintrinsics ()
38 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 40 (ps:defpsmacro api-call (func &rest args)
41 41 `(funcall (root api ,func) ,@args))
42 42
43 43 (ps:defpsmacro label-block ((&key (locals t)) &body body)
44 44 (let ((has-labels (some #'keywordp body)))
45 45 `(block nil
46 46 ,@(when has-labels
47 47 '((defvar __labels)))
48 48 ,@(if locals
49 49 `((with-frame
50 50 (tagbody
51 51 ,@body)))
52 52 `((tagbody
53 53 ,@body))))))
54 54
55 55 (ps:defpsmacro str (&rest forms)
56 56 (cond ((zerop (length forms))
57 57 "")
58 58 ((and (= 1 (length forms))
59 59 (stringp (first forms)))
60 60 (first forms))
61 61 (t
62 62 `(& ,@forms))))
63 63
64 64 ;;; 1loc
65 65
66 66 (ps:defpsmacro location ((name) &body body)
67 67 `(setf (root locs ,name)
68 68 (lambda (args)
69 69 (label-block ()
70 70 (api-call init-args args)
71 71 ,@body
72 72 (api-call get-result)))))
73 73
74 74 (ps:defpsmacro goto (target &rest args)
75 75 `(progn
76 76 (funcall (root lib goto) ,target ,args)
77 77 (exit)))
78 78
79 79 (ps:defpsmacro xgoto (target &rest args)
80 80 `(progn
81 81 (funcall (root lib xgoto) ,target ,args)
82 82 (exit)))
83 83
84 84 (ps:defpsmacro desc (target)
85 85 (declare (ignore target))
86 86 (report-error "DESC is not supported"))
87 87
88 88 ;;; 2var
89 89
90 90 (ps:defpsmacro var (name index slot)
91 91 `(api-call get-var ,(string name) ,index ,slot))
92 92
93 93 (ps:defpsmacro set ((var vname vindex vslot) value)
94 94 (assert (eq var 'var))
95 95 `(api-call set-var ,(string vname) ,vindex ,vslot ,value))
96 96
97 97 ;;; 3expr
98 98
99 99 (ps:defpsmacro <> (op1 op2)
100 100 `(not (equal ,op1 ,op2)))
101 101
102 102 (ps:defpsmacro ! (op1 op2)
103 103 `(not (equal ,op1 ,op2)))
104 104
105 105 ;;; 4code
106 106
107 107 (ps:defpsmacro exec (&body body)
108 108 (format nil "javascript: ~{~A~^~%~}" (mapcar #'ps:ps* body)))
109 109
110 110 ;;; 5arrays
111 111
112 112 ;;; 6str
113 113
114 114 (ps:defpsmacro & (&rest args)
115 115 `(ps:chain "" (concat ,@args)))
116 116
117 117 ;;; 7if
118 118
119 119 (ps:defpsmacro qspcond (&rest clauses)
120 120 `(cond ,@(loop :for clause :in clauses
121 121 :collect (list (first clause)
122 122 `(tagbody
123 123 ,@(rest clause))))))
124 124
125 125 ;;; 8sub
126 126
127 127 ;;; 9loops
128 128 ;;; Yep, that's a huge kludge since Javascript doesn't support arbitrary labels
129 129
130 130 (ps:defpsmacro jump (target)
131 131 `(return-from ,(intern (string-upcase (second target)))
132 132 (funcall (ps:getprop __labels ,target))))
133 133
134 134 (ps:defpsmacro tagbody (&body body)
135 135 (let ((funcs (list nil :__nil)))
136 136 (dolist (form body)
137 137 (cond ((keywordp form)
138 138 (setf (first funcs) (reverse (first funcs)))
139 139 (push form funcs)
140 140 (push nil funcs))
141 141 (t
142 142 (push form (first funcs)))))
143 143 (setf (first funcs) (reverse (first funcs)))
144 144 (setf funcs (reverse funcs))
145 145 (if (= 2 (length funcs))
146 146 `(progn
147 147 ,@body)
148 148 `(progn
149 149 (setf ,@(loop :for f :on funcs :by #'cddr
150 150 :append `((ps:@ __labels ,(first f))
151 151 (block ,(intern (string-upcase (string (first f))))
152 152 ,@(second f)
153 153 ,@(when (third f)
154 154 `((funcall
155 155 (ps:getprop __labels ,(third f)))))))))
156 156 (jump (str "__nil"))))))
157 157
158 158 ;;; 10dynamic
159 159
160 160 (ps:defpsmacro qspblock (&body body)
161 161 `(lambda (args)
162 162 (label-block ()
163 163 (api-call init-args args)
164 164 ,@body
165 165 (api-call get-result))))
166 166
167 167 ;;; 11main
168 168
169 169 (ps:defpsmacro act (name img &body body)
170 170 `(api-call add-act ,name ,img
171 171 (lambda ()
172 172 (label-block ()
173 173 ,@body))))
174 174
175 175 ;;; 12aux
176 176
177 177 ;;; 13diag
178 178
179 179 ;;; 14act
180 180
181 181 ;;; 15objs
182 182
183 183 ;;; 16menu
184 184
185 185 ;;; 17sound
186 186
187 187 ;;; 18img
188 188
189 189 ;;; 19input
190 190
191 191 ;;; 20time
192 192
193 193 ;;; 21local
194
195 ;;; 22for
196
197 (ps:defpsmacro qspfor (var from to step &body body)
198 `(block nil
199 (set ,var ,from)
200 (ps:for ()
201 ((< ,var ,to))
202 ((set ,var (+ ,var ,step)))
203 ,@body)))
General Comments 0
You need to be logged in to leave comments. Login now