1 grammar TclExpr::PAST::Grammar is TGE::Grammar;
3 transform past (ROOT) {
5 unless null $P0 goto expression
6 .return tree.get('dispatch', node, 'TclExpr::Grammar')
9 .return tree.get('expression', node)
12 transform expression (TclExpr::Grammar) {
14 past = new 'PAST::Expr'
19 $P0 = tree.get('dispatch', node, 'TclExpr::Grammar')
25 # Handle generic dispatch (needed at ROOT, and for things with kids.)
27 transform dispatch (TclExpr::Grammar) {
30 # Ask the child node for its past.
33 unless null $P0 goto expand
34 $P0 = node['backslash_substitution']
35 unless null $P0 goto constant
37 unless null $P0 goto empty
39 unless null $P0 goto chunks
40 $P0 = node['substitution']
41 unless null $P0 goto substitution
43 unless null $P0 goto boolean
44 $P0 = node['braced_word']
45 unless null $P0 goto braced_word
47 unless null $P0 goto integer
49 unless null $P0 goto has_float
50 $P0 = node['scientific']
51 unless null $P0 goto scientific
53 unless null $P0 goto number
54 $P0 = node['quoted_word']
55 unless null $P0 goto quoted_word
56 $P0 = node['mathfunc']
57 unless null $P0 goto mathfunc
59 unless null $P0 goto program
60 $P0 = node['subcommand']
61 unless null $P0 goto program
62 $P0 = node['variable_substitution']
63 unless null $P0 goto variable_substitution
64 $P0 = node['command_substitution']
65 unless null $P0 goto command_substitution
67 unless null $P0 goto nested
69 unless null $P0 goto operator
71 say "Didn't know how to handle node:"
76 .return tree.get('past', $P0, 'program')
81 $P0['class'] = 'TclString'
85 .return tree.get('past', node, 'expand')
88 .return tree.get('past', $P0, 'array')
91 .return tree.get('past', node, 'operator')
94 .return tree.get('past', $P0, 'mathfunc')
97 .return tree.get('past', $P0, 'quoted_word')
100 .return tree.get('past', $P0, 'braced_word')
103 .return tree.get('past', $P0, 'number')
106 .return tree.get('past', $P0, 'boolean')
109 .return tree.get('past', $P0, 'constant')
112 .return tree.get('past', $P0, 'integer')
115 .return tree.get('past', $P0, 'float')
118 .return tree.get('past', $P0, 'scientific')
124 variable_substitution:
125 .return tree.get('past', $P0, 'variable_substitution')
127 command_substitution:
129 $P0 = node['subcommand']
130 unless null $P0 goto program
132 # we have an empty command substitution []
133 $P0 = new 'PAST::Val'
134 $P0['class'] = 'TclString'
139 .return tree.get('past', $P0, 'nested')
142 # Go through all the children of an operator and transform them.
144 transform past (operator) {
145 # for each child of this operator, dispatch to get the past,
146 # use those as our children.
147 .local pmc children, iter, past
151 if name == 'ternary:? :' goto is_ternary
152 if name == 'infix:&&' goto is_and
153 if name == 'infix:||' goto is_or
155 past = new 'PAST::Op'
157 past['opfunc'] = name
158 $P0 = node.'get_array'()
159 if null $P0 goto iter_end
160 iter = new 'Iterator', $P0
162 unless iter goto iter_end
165 $P1 = tree.'get'('dispatch', $P0, 'TclExpr::Grammar')
166 past.'add_child'($P1)
173 .return tree.get('ternary', node, 'PAST::Op')
175 .return tree.get('logical_and', node, 'PAST::Op')
177 .return tree.get('logical_or', node, 'PAST::Op')
180 transform past (expand) {
182 past = new 'PAST::Expand'
184 delete node['expand']
185 $P0 = tree.'get'('dispatch', node, 'TclExpr::Grammar')
191 transform past (program) {
193 past = new 'PAST::Program'
196 iter = new 'Iterator', node
200 $P0 = tree.'get'('past', $P0, 'command')
201 if null $P0 goto loop
202 past.'add_child'($P0)
206 $P0 = past.'get_children'()
208 if $I0 == 0 goto empty
213 past = new 'PAST::Val'
215 past['class'] = 'TclString'
219 transform past (mathfunc) {
220 .local string function_name
223 args = node['expression']
225 unless args goto has_argc
230 past = new 'PAST::MathFunc'
231 $P0 = node['unary_function']
232 unless null $P0 goto unary
233 $P0 = node['nullary_function']
234 unless null $P0 goto nullary
235 $P0 = node['binary_function']
236 unless null $P0 goto binary
237 $P0 = node['nary_function']
238 unless null $P0 goto nary
243 if argc > 0 goto too_many
244 function_name = node['nullary_function']
248 if argc == 0 goto too_few
249 if argc > 1 goto too_many
250 function_name = node['unary_function']
252 $P1 = tree.'get'('expression', $P0)
253 past.'add_child'($P1)
257 if argc < 2 goto too_few
258 if argc > 2 goto too_many
259 function_name = node['binary_function']
262 $P2 = tree.'get'('expression', $P1)
263 past.'add_child'($P2)
266 $P2 = tree.'get'('expression', $P1)
267 past.'add_child'($P2)
271 if argc < 1 goto too_few
272 function_name = node['nary_function']
275 iter = new 'Iterator', args
277 unless iter goto arguments
279 $P0 = tree.'get'('expression', $P0)
280 past.'add_child'($P0)
284 past['mathfunc'] = function_name
289 tcl_error 'too few arguments for math function'
292 tcl_error 'too many arguments for math function'
295 transform past (boolean) {
297 past = new 'PAST::Val'
305 past['class'] = "TclString"
309 transform past (constant) {
311 past = new 'PAST::Val'
319 past['class'] = "TclString"
323 transform past (braced_word) {
325 past = new 'PAST::Val'
328 $P0 = node['PGE::Text::bracketed']
331 past['class'] = "TclString"
335 transform past (number) {
336 $P0 = node['integer']
337 unless null $P0 goto integer
339 unless null $P0 goto have_float
340 $P0 = node['scientific']
341 unless null $P0 goto scientific
342 tcl_error 'invalid number type'
345 .return tree.get('past', $P0, 'integer')
348 .return tree.get('past', $P0, 'float')
351 .return tree.get('past', $P0, 'scientific')
355 transform past (nested) :language('PIR') {
357 $P0 = node['expression'; 'expr']
358 past = tree.'get'('dispatch', $P0, 'TclExpr::Grammar')
363 transform past (scientific) {
365 past = new 'PAST::Val'
377 past['class'] = "TclFloat"
382 transform past (integer) {
384 past = new 'PAST::Val'
388 unless null $P0 goto binary
390 unless null $P0 goto octal
392 unless null $P0 goto hex
394 # XXX (40863): This is a bad hack to make bignums compile
395 $S0 = node['decimal']
397 if $I0 < 10 goto decimal
398 if $I0 > 10 goto bignum_hack
400 if $S0 >= "2147483647" goto bignum_hack
405 past['class'] = "TclInt"
410 past['class'] = "TclInt"
420 if $I0 >= $I1 goto binary_done
422 $S2 = substr $S0, $I0, 1
424 if $S2 == '0' goto binary_loop
428 past['value'] = bvalue
429 past['class'] = "TclInt"
435 .local int octal_value, octal_digit, octal_counter, octal_length
436 octal_length = length $S0
439 # at this point, string should consist only of digits 0-7
441 if octal_counter == octal_length goto octal_done # skip first 0
442 octal_digit = ord $S0, octal_counter
443 octal_digit -= 48 # ascii value of 0
445 octal_value += octal_digit
450 past['value'] = octal_value
451 past['class'] = "TclInt"
456 .local int len, digit, hex_value
461 if $I0 == len goto hex_done
463 # higher than Z - must be lowercase letter
464 if digit > 90 goto hex_lower
465 # higher than 9 - must be uppercase letter
466 if digit > 57 goto hex_upper
467 digit -= 48 # value of 0
470 digit -= 97 # value of a
474 digit -= 65 # value of A
484 past['value'] = hex_value
485 past['class'] = "TclInt"
490 transform past (float) {
492 past = new 'PAST::Val'
497 past['class'] = "TclFloat"
501 transform past (quoted_word) {
504 if null $P0 goto empty_string
506 .return tree.get('past', $P0, 'array')
509 past = new 'PAST::Val'
511 past['class'] = 'TclString'
517 transform past (array) {
520 iter = new 'Iterator', node
523 unless iter goto iter_end
524 .local pmc cnode, cpast
526 $I0 = exists cnode['substitution']
527 unless $I0 goto cpast_str
528 cnode = cnode['substitution']
529 cpast = tree.'get'('dispatch', cnode, 'TclExpr::Grammar')
536 cpast = new 'PAST::Val'
538 cpast['class'] = 'TclString'
541 unless null past goto cpast_concat
549 $P0['opfunc'] = 'infix:concat'
556 transform past (command) {
557 .local pmc past, words, iter
558 .local string node_type
561 if null words goto empty
564 command = shift words
565 command = tree.'get'('dispatch', command, 'TclExpr::Grammar')
567 node_type = typeof command
568 if node_type == 'PAST::Val' goto static
570 node_type = 'PAST::DynamicCommand'
574 node_type = 'PAST::StaticCommand'
578 past.'add_child'(command)
580 iter = new 'Iterator', words
582 unless iter goto end2
584 $P1 = tree.'get'('dispatch', $P0, 'TclExpr::Grammar')
585 past.'add_child'($P1)
595 transform past (variable_substitution) {
597 past = new 'PAST::Var'
603 $I0 = exists node['index']
609 $P0 = tree.'get'('past', $P0, 'array')
614 transform ternary (PAST::Op) {
617 past = new 'PAST::Cond'
621 $P2 = tree.'get'('dispatch', $P1, 'TclExpr::Grammar')
622 past.'add_child'($P2)
624 $P2 = tree.'get'('dispatch', $P1, 'TclExpr::Grammar')
625 past.'add_child'($P2)
627 $P2 = tree.'get'('dispatch', $P1, 'TclExpr::Grammar')
628 past.'add_child'($P2)
630 past['conditional'] = 1
635 transform logical_and (PAST::Op) {
636 .local pmc past, true, false, A, B
639 # Transform A && B into:
640 # A ? ( B ? 1 : 0) : 0
642 true = new 'PAST::Val'
644 true['class'] = "TclInt"
646 false = new 'PAST::Val'
648 false['class'] = "TclInt"
650 # Get our A & B trees..
652 A = tree.'get'('dispatch', $P1, 'TclExpr::Grammar')
654 B = tree.'get'('dispatch', $P1, 'TclExpr::Grammar')
656 # Generate (B ? 1 : 0)
657 inner = new 'PAST::Cond'
660 inner.'add_child'(true)
661 inner.'add_child'(false)
662 inner['conditional'] = 1
664 # Generate (A ? (...) : 0)
665 past = new 'PAST::Cond'
670 past.'add_child' (inner)
671 past.'add_child' (false)
673 past['conditional'] = 1
678 transform logical_or (PAST::Op) {
679 .local pmc past, true, false, A, B
682 # Transform A || B into:
683 # A ? 1 : ( B ? 1 : 0)
685 true = new 'PAST::Val'
687 true['class'] = "TclInt"
689 false = new 'PAST::Val'
691 false['class'] = "TclInt"
693 # Get our A & B trees..
695 A = tree.'get'('dispatch', $P1, 'TclExpr::Grammar')
697 B = tree.'get'('dispatch', $P1, 'TclExpr::Grammar')
699 # Generate (B ? 1 : 0)
700 inner = new 'PAST::Cond'
703 inner.'add_child'(true)
704 inner.'add_child'(false)
705 inner['conditional'] = 1
707 # Generate (A ? 1 : (...))
708 past = new 'PAST::Cond'
713 past.'add_child' (true)
714 past.'add_child' (inner)
716 past['conditional'] = 1