bootstrap

view genesis/ometa/ometa-interpreter.church @ 758:42c043932622

rename parse to parse-memo
add comments to ometa grammar
add 'transient' flags to ometa grammar
'memoize' instructions used by the interpreter so that we don't duplicate cons lists
author John Leuner <jewel@subvert-the-dominant-paradigm.net>
date Sun Apr 24 12:42:17 2011 +0200 (13 months ago)
parents 96f6eb9a4278
children 350b4488683d
line source
1 extern o-fail
3 class ometa-rule
4 with-slots
5 name
6 instructions
7 original-instructions
8 variables
9 flags
11 get-variable-position rule-variables sym
12 (position sym rule-variables)
14 replace-variables-with-positions variables form quoting
15 if (null? form)
16 form
17 else
18 typecase form
19 cons
20 cond
21 (and quoting (eq? (first form) 'unquote))
22 pos = position (second form) variables
23 `[_ometa_get_variable ,pos]
24 (and quoting (eq? (first form) 'unquote-splice))
25 pos = position (second form) variables
26 `[_ometa_get_variable_splice ,pos]
27 (eq? (first form) 'quote)
28 ,(replace-variables-with-positions variables (second form) true)
29 (eq? (first form) 'quasiquote)
30 loop
31 for f in (second form)
32 collect (replace-variables-with-positions variables f true)
33 true
34 loop
35 for f in form
36 collect (replace-variables-with-positions variables f quoting)
37 else
38 if (string? form)
39 form
40 else
41 if quoting
42 if (and (cons? form) (eq? (first form) 'quote))
43 form
44 else
45 `[quote ,form]
46 else
47 pos = get-variable-position variables form
48 if (null? pos)
49 error "var not found " (list form variables)
50 `[_ometa_get_variable ,pos]
53 class ometa-interpreter
54 with-slots
55 data-stack
56 rules
57 rules-map
58 memo
59 actions
60 instructions-map
61 profile-map
62 init
63 self.memo = new 'native-dictionary
64 create self.memo 10000
65 self.profile-map = new 'native-dictionary
66 create self.profile-map 10000
67 self.instructions-map = new 'equal-native-dictionary
68 create self.instructions-map 10000
69 self.actions = nil
70 reset-memo
71 self.memo = new 'native-dictionary
72 create self.memo 10000
73 rewrite-instruction rule form
74 new-form = actual-rewrite-instruction self rule form
75 lookup = get self.instructions-map new-form nil
76 if (null? lookup)
77 put self.instructions-map new-form new-form
78 new-form
79 else
80 lookup
81 actual-rewrite-instruction rule form
82 ; print "rewrite-instruction 3"
83 ; print form
84 case (first form)
85 and
86 new-forms = [(rewrite-instruction self rule x) for x in (cdr form)]
87 `[and |,(remove nil new-forms)]
88 or
89 new-forms = [(rewrite-instruction self rule x) for x in (cdr form)]
90 `[or |,(remove nil new-forms)]
91 set
92 ; print "set"
93 ; print form
94 ; print rule.variables
95 rhs = third form
96 variable-position = get-variable-position rule.variables (intern (second form))
97 `[set ,variable-position ,(rewrite-instruction self rule rhs)]
98 app
99 rule-name = second form
100 if (and (string? rule-name) (string-equal? rule-name "token"))
101 return-from actual-rewrite-instruction `[app-token ,rule-name ,(coerce rule-name 'array)]
102 if (eq? rule-name 'token)
103 str = (third form)
104 `[app-token ,str ,(coerce str 'array)]
105 else
106 if (eq? rule-name 'exactly)
107 args = cddr form
108 str = third form
109 if (cons? str)
110 str = second str
111 `[match-char ,(char-at str 0)]
112 else
113 ; print form
114 if (== (length form) 3)
115 if (and (cons? (third form)) (eq? (first (third form)) 'string))
116 `[app-with-string ,(intern (second form)) ,(second (third form))]
117 else
118 if (or (null? (third form)) (or (null? (third form)) (eq? 'nil (third form)) (string-equal? (third form) "nil")))
119 if (symbol? (second form))
120 `[app-with-nil ,(second form)]
121 else
122 `[app-with-nil ,(intern (second form))]
123 else
124 `[app-with-argument ,(second form) ,(get-variable-position rule.variables (intern (third form)))]
125 else
126 if (string? (second form))
127 `[app ,(intern (second form))]
128 else
129 form
130 act
131 ; print "*** rewrite act"
132 ; print rule.variables
133 ; print form
134 ; print (coerce (second form) 'array)
135 forms = (parse-sexps-from-array (coerce (second form) 'array))
136 if (null? forms)
137 error "bad sexp" form
138 act-form = first forms
139 res = `[act ,(replace-variables-with-positions rule.variables act-form nil)]
140 res
141 many
142 `[many ,(rewrite-instruction self rule (second form))]
143 many1
144 `[many1 ,(rewrite-instruction self rule (second form))]
145 not
146 `[not ,(rewrite-instruction self rule (second form))]
147 lookahead
148 `[not [not ,(rewrite-instruction self rule (second form))]]
149 loadarg
150 `[loadarg]
151 else
152 error "unhandled form" form
153 parse-memo rule-name stream frame-pointer stack-pointer
154 memo = self.memo
155 inputpos = stream.input-position
156 found = has? memo rule-name
157 mark stream
158 ; print "** parse-memo"
159 ; print rule-name
160 if found
161 lookup = get memo rule-name nil
162 lookup2 = get lookup inputpos nil
163 if (null? lookup2)
164 result = (actual-parse self rule-name stream frame-pointer stack-pointer)
165 put lookup inputpos (list result stream.input-position)
166 ; print "put result 1"
167 ; print (list result stream.input-position)
168 pop-mark stream
169 result
170 else
171 if (not (eq? (car lookup2) o-fail))
172 ; print "got memo "
173 ; print lookup2
174 reset-to stream (second lookup2)
175 else
176 reset-to-mark stream
177 pop-mark stream
178 car lookup2
179 else
180 result = (actual-parse self rule-name stream frame-pointer stack-pointer)
181 d = new 'native-dictionary
182 create d 100
183 put d inputpos (list result stream.input-position)
184 put memo rule-name d
185 ; print "put result 2"
186 ; print rule-name
187 ; print result
188 pop-mark stream
189 result
190 actual-parse rule-name stream frame-pointer stack-pointer
191 lookup = get self.rules-map rule-name nil
192 if (null? lookup)
193 ; out "** primitive parse "
194 ; print rule-name
195 prim-result = apply rule-name self stream
196 ; print prim-result
197 ; print (remaining stream)
198 prim-result
199 else
200 r = lookup
201 frame-pointer = stack-pointer
202 stack-pointer = + (+ stack-pointer (length r.variables)) 1
203 loop
204 for i from frame-pointer to stack-pointer
205 do
206 self.data-stack[i] = nil
208 result = interpret self r.instructions stream frame-pointer stack-pointer
209 ; print result
210 ; print (remaining stream)
211 result
212 parse-with-arg rule-name stream frame-pointer stack-pointer arg
213 ; print "** parse with arg"
214 ; print rule-name
215 ; print arg
216 lookup = get self.rules-map rule-name nil
217 if (null? lookup)
218 apply rule-name self stream arg
219 else
220 r = lookup
221 frame-pointer = stack-pointer
222 stack-pointer = + (+ stack-pointer (length r.variables)) 1
223 loop
224 for i from frame-pointer to stack-pointer
225 do
226 self.data-stack[i] = nil
228 self.data-stack[ frame-pointer ] = arg
229 interpret self r.instructions stream frame-pointer stack-pointer
230 seq stream arg
231 if (o-fail? arg)
232 return-from seq o-fail
233 ; print "in seq"
234 ; print arg
235 mark stream
236 loop
237 for x in arg
238 do
239 str = x
240 ; print "seq str"
241 ; print str
242 ; print "next"
243 if (string? str)
244 print "is string"
245 error "not string" str
246 else
247 if (at-end? stream)
248 reset-to-mark stream
249 pop-mark stream
250 return-from seq o-fail
251 c = read-next stream
252 if (not (eq? c str))
253 reset-to-mark stream
254 pop-mark stream
255 return-from seq o-fail
257 pop-mark stream
258 ; print "in seq ret"
259 arg
260 anything stream
261 if (at-end? stream)
262 o-fail
263 else
264 read-next stream
265 cnewline stream
266 if (at-end? stream)
267 o-fail
268 else
269 c = peek stream
270 ; assert (== (peek-distance stream) 1) (list "bad peek distance" (peek-distance stream))
271 x = nil
272 inline (set! |x| (|church-make-character| 10))
273 if (eq? c x)
274 read-next stream
275 else
276 unpeek stream
277 o-fail
278 stringquote stream
279 if (at-end? stream)
280 o-fail
281 else
282 c = peek stream
283 ; assert (== (peek-distance stream) 1) (list "bad peek distance" (peek-distance stream))
284 x = nil
285 inline (set! |x| (|church-make-character| 34))
286 if (eq? c x)
287 read-next stream
288 else
289 unpeek stream
290 o-fail
291 digit stream
292 if (>= (remaining-byte-count stream) 1)
293 c = peek stream
294 ; assert (== (peek-distance stream) 1) (list "bad peek distance" (peek-distance stream))
295 if (and (char? c) (digit? c))
296 read-next stream
297 c
298 else
299 unpeek stream
300 o-fail
301 else
302 o-fail
303 letter stream
304 if (>= (remaining-byte-count stream) 1)
305 c = peek stream
306 ; assert (== (peek-distance stream) 1) (list "bad peek distance" (peek-distance stream))
307 if (and (char? c) (letter? c))
308 read-next stream
309 else
310 unpeek stream
311 o-fail
312 else
313 o-fail
314 interpret-action form frame-pointer stack-pointer quoting
315 ; print "interpret-action"
316 ; print form
317 ; print frame-pointer
318 typecase form
319 cons
320 if (eq? (first form) 'quote)
321 second form
322 else
323 if (eq? (first form) '_ometa_get_variable)
324 ; print "getting variable"
325 ; print (second form)
326 ; print self.data-stack[frame-pointer]
327 self.data-stack[+ frame-pointer (second form)]
328 else
329 collector = nil
330 loop
331 for x in form
332 do
333 if (and (cons? x) (eq? (first x) '_ometa_get_variable_splice))
334 mylist = self.data-stack[+ frame-pointer (second x)]
335 collector = append! (reverse! mylist) collector
336 else
337 push (interpret-action self x frame-pointer stack-pointer quoting) collector
339 ; print collector
340 reverse! collector
341 else
342 error "bad type in interpret-action" form
343 interpret ins stream frame-pointer stack-pointer
344 ; out "<-------- "
345 ; if (not (at-end? stream))
346 ; print (remaining stream)
347 ; print ins
348 ; print stream.input-position
349 ; print "stack-pointer"
350 ; print stack-pointer
351 ; print ">"
352 ; loop
353 ; for i from 0 to frame-pointer
354 ; do
355 ; print self.data-stack[i]
356 ;
357 ; print ">>"
358 ; loop
359 ; for i from frame-pointer to stack-pointer
360 ; do
361 ; print self.data-stack[i]
362 ;
363 ; pm = self.profile-map
364 ; entry = get pm ins nil
365 ; if (null? entry)
366 ; put pm ins 1
367 ; else
368 ; put pm ins (+ 1 entry)
369 case (first ins)
370 match-char
371 if (>= (remaining-byte-count stream) 1)
372 arg = second ins
373 c = peek stream
374 ; assert (== (peek-distance stream) 1) (list "bad peek distance" (peek-distance stream))
375 if (eq? c arg)
376 read-next stream
377 else
378 unpeek stream
379 o-fail
380 else
381 o-fail
382 app (parse-memo self (second ins) stream frame-pointer stack-pointer)
383 app-no-memo (actual-parse self (second ins) stream frame-pointer stack-pointer)
384 and
385 args = rest ins
386 if (null? args)
387 true
388 else
389 mark stream
390 answer = nil
391 loop
392 for x in args
393 do (answer = interpret self x stream frame-pointer stack-pointer)
394 when (o-fail? answer)
395 do
396 reset-to-mark stream
397 pop-mark stream
398 return-from interpret o-fail
400 pop-mark stream
401 answer
402 or
403 mark stream
404 args = rest ins
405 if (null? args)
406 error "bad or" ins
407 loop
408 for x in args
409 do
410 reset-to-mark stream
411 answer = interpret self x stream frame-pointer stack-pointer
412 if (not (o-fail? answer))
413 pop-mark stream
414 return-from interpret answer
416 pop-mark stream
417 o-fail
418 many
419 answer = nil
420 loop
421 do
422 mark stream
423 v = interpret self (second ins) stream frame-pointer stack-pointer
424 if (o-fail? v)
425 reset-to-mark stream
426 pop-mark stream
427 return-from interpret (reverse! answer)
428 push v answer
429 pop-mark stream
431 many1
432 x = second ins
433 v = interpret self x stream frame-pointer stack-pointer
434 if (o-fail? v)
435 o-fail
436 else
437 answer = list v
438 loop
439 do
440 mark stream
441 v = interpret self x stream frame-pointer stack-pointer
442 if (o-fail? v)
443 reset-to-mark stream
444 pop-mark stream
445 return-from interpret (reverse! answer)
446 push v answer
447 pop-mark stream
449 act
450 ; print "act"
451 ; print ins
452 v = interpret-action self (second ins) frame-pointer stack-pointer nil
453 ; print "interpret-action "
454 ; print v
455 v
456 set
457 index = second ins
458 x = third ins
459 v = interpret self x stream frame-pointer stack-pointer
460 self.data-stack[+ frame-pointer index] = v
461 v
462 not
463 mark stream
464 if (o-fail? (interpret self (second ins) stream frame-pointer stack-pointer))
465 pop-mark stream
466 true
467 else
468 reset-to-mark stream
469 pop-mark stream
470 o-fail
471 app-token
472 str = second ins
473 char-array = third ins
474 len = length char-array
475 if (>= (remaining-byte-count stream) len)
476 input-position = stream.input-position
477 native1 = char-array.native-array
478 native2 = stream.input-array.native-array
479 result = 0
480 inline (set! result (tf (call-c memcmp native1 (+ native2 (* (uf input-position) CHURCH_WORD_SIZE)) (* (uf len) CHURCH_WORD_SIZE))))
481 if (== result 0)
482 read-ahead stream len
483 ; print "app-token returning"
484 ; print str
485 str
486 else
487 ;print "app-token failed"
488 ;print (remaining stream)
489 o-fail
490 else
491 o-fail
492 app-with-nil
493 parse-with-arg self (second ins) stream frame-pointer stack-pointer nil
494 app-with-argument
495 parse-with-arg self (second ins) stream frame-pointer stack-pointer self.data-stack[ + frame-pointer (third ins)]
496 app-with-string
497 parse-with-arg self (second ins) stream frame-pointer stack-pointer (third ins)
498 loadarg
499 self.data-stack[frame-pointer]
500 else
501 error "invalid ins" ins