##// END OF EJS Templates
Properly handle stringly-indexed arrays
naryl -
r16:6eb15d3f default
parent child Browse files
Show More
@@ -1,6 +1,3 b''
1
2 * string array keys as addition to number keys
3 * arr[] notation (i.e. with empty index)
4 1
5 2 * Windows GUI (for the compiler)
6 3 * Save-load game in slots
@@ -22,29 +22,43 b''
22 22 "</a>"))
23 23
24 24 ;; To be used in saving game
25 (defm (root api stash-state) ()
25 (defm (root api stash-state) (args)
26 26 (setf (root state-stash)
27 27 (*j-s-o-n.stringify
28 28 (ps:create vars (root vars)
29 29 objs (root objs)
30 loc-args args
31 main-html (ps:@
32 (document.get-element-by-id :qsp-main)
33 inner-h-t-m-l)
34 stat-html (ps:@
35 (document.get-element-by-id :qsp-stat)
36 inner-h-t-m-l)
30 37 next-location (root current-location))))
31 38 (values))
32 39
40 (defm (root api unstash-state) ()
41 (let ((data (*j-s-o-n.parse (root state-stash))))
42 (this.clear-act)
43 (setf (root vars) (ps:@ data vars))
44 (loop :for k :in (*object.keys (root vars))
45 :do (*object.set-prototype-of (ps:getprop (root vars) k)
46 (root api *var prototype)))
47 (setf (root objs) (ps:@ data objs))
48 (setf (root current-location) (ps:@ data next-location))
49 (setf (ps:@ (document.get-element-by-id :qsp-main) inner-h-t-m-l)
50 (ps:@ data main-html))
51 (setf (ps:@ (document.get-element-by-id :qsp-stat) inner-h-t-m-l)
52 (ps:@ data stat-html))
53 (funcall (root locs (root current-location)) (ps:@ data loc-args))
54 (this.update-objs)
55 (values)))
56
33 57 (defm (root api state-to-base64) ()
34 58 (btoa (encode-u-r-i-component (root state-stash))))
35 59
36 60 (defm (root api base64-to-state) (data)
37 (setf (root state-stash) (decode-u-r-i-component (atob data)))
38 (let ((data (*j-s-o-n.parse (root state-stash))))
39 (this.clear-id :qsp-main)
40 (this.clear-id :qsp-stat)
41 (this.clear-act)
42 (setf (root vars) (ps:@ data vars))
43 (setf (root objs) (ps:@ data objs))
44 (setf (root current-location) (ps:@ data next-location))
45 (funcall (root locs (root current-location)))
46 (this.update-objs)
47 (values)))
61 (setf (root state-stash) (decode-u-r-i-component (atob data))))
48 62
49 63 ;;; Misc
50 64
@@ -52,17 +66,17 b''
52 66 (setf (ps:chain document (get-element-by-id id) inner-text) ""))
53 67
54 68 (defm (root api get-id) (id)
55 (if (var "USEHTML" 0)
69 (if (var "USEHTML" 0 :num)
56 70 (ps:chain (document.get-element-by-id id) inner-h-t-m-l)
57 71 (ps:chain (document.get-element-by-id id) inner-text)))
58 72
59 73 (defm (root api set-id) (id contents)
60 (if (var "USEHTML" 0)
74 (if (var "USEHTML" 0 :num)
61 75 (setf (ps:chain (document.get-element-by-id id) inner-h-t-m-l) contents)
62 76 (setf (ps:chain (document.get-element-by-id id) inner-text) contents)))
63 77
64 78 (defm (root api append-id) (id contents)
65 (if (var "USEHTML" 0)
79 (if (var "USEHTML" 0 :num)
66 80 (incf (ps:chain (document.get-element-by-id id) inner-h-t-m-l) contents)
67 81 (incf (ps:chain (document.get-element-by-id id) inner-text) contents)))
68 82
@@ -70,14 +84,15 b''
70 84
71 85 (defm (root api init-args) (args)
72 86 (dotimes (i (length args))
73 (if (numberp (elt args i))
74 (set (var args i) (elt args i))
75 (set (var $args i) (elt args i)))))
87 (let ((arg (elt args i)))
88 (if (numberp arg)
89 (this.set-var args i :num arg)
90 (this.set-var args i :str arg)))))
76 91
77 92 (defm (root api get-result) ()
78 (if (not (equal "" (var $result 0)))
79 (var $result 0)
80 (var result 0)))
93 (if (not (equal "" (var result 0 :str)))
94 (var result 0 :str)
95 (var result 0 :num)))
81 96
82 97 ;;; Text windows
83 98
@@ -134,61 +149,113 b''
134 149 (this.append-id "qsp-acts"
135 150 (this.make-act-html title (ps:getprop obj :img))))))
136 151
137 ;;; Variables
152 ;;; Variable class
153
154 (defm (root api *var) (name)
155 ;; From strings to numbers
156 (setf this.indexes (ps:create))
157 ;; From numbers to {num: 0, str: ""} objects
158 (setf this.values (list))
159 (values))
160
161 (defm (root api *var prototype new-value) ()
162 (ps:create :num 0 :str ""))
138 163
139 (defm (root api var-slot) (name)
140 (if (= (ps:@ name 0) #\$)
141 :str
142 :num))
164 (defm (root api *var prototype index-num) (index)
165 (let ((num-index
166 (if (stringp index)
167 (if (in index this.indexes)
168 (ps:getprop this.indexes index)
169 (let ((n (length this.values)))
170 (setf (ps:getprop this.indexes index) n)
171 n))
172 index)))
173 (unless (in num-index this.values)
174 (setf (elt this.values num-index) (this.new-value)))
175 num-index))
176
177 (defm (root api *var prototype get) (index slot)
178 (unless (or index (= 0 index))
179 (setf index (1- (length this.values))))
180 (ps:getprop this.values (this.index-num index) slot))
181
182 (defm (root api *var prototype set) (index slot value)
183 (unless (or index (= 0 index))
184 (setf index (length store)))
185 (case slot
186 (:num (setf value (ps:chain *number (parse-int value))))
187 (:str (setf value (ps:chain value (to-string)))))
188 (setf (ps:getprop this.values (this.index-num index) slot) value)
189 (values))
190
191 (defm (root api *var prototype kill) (index)
192 (setf (elt this.values (this.index-num index)) (this.new-value)))
193
194 ;;; Variables
143 195
144 196 (defm (root api var-real-name) (name)
145 197 (if (= (ps:@ name 0) #\$)
146 (ps:chain name (substr 1))
147 name))
198 (values (ps:chain name (substr 1)) :str)
199 (values name :num)))
148 200
149 (defm (root api ensure-var) (name index)
201 (defm (root api ensure-var) (name)
150 202 (let ((store (this.var-ref name)))
151 203 (unless store
152 (setf store (ps:create))
153 (setf (ps:getprop (root vars) name) store)))
154 (unless (in index store)
155 (setf (elt store index) (ps:create :num 0 :str "")))
156 (values))
204 (setf store (ps:new (this.-var name)))
205 (setf (ps:getprop (root vars) name) store))
206 store))
157 207
158 208 (defm (root api var-ref) (name)
159 (let ((var-name (this.var-real-name name))
160 (local-store (this.current-local-frame)))
161 (cond ((in var-name local-store)
162 (ps:getprop local-store))
163 ((in var-name (root vars))
164 (ps:getprop (root vars) var-name))
209 (let ((local-store (this.current-local-frame)))
210 (cond ((in name local-store)
211 (ps:getprop local-store name))
212 ((in name (root vars))
213 (ps:getprop (root vars) name))
165 214 (t nil))))
166 215
167 (defm (root api get-var) (name index)
168 (this.ensure-var name index)
169 (let ((store (this.var-ref name)))
170 (ps:getprop store index (this.var-slot name))))
216 (defm (root api get-var) (name index slot)
217 (ps:chain (this.ensure-var name) (get index slot)))
171 218
172 (defm (root api set-var) (name index value)
173 (this.ensure-var name index)
174 (let ((store (this.var-ref name)))
175 (setf (ps:getprop store index (this.var-slot name)) value)
176 (values)))
219 (defm (root api set-var) (name index slot value)
220 (ps:chain (this.ensure-var name) (set index slot value))
221 (values))
177 222
178 223 (defm (root api get-array) (name)
179 (ps:getprop (root vars) name))
224 (this.var-ref name))
180 225
181 226 (defm (root api set-array) (name value)
182 (setf (ps:getprop (root vars) name) value))
227 (let ((store (this.var-ref name)))
228 (setf (ps:@ store values) (ps:@ value values))
229 (setf (ps:@ store indexes) (ps:@ value indexes)))
230 (values))
183 231
184 232 (defm (root api kill-var) (name &optional index)
185 (if index
186 (ps:delete (ps:getprop (root vars) name index))
233 (if (and index (not (= 0 index)))
234 (ps:chain (ps:getprop (root vars) name) (kill index))
187 235 (ps:delete (ps:getprop (root vars) name)))
188 236 (values))
189 237
190 238 (defm (root api array-size) (name)
191 (ps:getprop (root vars) (this.var-real-name name) 'length))
239 (ps:getprop (this.var-ref name) 'length))
240
241 ;;; Locals
242
243 (defm (root api push-local-frame) ()
244 (ps:chain (root locals) (push (ps:create)))
245 (values))
246
247 (defm (root api pop-local-frame) ()
248 (ps:chain (root locals) (pop))
249 (values))
250
251 (defm (root api current-local-frame) ()
252 (elt (root locals) (1- (length (root locals)))))
253
254 (defm (root api new-local) (name)
255 (let ((frame (this.current-local-frame)))
256 (unless (in name frame)
257 (setf (ps:getprop frame name) (ps:create)))
258 (values)))
192 259
193 260 ;;; Objects
194 261
@@ -218,19 +285,3 b''
218 285 :do (when (ps:@ v ended)
219 286 (ps:delete (ps:@ (root playing) k)))))
220 287
221 ;;; Locals
222
223 (defm (root api push-local-frame) ()
224 (ps:chain (root locals) (push (ps:create))))
225
226 (defm (root api pop-local-frame) ()
227 (ps:chain (root locals) (pop)))
228
229 (defm (root api current-local-frame) ()
230 (elt (root locals) (1- (length (root locals)))))
231
232 (defm (root api new-local) (name)
233 (let ((frame (this.current-local-frame))
234 (var-name (this.var-real-name name)))
235 (unless (in var-name frame)
236 (setf (ps:getprop frame var-name) (ps:create)))))
@@ -9,16 +9,18 b''
9 9
10 10 ;;; 1loc
11 11
12 (defm (root lib goto) (target &rest args)
12 (defm (root lib goto) (target args)
13 13 (api-call clear-text :main)
14 (apply (root lib xgoto) target args))
14 (funcall (root lib xgoto) target (or args (list)))
15 (values))
15 16
16 (defm (root lib xgoto) (target &rest args)
17 (defm (root lib xgoto) (target args)
17 18 (api-call clear-act)
18 (api-call init-args args)
19 19 (setf (root current-location) (ps:chain target (to-upper-case)))
20 (api-call stash-state)
21 (funcall (ps:getprop (root locs) (root current-location))))
20 (api-call stash-state args)
21 (funcall (ps:getprop (root locs) (root current-location))
22 (or args (list)))
23 (values))
22 24
23 25 ;;; 2var
24 26
@@ -34,23 +36,31 b''
34 36 ;;; 5arrays
35 37
36 38 (defm (root lib copyarr) (to from start count)
37 (ps:for ((i start))
38 ((< i (min (api-call array-size from)
39 (+ start count))))
40 ((incf i))
41 (api-call set-var to (+ start i)
42 (api-call get-var from (+ start i)))))
39 (multiple-value-bind (to-name to-slot)
40 (api-call var-real-name to)
41 (multiple-value-bind (from-name from-slot)
42 (api-call var-real-name from)
43 (ps:for ((i start))
44 ((< i (min (api-call array-size from-name)
45 (+ start count))))
46 ((incf i))
47 (api-call set-var to-name (+ start i) to-slot
48 (api-call get-var from-name (+ start i) from-slot))))))
43 49
44 50 (defm (root lib arrpos) (name value &optional (start 0))
45 (ps:for ((i start)) ((< i (api-call array-size name))) ((incf i))
46 (when (eq (api-call get-var name i) value)
47 (return i)))
51 (multiple-value-bind (real-name slot)
52 (api-call var-real-name name)
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)
55 (return i))))
48 56 -1)
49 57
50 58 (defm (root lib arrcomp) (name pattern &optional (start 0))
51 (ps:for ((i start)) ((< i (api-call array-size name))) ((incf i))
52 (when (funcall (ps:getprop (api-call get-var name i) 'match) pattern)
53 (return i)))
59 (multiple-value-bind (real-name slot)
60 (api-call var-real-name name)
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)
63 (return i))))
54 64 -1)
55 65
56 66 ;;; 6str
@@ -91,32 +101,22 b''
91 101 ;;; 8sub
92 102
93 103 (defm (root lib gosub) (target &rest args)
94 (conserving-vars (__funcall args result)
95 (api-call init-args args)
96 (funcall (ps:getprop (root locs) target))
97 (values)))
104 (funcall (ps:getprop (root locs) target) args)
105 (values))
98 106
99 107 (defm (root lib func) (target &rest args)
100 (conserving-vars (__funcall args result)
101 (api-call init-args args)
102 (funcall (ps:getprop (root locs) target))
103 (api-call get-result)))
108 (funcall (ps:getprop (root locs) target) args))
104 109
105 110 ;;; 9loops
106 111
107 112 ;;; 10dynamic
108 113
109 (defm (root lib dyneval) (block &rest args)
110 (conserving-vars (__funcall args result)
111 (api-call init-args args)
112 (funcall block)
113 (api-call get-result)))
114 (defm (root lib dynamic) (block &rest args)
115 (funcall block args)
116 (values))
114 117
115 (defm (root lib dynamic) (&rest args)
116 (conserving-vars (__funcall args result)
117 (api-call init-args args)
118 (funcall block)
119 (values)))
118 (defm (root lib dyneval) (block &rest args)
119 (funcall block args))
120 120
121 121 ;;; 11main
122 122
@@ -307,7 +307,8 b''
307 307 (let ((target ev.current-target))
308 308 (unless target.result
309 309 (return))
310 (api-call base64-to-state target.result)))))
310 (api-call base64-to-state target.result)
311 (api-call unstash-state)))))
311 312 (reader.read-as-text file))))
312 313 (document.body.append-child element)
313 314 (element.click)
@@ -25,7 +25,8 b''
25 25 (setf window.onload
26 26 (lambda ()
27 27 (funcall (ps:getprop (root locs)
28 (ps:chain *object (keys (root locs)) 0)))
28 (ps:chain *object (keys (root locs)) 0))
29 (list))
29 30 (values)))
30 31
31 32 ;; Close the dropdown on any click
@@ -555,11 +555,12 b''
555 555
556 556 (p:defrule variable (and identifier (p:? array-index))
557 557 (:destructure (id idx)
558 (list 'var id (or idx 0))))
558 (if (char= #\$ (elt (string id) 0))
559 (list 'var (intern (subseq (string-upcase id) 1)) (or idx 0) :str)
560 (list 'var id (or idx 0) :num))))
559 561
560 562 (p:defrule array-index (and #\[ spaces? (p:? expression) spaces? #\])
561 (:lambda (list)
562 (or (third list) :end)))
563 (:function third))
563 564
564 565 (p:defrule assignment (or kw-assignment plain-assignment op-assignment)
565 566 (:destructure (var eq expr)
@@ -16,6 +16,13 b''
16 16 (ps:defpsmacro in (key obj)
17 17 `(ps:chain ,obj (has-own-property ,key)))
18 18
19 (ps:defpsmacro with-frame (&body body)
20 `(progn
21 (api-call push-local-frame)
22 (unwind-protect
23 ,@body
24 (api-call pop-local-frame))))
25
19 26 ;;; Common
20 27
21 28 (defmacro defpsintrinsic (name)
@@ -33,17 +40,17 b''
33 40 (ps:defpsmacro api-call (func &rest args)
34 41 `(funcall (root api ,func) ,@args))
35 42
36 (ps:defpsmacro label-block (&body body)
43 (ps:defpsmacro label-block ((&key (locals t)) &body body)
37 44 (let ((has-labels (some #'keywordp body)))
38 45 `(block nil
39 46 ,@(when has-labels
40 47 '((defvar __labels)))
41 (api-call push-local-frame)
42 (unwind-protect
43 (tagbody
44 ,@body)
45 (api-call pop-local-frame))
46 (values))))
48 ,@(if locals
49 `((with-frame
50 (tagbody
51 ,@body)))
52 `((tagbody
53 ,@body))))))
47 54
48 55 (ps:defpsmacro str (&rest forms)
49 56 (cond ((zerop (length forms))
@@ -58,18 +65,20 b''
58 65
59 66 (ps:defpsmacro location ((name) &body body)
60 67 `(setf (root locs ,name)
61 (lambda ()
62 (label-block
63 ,@body))))
68 (lambda (args)
69 (label-block ()
70 (api-call init-args args)
71 ,@body
72 (api-call get-result)))))
64 73
65 74 (ps:defpsmacro goto (target &rest args)
66 75 `(progn
67 (funcall (root lib goto) ,target ,@args)
76 (funcall (root lib goto) ,target ,args)
68 77 (exit)))
69 78
70 79 (ps:defpsmacro xgoto (target &rest args)
71 80 `(progn
72 (funcall (root lib xgoto) ,target ,@args)
81 (funcall (root lib xgoto) ,target ,args)
73 82 (exit)))
74 83
75 84 (ps:defpsmacro desc (target)
@@ -78,12 +87,12 b''
78 87
79 88 ;;; 2var
80 89
81 (ps:defpsmacro var (name index)
82 `(api-call get-var ,(string name) ,index))
90 (ps:defpsmacro var (name index slot)
91 `(api-call get-var ,(string name) ,index ,slot))
83 92
84 (ps:defpsmacro set ((var vname vindex) value)
93 (ps:defpsmacro set ((var vname vindex vslot) value)
85 94 (assert (eq var 'var))
86 `(api-call set-var ,(string vname) ,vindex ,value))
95 `(api-call set-var ,(string vname) ,vindex ,vslot ,value))
87 96
88 97 ;;; 3expr
89 98
@@ -110,7 +119,8 b''
110 119 (ps:defpsmacro qspcond (&rest clauses)
111 120 `(cond ,@(loop :for clause :in clauses
112 121 :collect (list (first clause)
113 `(tagbody ,@(rest clause))))))
122 `(tagbody
123 ,@(rest clause))))))
114 124
115 125 ;;; 8sub
116 126
@@ -137,27 +147,29 b''
137 147 ,@body)
138 148 `(progn
139 149 (setf ,@(loop :for f :on funcs :by #'cddr
140 :append (list `(ps:@ __labels ,(first f))
141 `(block ,(intern (string-upcase (string (first f))))
142 ,@(second f)
143 ,@(when (third f)
144 `((funcall
145 (ps:getprop __labels ,(third f)))))))))
150 :append `((ps:@ __labels ,(first f))
151 (block ,(intern (string-upcase (string (first f))))
152 ,@(second f)
153 ,@(when (third f)
154 `((funcall
155 (ps:getprop __labels ,(third f)))))))))
146 156 (jump (str "__nil"))))))
147 157
148 158 ;;; 10dynamic
149 159
150 160 (ps:defpsmacro qspblock (&body body)
151 `(lambda ()
152 (label-block
153 ,@body)))
161 `(lambda (args)
162 (label-block ()
163 (api-call init-args args)
164 ,@body
165 (api-call get-result))))
154 166
155 167 ;;; 11main
156 168
157 169 (ps:defpsmacro act (name img &body body)
158 170 `(api-call add-act ,name ,img
159 171 (lambda ()
160 (label-block
172 (label-block ()
161 173 ,@body))))
162 174
163 175 ;;; 12aux
General Comments 0
You need to be logged in to leave comments. Login now