bootstrap
view genesis/ometa/ometa-interpreter.church @ 867:3557dbdaf618
add new macros for getting and setting array values, which can work on both byte and word sized arrays
comment out some debugging print statements
comment out some debugging print statements
| author | John Leuner <jewel@subvert-the-dominant-paradigm.net> |
|---|---|
| date | Sun Apr 15 19:17:11 2012 +0200 (4 weeks ago) |
| parents | b937c15aa55d |
| children |
line source
1 extern o-fail
3 class ometa-rule
4 with-slots
5 name
6 instructions
7 original-instructions
8 variables
9 variables-length
10 transient?
11 rule-number
12 reference-count
14 print r:ometa-rule
15 out "<"
16 out r.name
17 out " ("
18 out r.reference-count
19 out ") "
20 out (if r.transient? "transient " "")
21 out r.variables
22 out " ; "
23 print r.instructions
25 ; for performance, inline these calls
26 ; note this breaks encapsulation
28 macro _o-fail? arg
29 <<
30 eq? \arg o-fail
31 >>
33 macro _unsafe-array-length array
34 <<
35 __v = \array
36 inline (deref (band __v LOWTAG_MASK) 16)
37 >>
39 ; no performance improvement
40 macro at-end? stream
41 <<
42 (== (\stream).input-position (_unsafe-array-length (\stream).input-array))
43 >>
45 get-variable-position rule-variables sym
46 (position sym rule-variables)
48 replace-variables-with-positions variables form quoting
49 typecase form
50 nil nil
51 cons
52 cond
53 (and quoting (eq? (first form) 'unquote))
54 pos = position (second form) variables
55 `[_ometa_get_variable ,pos]
56 (and quoting (eq? (first form) 'unquote-splice))
57 pos = position (second form) variables
58 `[_ometa_get_variable_splice ,pos]
59 (eq? (first form) 'quote)
60 (replace-variables-with-positions variables (second form) true)
61 (eq? (first form) 'quasiquote)
62 loop
63 for f in (second form)
64 collect (replace-variables-with-positions variables f true)
65 true
66 loop
67 for f in form
68 collect (replace-variables-with-positions variables f quoting)
69 else
70 if (string? form)
71 form
72 else
73 if quoting
74 `[quote ,form]
75 else
76 pos = get-variable-position variables form
77 if (null? pos)
78 error "var not found " (list form variables)
79 `[_ometa_get_variable ,pos]
84 class ometa-interpreter
85 with-slots
86 data-stack
87 rules
88 rules-map
89 memo-table
90 column-size
91 actions
92 instructions-map
93 ins-profile-map
94 ; call-profile-map
95 ; current-rule
96 ; tracing
97 init
98 ; self.two-key-memo = new 'two-key-dictionary
99 ; reset-memo self
100 ; self.ins-profile-map = new 'dictionary
101 ; create self.ins-profile-map 10000
102 ; self.call-profile-map = new 'dictionary
103 ; create self.call-profile-map 10000
104 self.instructions-map = new 'dictionary
105 create self.instructions-map 10000
106 self.actions = nil
107 ; self.current-rule = nil
108 reset-memo input-size
109 ; create self.two-key-memo 50000
110 ; self.current-rule = list 'top
111 self.memo-table = make-array (+ input-size 1) 4
112 rewrite-instruction rule form count-references
113 ; by using an equal-dictionary to 'intern' sequences of the same instructions
114 ; we are able to let the memoization in the parser share the same cache value
115 ; for identical sequences of instructions present in different rules
116 new-form = actual-rewrite-instruction self rule form count-references
117 lookup = get self.instructions-map new-form nil
118 if (null? lookup)
119 put self.instructions-map new-form new-form
120 new-form
121 else
122 lookup
123 actual-rewrite-instruction rule form count-references
124 ; print "rewrite-instruction 3"
125 ; print form
126 case (first form)
127 and
128 new-forms = [(rewrite-instruction self rule x count-references) for x in (cdr form)]
129 `[and |,(remove nil new-forms)]
130 or
131 new-forms = [(rewrite-instruction self rule x count-references) for x in (cdr form)]
132 `[or |,(remove nil new-forms)]
133 set
134 ; print "set"
135 ; print form
136 ; print rule.variables
137 rhs = third form
138 var-name = second form
139 if (not (symbol? var-name))
140 var-name = intern var-name
141 variable-position = get-variable-position rule.variables var-name
142 `[set ,variable-position ,(rewrite-instruction self rule rhs count-references)]
143 app
144 rule-name = second form
145 if (and (string? rule-name) (string-equal? rule-name "token"))
146 return-from actual-rewrite-instruction `[app-token ,rule-name ,(coerce rule-name 'array)]
147 if (eq? rule-name 'token)
148 str = (third form)
149 `[app-token ,str ,(coerce str 'array)]
150 else
151 if (eq? rule-name 'exactly)
152 args = cddr form
153 str = third form
154 if (cons? str)
155 str = second str
156 `[match-char ,(char-at str 0)]
157 else
158 ; print form
159 if (== (length form) 3)
160 if (and (cons? (third form)) (eq? (first (third form)) 'string))
161 `[app-with-string ,(intern (second form)) ,(second (third form))]
162 else
163 if (or (null? (third form)) (or (null? (third form)) (eq? 'nil (third form)) (string-equal? (third form) "nil")))
164 if (symbol? (second form))
165 `[app-with-nil ,(second form)]
166 else
167 `[app-with-nil ,(intern (second form))]
168 else
169 rule-name = second form
170 if (string? rule-name)
171 rule-name = intern rule-name
172 ; called-rule = get self.rules-map rule-name nil
173 ; if (not (null? called-rule))
174 ; if count-references
175 ; if (null? called-rule.reference-count)
176 ; called-rule.reference-count = 0
177 ; called-rule.reference-count = + called-rule.reference-count 1
178 `[app-with-argument ,(second form) ,(get-variable-position rule.variables (intern (third form)))]
179 else
180 calling-rule = rule
181 if (== (length form) 2)
182 rule-name = second form
183 if (string? (second form))
184 rule-name = intern rule-name
185 rule = get self.rules-map rule-name nil
186 if (null? rule)
187 `[app-no-memo ,rule-name]
188 else
189 if count-references
190 if (null? rule.reference-count)
191 rule.reference-count = 0
192 rule.reference-count = + rule.reference-count 1
193 if rule.transient?
194 `[app-rule-no-memo ,rule]
195 else
196 `[app-rule ,rule]
197 else
198 error "bad app form" form
199 act
200 ; print "*** rewrite act"
201 ; print rule.variables
202 ; print form
203 ; print (coerce (second form) 'array)
204 forms = (parse-sexps-from-array (coerce (second form) 'array))
205 if (null? forms)
206 error "bad sexp" form
207 act-form = first forms
208 ; print "act-form"
209 ; print act-form
210 res = `[act ,(replace-variables-with-positions rule.variables act-form nil)]
211 res
212 many
213 `[many ,(rewrite-instruction self rule (second form) count-references)]
214 many1
215 `[many1 ,(rewrite-instruction self rule (second form) count-references)]
216 not
217 `[not ,(rewrite-instruction self rule (second form) count-references)]
218 lookahead
219 `[not [not ,(rewrite-instruction self rule (second form) count-references)]]
220 loadarg
221 `[loadarg]
222 else
223 error "unhandled form" form
224 parse-memo-two-key rule-name stream frame-pointer stack-pointer
225 memo = self.two-key-memo
226 inputpos = stream.input-position
227 mark stream
228 ptr = get-ptr memo rule-name inputpos
229 if (== ptr 0)
230 result = (actual-parse self rule-name stream frame-pointer stack-pointer)
231 put-vals memo rule-name inputpos result stream.input-position
232 pop-mark stream
233 result
234 else
235 result = inline (deref ptr 0)
236 pos = inline (deref ptr CHURCH_WORD_SIZE)
237 if (not (eq? result o-fail))
238 reset-to stream pos
239 else
240 reset-to-mark stream
241 pop-mark stream
242 result
243 parse-memo rule-name stream frame-pointer stack-pointer
244 memo = self.memo-table
245 inputpos = stream.input-position
246 ; print "in parse-memo"
247 ; print memo
248 ; print inputpos
249 ; column = memo[inputpos]
250 column = unsafe-get-array-value memo inputpos
251 if (null? column)
252 ; print "making column"
253 ; print inputpos
254 column = make-array (* self.column-size 2) 4
255 ; memo[inputpos] = column
256 unsafe-set-array-value memo inputpos column
257 rule = get self.rules-map rule-name nil
258 ; assert rule "missing rule"
259 ; assert rule.rule-number "bad rule number"
260 ; print "lookup"
261 ; print column
262 ; print rule.rule-number
263 ; result = column[(* rule.rule-number 2)]
264 result = unsafe-get-array-value column (* rule.rule-number 2)
265 ; print result
266 if (null? result)
267 result = actual-parse self rule-name stream frame-pointer stack-pointer
268 ; column[(* rule.rule-number 2)] = result
269 unsafe-set-array-value column (* rule.rule-number 2) result
270 ; column[+ (* rule.rule-number 2) 1] = stream.input-position
271 unsafe-set-array-value column (+ (* rule.rule-number 2) 1) stream.input-position
272 result
273 else
274 ; reset-to stream column[+ (* rule.rule-number 2) 1]
275 reset-to stream (unsafe-get-array-value column (+ (* rule.rule-number 2) 1))
276 result
277 parse-memo-rule rule stream frame-pointer stack-pointer
278 memo = self.memo-table
279 inputpos = stream.input-position
280 column = unsafe-get-array-value memo inputpos
281 if (null? column)
282 column = make-array (* self.column-size 2) 4
283 unsafe-set-array-value memo inputpos column
284 result = unsafe-get-array-value column (* rule.rule-number 2)
285 if (null? result)
286 result = actual-parse-rule self rule stream frame-pointer stack-pointer
287 unsafe-set-array-value column (* rule.rule-number 2) result
288 unsafe-set-array-value column (+ (* rule.rule-number 2) 1) stream.input-position
289 result
290 else
291 reset-to stream (unsafe-get-array-value column (+ (* rule.rule-number 2) 1))
292 result
293 actual-parse rule-name stream frame-pointer stack-pointer
294 ; curr-rule = (if (null? self.current-rule) nil (unsafe-car self.current-rule))
295 ; self.current-rule = cons rule-name self.current-rule
296 ; cpm = self.call-profile-map
297 ; lookup1 = get cpm curr-rule nil
298 ; if (null? lookup1)
299 ; d = new 'dictionary
300 ; create d 10
301 ; put cpm curr-rule d
302 ; put d rule-name 1
303 ; else
304 ; d = lookup1
305 ; lookup2 = get d rule-name nil
306 ; if (null? lookup2)
307 ; put d rule-name 1
308 ; else
309 ; put d rule-name (+ lookup2 1)
310 lookup = get self.rules-map rule-name nil
311 if (null? lookup)
312 ; out "** primitive parse "
313 ; print rule-name
314 prim-result = apply rule-name self stream
315 ; self.current-rule = unsafe-cdr self.current-rule
316 prim-result
317 else
318 r = lookup
319 frame-pointer = stack-pointer
320 stack-pointer = + (+ stack-pointer r.variables-length) 1
321 loop
322 for i from frame-pointer to stack-pointer
323 do
324 self.data-stack[i] = nil
326 result = interpret self r.instructions stream frame-pointer stack-pointer
327 ; self.current-rule = unsafe-cdr self.current-rule
328 result
329 actual-parse-rule rule stream frame-pointer stack-pointer
330 r = rule
331 frame-pointer = stack-pointer
332 stack-pointer = + (+ stack-pointer r.variables-length) 1
333 loop
334 for i from frame-pointer to stack-pointer
335 do
336 self.data-stack[i] = nil
338 result = interpret self r.instructions stream frame-pointer stack-pointer
339 result
340 parse-with-arg rule-name stream frame-pointer stack-pointer arg
341 ; print "** parse with arg"
342 ; print rule-name
343 ; print arg
344 lookup = get self.rules-map rule-name nil
345 if (null? lookup)
346 ; error "primitive with arg" rule-name
347 apply rule-name self stream arg
348 else
349 r = lookup
350 frame-pointer = stack-pointer
351 stack-pointer = + (+ stack-pointer r.variables-length) 1
352 loop
353 for i from frame-pointer to stack-pointer
354 do
355 self.data-stack[i] = nil
357 self.data-stack[ frame-pointer ] = arg
358 interpret self r.instructions stream frame-pointer stack-pointer
359 seq stream arg
360 if (_o-fail? arg)
361 return-from seq o-fail
362 ; print "in seq"
363 ; print arg
364 mark stream
365 loop
366 for x in arg
367 do
368 str = x
369 ; print "seq str"
370 ; print str
371 ; print "next"
372 if (string? str)
373 print "is string"
374 error "not string" str
375 else
376 if (at-end? stream)
377 reset-to-mark stream
378 pop-mark stream
379 return-from seq o-fail
380 c = read-next stream
381 if (not (eq? c str))
382 reset-to-mark stream
383 pop-mark stream
384 return-from seq o-fail
386 pop-mark stream
387 ; print "in seq ret"
388 arg
389 anything stream
390 if (at-end? stream)
391 o-fail
392 else
393 read-next stream
394 cnewline stream
395 if (at-end? stream)
396 o-fail
397 else
398 c = peek stream
399 ; assert (== (peek-distance stream) 1) (list "bad peek distance" (peek-distance stream))
400 x = nil
401 inline (set! |x| (|church-make-character| 10))
402 if (eq? c x)
403 read-next stream
404 else
405 unpeek stream
406 o-fail
407 stringquote stream
408 if (at-end? stream)
409 o-fail
410 else
411 c = peek stream
412 ; assert (== (peek-distance stream) 1) (list "bad peek distance" (peek-distance stream))
413 x = nil
414 inline (set! |x| (|church-make-character| 34))
415 if (eq? c x)
416 read-next stream
417 else
418 unpeek stream
419 o-fail
420 digit stream
421 if (>= (remaining-byte-count stream) 1)
422 c = peek stream
423 ; assert (== (peek-distance stream) 1) (list "bad peek distance" (peek-distance stream))
424 if (and (char? c) (digit? c))
425 read-next stream
426 c
427 else
428 unpeek stream
429 o-fail
430 else
431 o-fail
432 letter stream
433 if (>= (remaining-byte-count stream) 1)
434 c = peek stream
435 ; assert (== (peek-distance stream) 1) (list "bad peek distance" (peek-distance stream))
436 if (and (char? c) (letter? c))
437 read-next stream
438 else
439 unpeek stream
440 o-fail
441 else
442 o-fail
443 interpret-action form frame-pointer stack-pointer quoting
444 ; print "interpret-action"
445 ; print form
446 ; print frame-pointer
447 typecase form
448 cons
449 if (eq? (unsafe-car form) 'quote)
450 second form
451 else
452 if (eq? (unsafe-car form) '_ometa_get_variable)
453 ; print "getting variable"
454 ; print (second form)
455 ; print self.data-stack[frame-pointer]
456 self.data-stack[+ frame-pointer (second form)]
457 else
458 collector = nil
459 loop
460 for x in form
461 do
462 if (and (cons? x) (eq? (unsafe-car x) '_ometa_get_variable_splice))
463 mylist = self.data-stack[+ frame-pointer (second x)]
464 collector = append! (reverse! mylist) collector
465 else
466 push (interpret-action self x frame-pointer stack-pointer quoting) collector
468 ; print collector
469 reverse! collector
470 else
471 error "bad type in interpret-action" form
472 interpret ins stream frame-pointer stack-pointer
473 ; record-trace stream.input-position ins
474 ; out "<-------- "
475 ; if (not (at-end? stream))
476 ; print (remaining stream)
477 ; print ins
478 ; print stream.input-position
479 ; print "stack-pointer"
480 ; print stack-pointer
481 ; print ">"
482 ; loop
483 ; for i from 0 to frame-pointer
484 ; do
485 ; print self.data-stack[i]
486 ;
487 ; print ">>"
488 ; loop
489 ; for i from frame-pointer to stack-pointer
490 ; do
491 ; print self.data-stack[i]
492 ;
493 ; pm = self.ins-profile-map
494 ; entry = get pm ins nil
495 ; if (null? entry)
496 ; put pm ins 1
497 ; else
498 ; put pm ins (+ 1 entry)
499 ; if self.tracing
500 ; print ins
501 case (unsafe-car ins)
502 match-char
503 if (>= (remaining-byte-count stream) 1)
504 arg = (unsafe-car (unsafe-cdr ins))
505 c = peek stream
506 ; assert (== (peek-distance stream) 1) (list "bad peek distance" (peek-distance stream))
507 if (eq? c arg)
508 read-next stream
509 else
510 unpeek stream
511 o-fail
512 else
513 o-fail
514 app-rule (parse-memo-rule self (unsafe-car (unsafe-cdr ins)) stream frame-pointer stack-pointer)
515 app-rule-no-memo (actual-parse-rule self (unsafe-car (unsafe-cdr ins)) stream frame-pointer stack-pointer)
516 app (parse-memo self (unsafe-car (unsafe-cdr ins)) stream frame-pointer stack-pointer)
517 app-no-memo (actual-parse self (unsafe-car (unsafe-cdr ins)) stream frame-pointer stack-pointer)
518 and
519 args = unsafe-cdr ins
520 if (null? args)
521 true
522 else
523 mark stream
524 answer = nil
525 loop
526 for x in args
527 do (answer = interpret self x stream frame-pointer stack-pointer)
528 when (_o-fail? answer)
529 do
530 reset-to-mark stream
531 pop-mark stream
532 return-from interpret o-fail
534 pop-mark stream
535 answer
536 or
537 mark stream
538 args = unsafe-cdr ins
539 ; if (null? args)
540 ; error "bad or" ins
541 loop
542 for x in args
543 do
544 reset-to-mark stream
545 answer = interpret self x stream frame-pointer stack-pointer
546 if (not (_o-fail? answer))
547 pop-mark stream
548 return-from interpret answer
550 pop-mark stream
551 o-fail
552 many
553 answer = nil
554 loop
555 do
556 mark stream
557 v = interpret self (unsafe-car (unsafe-cdr ins)) stream frame-pointer stack-pointer
558 if (_o-fail? v)
559 reset-to-mark stream
560 pop-mark stream
561 return-from interpret (reverse! answer)
562 push v answer
563 pop-mark stream
565 many1
566 x = unsafe-car (unsafe-cdr ins)
567 v = interpret self x stream frame-pointer stack-pointer
568 if (_o-fail? v)
569 o-fail
570 else
571 answer = list v
572 loop
573 do
574 mark stream
575 v = interpret self x stream frame-pointer stack-pointer
576 if (_o-fail? v)
577 reset-to-mark stream
578 pop-mark stream
579 return-from interpret (reverse! answer)
580 push v answer
581 pop-mark stream
583 act
584 ; print "act"
585 ; print ins
586 v = interpret-action self (unsafe-car (unsafe-cdr ins)) frame-pointer stack-pointer nil
587 ; print "interpret-action "
588 ; print v
589 v
590 set
591 index = unsafe-car (unsafe-cdr ins)
592 x = unsafe-car (unsafe-cdr (unsafe-cdr ins))
593 v = interpret self x stream frame-pointer stack-pointer
594 self.data-stack[+ frame-pointer index] = v
595 v
596 not
597 mark stream
598 if (_o-fail? (interpret self (unsafe-car (unsafe-cdr ins)) stream frame-pointer stack-pointer))
599 pop-mark stream
600 true
601 else
602 reset-to-mark stream
603 pop-mark stream
604 o-fail
605 app-token
606 str = second ins
607 char-array = (unsafe-car (unsafe-cdr (unsafe-cdr ins)))
608 len = _unsafe-array-length char-array
609 if (>= (remaining-byte-count stream) len)
610 input-position = stream.input-position
611 native1 = char-array.native-array
612 native2 = stream.input-array.native-array
613 result = 0
614 inline (set! result (tf (call-c memcmp native1 (+ native2 (* (uf input-position) CHURCH_WORD_SIZE)) (* (uf len) CHURCH_WORD_SIZE))))
615 if (== result 0)
616 read-ahead stream len
617 ; print "app-token returning"
618 ; print str
619 str
620 else
621 ;print "app-token failed"
622 ;print (remaining stream)
623 o-fail
624 else
625 o-fail
626 app-with-nil
627 parse-with-arg self (unsafe-car (unsafe-cdr ins)) stream frame-pointer stack-pointer nil
628 app-with-argument
629 parse-with-arg self (unsafe-car (unsafe-cdr ins)) stream frame-pointer stack-pointer self.data-stack[ + frame-pointer (unsafe-car (unsafe-cdr (unsafe-cdr ins)))]
630 app-with-string
631 parse-with-arg self (unsafe-car (unsafe-cdr ins)) stream frame-pointer stack-pointer (unsafe-car (unsafe-cdr (unsafe-cdr ins)))
632 loadarg
633 self.data-stack[frame-pointer]
634 dispatch-on-char
635 if (>= (remaining-byte-count stream) 1)
636 dispatch-table = second ins
637 c = peek stream
638 ; rule = dispatch-table[(char-code c)]
639 rule = unsafe-get-array-value dispatch-table (char-code c)
640 unpeek stream
641 if (null? rule)
642 o-fail
643 else
644 interpret self rule stream frame-pointer stack-pointer
645 else
646 o-fail
647 else
648 error "invalid ins" ins
650 global trace-table
652 record-trace position ins
653 entry = get trace-table ins nil
654 put trace-table ins (cons ins entry)
656 show-trace
657 keys = keys trace-table
658 total = 0
659 loop
660 for k in keys
661 do
662 total = + total (length (get trace-table k nil))
664 out "total is "
665 print total
