Tagging trunk at r29452 so that the noautopack can later be synched to it.
[parrot.git] / languages / lua / src / POSTGrammar.tg
blob04bd73969c4040d499c7b7c5041857c29f74cc18
1 # Copyright (C) 2007-2008, The Perl Foundation.
2 # $Id$
4 =head1 NAME
6 POSTGrammar.tg - A grammar for transforming the abstract syntax tree (PAST)
7 into an opcode syntax tree (POST).
9 =head1 DESCRIPTION
12 =cut
14 grammar Lua::POST::Grammar is TGE::Grammar;
17 transform post (PAST::Block) :language('PIR') {
18     null $P0
19     set_hll_global ['Lua::POST'], '$?environ', $P0
20     .local pmc endlabels
21     endlabels = get_hll_global ['Lua::POST'], '@endlabels'
22     new $P0, 'ResizableStringArray'
23     set_hll_global ['Lua::POST'], '@endlabels', $P0
24     .local pmc outerpost
25     outerpost = get_hll_global ['Lua::POST'], '$?SUB'
26     .local string name
27     $S0 = node.'name'()
28     unless $S0 == '' goto L1
29     $S0 = 'anon'
30   L1:
31     .local pmc post
32     $P0 = get_hll_global ['Lua'; 'POST'], 'Sub'
33     post = $P0.'new'('node'=>node, 'outer'=>outerpost, 'pirflags'=>':anon :lex', 'blocktype'=>'declaration')
34     $S1 = $S0 . '_'
35     name = post.'unique'($S1)
36     post.'name'(name)
37     new $P0, 'Hash'
38     post.'storage_lex'($P0)
39     new $P0, 'Hash'
40     post.'storage_const'($P0)
41     $P0 = post.'push_new'('POST::Ops')
42     post.'ops_const'($P0)
43     $P0 = post.'push_new'('POST::Ops')
44     post.'ops_subr'($P0)
45     set_hll_global ['Lua::POST'], '$?SUB', post
46     .local pmc iter, cpost
47     iter = node.'iterator'()
48   L2:
49     unless iter goto L3
50     $P0 = shift iter
51     cpost = tree.'get'('post', $P0)
52     post.'push'(cpost)
53     goto L2
54   L3:
55     set_hll_global ['Lua::POST'], '$?SUB', outerpost
56     set_hll_global ['Lua::POST'], '@endlabels', endlabels
57     .local string esc_name
58     esc_name = post.'escape'(name)
59     if null outerpost goto L4
60     .local pmc ops_subr
61     ops_subr = outerpost.'ops_subr'()
62     $I0 = defined ops_subr
63     unless $I0 goto L5
64     ops_subr.'push_pirop'('inline', 'inline'=><<'PIRCODE')
65     .local pmc subr
66     subr = interpinfo .INTERPINFO_CURRENT_SUB
67 PIRCODE
68     new $P0, 'Undef'
69     outerpost.'ops_subr'($P0)
70   L5:
71     .local pmc ops
72     $P0 = get_hll_global ['POST'], 'Ops'
73     ops = $P0.'new'('node'=>node)
74     ops.'push'(post)
75     $S0 = post.'unique'('fct_')
76     ops.'push_pirop'('inline', $S0, esc_name, 'inline'=>'    .const .Sub %0 = %1')
77     .local string result
78     result = ops.'unique'('$P')
79     ops.'push_pirop'('newclosure', result, $S0)
80     $S0 = ops.'unique'('$P')
81     ops.'push_pirop'('callmethod', 'getfenv', 'subr', 'result'=>$S0)
82     ops.'push_pirop'('callmethod', 'setfenv', result, $S0, 'result'=>'')
83     ops.'result'(result)
84     .return (ops)
85   L4:
86     .local pmc start
87     $P0 = get_hll_global ['Lua'; 'POST'], 'Sub'
88     start = $P0.'new'('name'=>'&start', 'pirflags'=>':anon :main')
89     start.'push_pirop'('inline', esc_name, 'inline'=><<'PIRCODE')
90     .param pmc args :optional
91 #    print "start\n"
92     load_bytecode "languages/lua/lua.pbc"
93     lua_openlibs()
94     .local pmc env
95     env = get_hll_global "_G"
96     .local pmc vararg
97     vararg = argstolua(env, args)
98     .const .Sub main = %0
99     main."setfenv"(env)
100     ($I0, $P0) = docall(main, vararg :flat)
101     unless $I0 goto L1
102     printerr "luap: "
103     printerr $P0
104   L1:
105 PIRCODE
106     post.'outer'(start)
107     start.'push'(post)
108     $P0 = get_hll_global ['Lua'; 'POST'], 'Chunk'
109     .return $P0.'new'(start, 'node'=>node, 'prologue'=><<'PIRCODE')
110 .include "interpinfo.pasm"
111 .HLL "Lua", "lua_group"
112 PIRCODE
116 transform post (PAST::Stmts) :language('PIR') {
117     .local pmc ops
118     $P0 = get_hll_global ['POST'], 'Ops'
119     ops = $P0.'new'('node'=>node)
120     .local pmc iter
121     iter = node.'iterator'()
122   L1:
123     unless iter goto L2
124     $P0 = shift iter
125     $P1 = tree.'get'('void', $P0)
126     ops.'push'($P1)
127     goto L1
128   L2:
129     null $P0
130     set_hll_global ['Lua::POST'], '$?environ', $P0
131     .return (ops)
135 transform void (PAST::Stmts) :language('PIR') {
136     .return tree.'get'('post', node)
140 transform void (PAST::Op) :language('PIR') {
141     $S0 = node.'pasttype'()
142     .return tree.'get'($S0, node)
146 transform cond (PAST::Op) :language('PIR') {
147     $S0 = node.'pirop'()
148     $I0 = index $S0, 'is'
149     unless $I0 >= 0 goto L1
150     .return tree.'get'('cmp', node)
151   L1:
152     .return tree.'get'('post', node)
156 transform post (PAST::Op) :language('PIR') {
157     $S0 = node.'pasttype'()
158     unless $S0 == 'call' goto L1
159     .local pmc post
160     post = tree.'get'($S0, node)
161     $P0 = post.'pop'()
162     .local string result
163     result = post.'unique'('$P')
164     post.'push_pirop'('new', result, '"LuaNil"')
165     $P0.'result'(result)
166     post.'push'($P0)
167     post.'result'(result)
168     .return (post)
169   L1:
170     .return tree.'get'($S0, node)
174 transform pirop (PAST::Op) :language('PIR') {
175     .local string result
176     $S0 = node.'pirop'()
177     $I0 = index $S0, 'is'
178     unless $I0 >= 0 goto L1
179     .local pmc post
180     post = tree.'get'('cmp', node)
181     $S0 = post.'result'()
182     result = post.'unique'('$P')
183     post.'push_pirop'('new', result, '"LuaBoolean"')
184     post.'push_pirop'('set', result, $S0)
185     post.'result'(result)
186     .return (post)
187   L1:
188     .local pmc ops
189     $P0 = get_hll_global ['POST'], 'Ops'
190     ops = $P0.'new'('node'=>node)
191     .local pmc arglist, iter
192     new arglist, 'ResizableStringArray'
193     iter = node.'iterator'()
194   L2:
195     unless iter goto L3
196     .local pmc cpost
197     $P0 = shift iter
198     cpost = tree.'get'('post', $P0)
199     ops.'push'(cpost)
200     $S1 = cpost.'result'()
201     push arglist, $S1
202     goto L2
203   L3:
204     result = ops.'unique'('$P')
205     post = ops.'push_pirop'($S0, result, arglist :flat, 'node'=>node, 'result'=>result)
206     ops.'result'(result)
207     .return (ops)
211 transform cmp (PAST::Op) :language('PIR') {
212     .local pmc ops
213     $P0 = get_hll_global ['POST'], 'Ops'
214     ops = $P0.'new'('node'=>node)
215     .local pmc expr1
216     $P0 = node[0]
217     expr1 = tree.'get'('post', $P0)
218     ops.'push'(expr1)
219     .local pmc expr2
220     $P0 = node[1]
221     expr2 = tree.'get'('post', $P0)
222     ops.'push'(expr2)
223     .local string pirop
224     pirop = node.'pirop'()
225     $S0 = ops.'unique'('$I')
226     ops.'push_pirop'(pirop, $S0, expr1, expr2, 'node'=>node)
227     ops.'result'($S0)
228     .return (ops)
232 transform call (PAST::Op) :language('PIR') {
233     .local pmc ops
234     $P0 = get_hll_global ['POST'], 'Ops'
235     ops = $P0.'new'('node'=>node)
236     .local pmc arglist, iter, cpost
237     new arglist, 'ResizableStringArray'
238     iter = node.'iterator'()
239     .local int first
240     first = 1
241   L1:
242     unless iter goto L2
243     $P0 = shift iter
244     cpost = tree.'get'('post', $P0)
245     ops.'push'(cpost)
246     $S0 = cpost.'result'()
247     if first goto L3
248     if iter goto L3
249     ($I0, $P0) = cpost.'has_call_in_last_op'()
250     unless $I0 goto L3
251     $S1 = '(' . $S0
252     $S1 .= ' :slurpy)'
253     $P0.'result'($S1)
254     $S0 .= ' :flat'
255   L3:
256     first = 0
257     push arglist, $S0
258     goto L1
259   L2:
260     ops.'push_pirop'('call', arglist :flat, 'node'=>node, 'result'=>'')
261     null $P0
262     set_hll_global ['Lua::POST'], '$?environ', $P0
263     .return (ops)
267 transform len (PAST::Op) :language('PIR') {
268     .local pmc ops
269     $P0 = get_hll_global ['POST'], 'Ops'
270     ops = $P0.'new'('node'=>node)
271     .local pmc expr
272     $P0 = node[0]
273     expr = tree.'get'('post', $P0)
274     ops.'push'(expr)
275     .local string result
276     result = ops.'unique'('$P')
277     $S0 = ops.'escape'('len')
278     ops.'push_pirop'('callmethod', $S0, expr, 'node'=>node, 'result'=>result)
279     ops.'result'(result)
280     .return (ops)
284 transform and (PAST::Op) :language('PIR') {
285     .local pmc ops
286     $P0 = get_hll_global ['POST'], 'Ops'
287     ops = $P0.'new'('node'=>node)
288     .local string type
289     type = node.'pasttype'()
290     .local pmc expr1
291     $P0 = node[0]
292     expr1 = tree.'get'('post', $P0)
293     ops.'push'(expr1)
294     .local string label, endlabel
295     $S1 = type . '_'
296     label = ops.'unique'($S1)
297     endlabel = label . '_end'
298     $S0 = ops.'unique'('$P')
299     unless type == 'and' goto L1
300     ops.'push_pirop'('if', expr1, label)
301     goto L2
302   L1:
303     ops.'push_pirop'('unless', expr1, label)
304   L2:
305     ops.'push_pirop'('clone', $S0, expr1)
306     ops.'push_pirop'('goto', endlabel)
307     ops.'push_new'('POST::Label', 'result'=>label)
308     .local pmc expr2
309     $P0 = node[1]
310     expr2 = tree.'get'('post', $P0)
311     ops.'push'(expr2)
312     ops.'push_pirop'('clone', $S0, expr2)
313     ops.'push_new'('POST::Label', 'result'=>endlabel)
314     ops.'result'($S0)
315     .return (ops)
319 transform or (PAST::Op) :language('PIR') {
320     .return tree.'get'('and', node)
324 transform vararg (PAST::Op) :language('PIR') {
325     .local pmc ops
326     $P0 = get_hll_global ['POST'], 'Ops'
327     ops = $P0.'new'('node'=>node)
328     .local string result
329     result = ops.'unique'('$P')
330     ops.'push_pirop'('new', result, '"LuaNil"')
331     ops.'push_pirop'('call', 'mkarg', 'vararg', 'result'=>result)
332     ops.'result'(result)
333     .return (ops)
337 transform if (PAST::Op) :language('PIR') {
338     .local pmc ops
339     $P0 = get_hll_global ['POST'], 'Ops'
340     ops = $P0.'new'('node'=>node)
341     .local string thenlabel, endlabel
342     thenlabel = ops.'unique'('if_')
343     endlabel = thenlabel . '_end'
344     .local pmc expr
345     $P0 = node[0]
346     expr = tree.'get'('cond', $P0)
347     ops.'push'(expr)
348     ops.'push_pirop'('if', expr, thenlabel)
349     .local pmc else
350     $P0 = node[2]
351     $I0 = defined $P0
352     if $I0 == 0 goto L1
353     else = tree.'get'('post', $P0)
354     ops.'push'(else)
355   L1:
356     ops.'push_pirop'('goto', endlabel)
357     ops.'push_new'('POST::Label', 'result'=>thenlabel)
358     .local pmc then
359     $P0 = node[1]
360     $I0 = defined $P0
361     if $I0 == 0 goto L2
362     then = tree.'get'('post', $P0)
363     ops.'push'(then)
364   L2:
365     ops.'push_new'('POST::Label', 'result'=>endlabel)
366     .return (ops)
370 transform while (PAST::Op) :language('PIR') {
371     .local pmc endlabels
372     endlabels = get_hll_global ['Lua::POST'], '@endlabels'
373     .local pmc ops
374     $P0 = get_hll_global ['POST'], 'Ops'
375     ops = $P0.'new'('node'=>node)
376     .local string looplabel, endlabel
377     looplabel = ops.'unique'('while_')
378     endlabel = looplabel . '_end'
379     unshift endlabels, endlabel
380     ops.'push_new'('POST::Label', 'result'=>looplabel)
381     .local pmc expr
382     $P0 = node[0]
383     expr = tree.'get'('cond', $P0)
384     ops.'push'(expr)
385     ops.'push_pirop'('unless', expr, endlabel)
386     .local pmc blk
387     $P0 = node[1]
388     blk = tree.'get'('post', $P0)
389     ops.'push'(blk)
390     ops.'push_pirop'('goto', looplabel)
391     ops.'push_new'('POST::Label', 'result'=>endlabel)
392     $P0 = shift endlabels
393     .return (ops)
397 transform repeat (PAST::Op) :language('PIR') {
398     .local pmc endlabels
399     endlabels = get_hll_global ['Lua::POST'], '@endlabels'
400     .local pmc ops
401     $P0 = get_hll_global ['POST'], 'Ops'
402     ops = $P0.'new'('node'=>node)
403     .local string looplabel, endlabel
404     looplabel = ops.'unique'('repeat_')
405     endlabel = looplabel . '_end'
406     unshift endlabels, endlabel
407     ops.'push_new'('POST::Label', 'result'=>looplabel)
408     .local pmc blk
409     $P0 = node[0]
410     blk = tree.'get'('post', $P0)
411     ops.'push'(blk)
412     .local pmc expr
413     $P0 = node[1]
414     expr = tree.'get'('cond', $P0)
415     ops.'push'(expr)
416     ops.'push_pirop'('if', expr, endlabel)
417     ops.'push_pirop'('goto', looplabel)
418     ops.'push_new'('POST::Label', 'result'=>endlabel)
419     $P0 = shift endlabels
420     .return (ops)
424 transform fornum (PAST::Op) :language('PIR') {
425     .local pmc endlabels
426     endlabels = get_hll_global ['Lua::POST'], '@endlabels'
427     .local pmc ops
428     $P0 = get_hll_global ['POST'], 'Ops'
429     ops = $P0.'new'('node'=>node)
430     .local pmc e_var, e_limit, e_step
431     $P0 = node[1]
432     $P1 = $P0[0]
433     e_var = tree.'get'('post', $P1)
434     ops.'push'(e_var)
435     $P1 = $P0[1]
436     e_limit = tree.'get'('post', $P1)
437     ops.'push'(e_limit)
438     $P1 = $P0[2]
439     e_step = tree.'get'('post', $P1)
440     ops.'push'(e_step)
441     .local string var
442     $P0 = node[0]
443     $P0 = tree.'get'('post', $P0)
444     $P1 = $P0.'pop'()
445     ops.'push'($P0)
446     $P1 = $P0.'pop'()
447     $P0.'push'($P1)
448     var = $P1.'result'()
449     .local string limit, step
450     limit = ops.'unique'('$P')
451     step = ops.'unique'('$P')
452     ops.'push_pirop'('inline', var, limit, step, e_var, e_limit, e_step, 'inline'=>'    (%0, %1, %2) = checkforloop(%3, %4, %5)')
453     .local string incr
454     $S0 = ops.'unique'('$N')
455     ops.'push_pirop'('set', $S0, step)
456     incr = ops.'unique'('$I')
457     ops.'push_pirop'('isgt', incr, $S0, '0.0')
458     .local string looplabel, endlabel, orlabel, blklabel
459     looplabel = ops.'unique'('fornum_')
460     orlabel = looplabel . '_or'
461     blklabel = looplabel . '_blk'
462     endlabel = looplabel . '_end'
463     unshift endlabels, endlabel
464     ops.'push_new'('POST::Label', 'result'=>looplabel)
465     ops.'push_pirop'('unless', incr, orlabel)
466     ops.'push_pirop'('gt', var, limit, endlabel)
467     ops.'push_pirop'('goto', blklabel)
468     ops.'push_new'('POST::Label', 'result'=>orlabel)
469     ops.'push_pirop'('lt', var, limit, endlabel)
470     ops.'push_new'('POST::Label', 'result'=>blklabel)
471     .local pmc blk
472     $P0 = node[2]
473     blk = tree.'get'('post', $P0)
474     ops.'push'(blk)
475     ops.'push_pirop'('add', var, step)
476     ops.'push_pirop'('goto', looplabel)
477     ops.'push_new'('POST::Label', 'result'=>endlabel)
478     $P0 = shift endlabels
479     .return (ops)
483 transform forlist (PAST::Op) :language('PIR') {
484     .local pmc endlabels
485     endlabels = get_hll_global ['Lua::POST'], '@endlabels'
486     .local pmc ops
487     $P0 = get_hll_global ['POST'], 'Ops'
488     ops = $P0.'new'('node'=>node)
489     .local pmc explist, rpost
490     explist = node[1]
491     .local string func, state, var
492     .local pmc iter
493     new iter, 'Iterator', explist
494     $P0 = shift iter
495     rpost = tree.'get'('post', $P0)
496     ops.'push'(rpost)
497     func = rpost.'result'()
498     if iter goto L1
499     $I0 = rpost.'has_call_in_last_op'()
500     unless $I0 goto L1
501     $P0 = rpost.'pop'()
502     $S0 = '(' . func
503     state = rpost.'unique'('$P')
504     rpost.'push_pirop'('new', state, '"LuaNil"')
505     $S0 .= ', '
506     $S0 .= state
507     var = rpost.'unique'('$P')
508     rpost.'push_pirop'('new', var, '"LuaNil"')
509     $S0 .= ', '
510     $S0 .= var
511     $S0 .= ')'
512     $P0.'result'($S0)
513     rpost.'push'($P0)
514   L1:
515     unless iter goto L4
516     $P0 = shift iter
517     rpost = tree.'get'('post', $P0)
518     ops.'push'(rpost)
519     state = rpost.'result'()
520     if iter goto L2
521     $I0 = rpost.'has_call_in_last_op'()
522     unless $I0 goto L2
523     $P0 = rpost.'pop'()
524     $S0 = '(' . state
525     var = rpost.'unique'('$P')
526     rpost.'push_pirop'('new', var, '"LuaNil"')
527     $S0 .= ', '
528     $S0 .= var
529     $S0 .= ')'
530     $P0.'result'($S0)
531     rpost.'push'($P0)
532   L2:
533     unless iter goto L4
534     $P0 = shift iter
535     rpost = tree.'get'('post', $P0)
536     ops.'push'(rpost)
537     var = rpost.'result'()
538   L3:
539     unless iter goto L4
540     $P0 = shift iter
541     rpost = tree.'get'('post', $P0)
542     ops.'push'(rpost)
543     goto L3
544   L4:
545     unless state == '' goto L5
546     var = ops.'unique'('$P')
547     ops.'push_pirop'('new', var, '"LuaNil"')
548   L5:
549     unless var == '' goto L6
550     var = ops.'unique'('$P')
551     ops.'push_pirop'('new', var, '"LuaNil"')
552   L6:
553     .local pmc namelist, lpost, tmp
554     namelist = node[0]
555     new iter, 'Iterator', namelist
556     new tmp, 'ResizableStringArray'
557   L7:
558     unless iter goto L8
559     $P0 = shift iter
560     lpost = tree.'get'('post', $P0)
561     lpost.'pop'()
562     ops.'push'(lpost)
563     $P1 = lpost.'pop'()
564     lpost.'push'($P1)
565     $S1 = $P1.'result'()
566     push tmp, $S1
567     goto L7
568   L8:
569     .local string looplabel, endlabel
570     looplabel = ops.'unique'('forlist_')
571     endlabel = looplabel . '_end'
572     unshift endlabels, endlabel
573     ops.'push_new'('POST::Label', 'result'=>looplabel)
574     new iter, 'Iterator', tmp
575     $S0 = '('
576   L9:
577     unless iter goto L10
578     $S1 = shift iter
579     ops.'push_pirop'('new', $S1, '"LuaNil"')
580     if $S0 == '(' goto L11
581     $S0 .= ', '
582   L11:
583     $S0 .= $S1
584     goto L9
585   L10:
586     $S0 .= ')'
587     ops.'push_pirop'('call', func, state, var, 'node'=>node, 'result'=>$S0)
588     $S0 = tmp[0]
589     ops.'push_pirop'('assign', var, $S0)
590     $S0 = ops.'unique'('$I')
591     ops.'push_pirop'('isa', $S0, var, '"LuaNil"')
592     ops.'push_pirop'('if', $S0, endlabel)
593     .local pmc blk
594     $P0 = node[2]
595     blk = tree.'get'('post', $P0)
596     ops.'push'(blk)
597     ops.'push_pirop'('goto', looplabel)
598     ops.'push_new'('POST::Label', 'result'=>endlabel)
599     $P0 = shift endlabels
600     .return (ops)
604 transform return (PAST::Op) :language('PIR') {
605     .local pmc ops
606     $P0 = get_hll_global ['POST'], 'Ops'
607     ops = $P0.'new'('node'=>node)
608     .local pmc arglist
609     new arglist, 'ResizableStringArray'
610     .local pmc iter, cpost
611     iter = node.'iterator'()
612   L1:
613     unless iter goto L2
614     $P0 = shift iter
615     cpost = tree.'get'('post', $P0)
616     ops.'push'(cpost)
617     $S0 = cpost.'result'()
618     if iter goto L3
619     ($I0, $P0) = cpost.'has_call_in_last_op'()
620     unless $I0 goto L3
621     if arglist goto L4
622     $P0.'pirop'('tailcall')
623     .return (ops)
624   L4:
625     $S1 = '(' . $S0
626     $S1 .= ' :slurpy)'
627     $P0.'result'($S1)
628     $S0 .= ' :flat'
629   L3:
630     push arglist, $S0
631     goto L1
632   L2:
633     ops.'push_pirop'('return', arglist :flat)
634     .return (ops)
638 transform break (PAST::Op) :language('PIR') {
639     .local pmc endlabels
640     endlabels = get_hll_global ['Lua::POST'], '@endlabels'
641     $S0 = endlabels[0]
642     $P0 = get_hll_global ['POST'], 'Op'
643     .return $P0.'new'($S0, 'node'=>node, 'pirop'=>'goto')
647 transform assign (PAST::Op) :language('PIR') {
648     .local pmc ops
649     $P0 = get_hll_global ['POST'], 'Ops'
650     ops = $P0.'new'('node'=>node)
651     .local pmc rpost
652     $P0 = node[1]
653     rpost = tree.'get'('post', $P0)
654     .local string val
655     val = rpost.'result'()
656     ops.'push'(rpost)
657     .local pmc lpost
658     $P0 = node[0]
659     lpost = tree.'get'('post', $P0)
660     .local pmc ass
661     ass = lpost.'pop'()
662     ops.'push'(lpost)
663     ass.'push'(val)
664     ops.'push'(ass)
665     .return (ops)
669 transform assignlist (PAST::Op) :language('PIR') {
670     .local pmc ops
671     $P0 = get_hll_global ['POST'], 'Ops'
672     ops = $P0.'new'('node'=>node)
673     .local pmc namelist, explist
674     namelist = node[0]
675     explist = node[1]
676     .local pmc iter, tmp, rpost
677     new tmp, 'ResizableStringArray'
678     new iter, 'Iterator', explist
679   L1:
680     unless iter goto L2
681     $P0 = shift iter
682     rpost = tree.'get'('post', $P0)
683     ops.'push'(rpost)
684     $S1 = rpost.'result'()
685     push tmp, $S1
686     if iter goto L1
687     $I0 = rpost.'has_call_in_last_op'()
688     unless $I0 goto L1
689     $I1 = namelist
690     $I2 = explist
691     $I1 -= $I2
692     unless $I1 goto L1
693     $S0 = '(' . $S1
694     $P0 = rpost.'pop'()
695   L3:
696     unless $I1 > 0 goto L4
697     $S1 = ops.'unique'('$P')
698     rpost.'push_pirop'('new', $S1, '"LuaNil"')
699     push tmp, $S1
700     $S0 .= ', '
701     $S0 .= $S1
702     dec $I1
703     goto L3
704   L4:
705     $S0 .= ')'
706     $P0.'result'($S0)
707     rpost.'push'($P0)
708   L2:
709     .local pmc ass, lpost
710     $P0 = get_hll_global ['POST'], 'Ops'
711     ass = $P0.'new'('node'=>node)
712     new iter, 'Iterator', namelist
713   L5:
714     unless iter goto L6
715     $P0 = shift iter
716     unless tmp goto L7
717     $S1 = shift tmp
718     goto L8
719   L7:
720     $S1 = ops.'unique'('$P')
721     ops.'push_pirop'('new', $S1, '"LuaNil"')
722   L8:
723     lpost = tree.'get'('post', $P0)
724     $P0 = lpost.'pop'()
725     $P0.'push'($S1)
726     ops.'push'(lpost)
727     ass.'push'($P0)
728     goto L5
729   L6:
730     ops.'push'(ass)
731     .return (ops)
735 transform parenthese (PAST::Op) :language('PIR') {
736     .local pmc ops
737     $P0 = get_hll_global ['POST'], 'Ops'
738     ops = $P0.'new'('node'=>node)
739     .local pmc expr
740     $P0 = node[0]
741     expr = tree.'get'('post', $P0)
742     ops.'push'(expr)
743     ops.'result'(expr)
744     .return (ops)
748 transform cond (PAST::Val) :language('PIR') {
749     .return tree.'get'('post', node)
753 transform post (PAST::Val) :language('PIR') {
754     .local string type
755     type = node.'name'()
756     $I0 = index type, 'Lua'
757     if $I0 < 0 goto L1
758     .local pmc ops
759     $P0 = get_hll_global ['POST'], 'Ops'
760     ops = $P0.'new'('node'=>node)
761     .local string result
762     result = ops.'unique'('$P')
763     $S0 = ops.'escape'(type)
764     ops.'push_pirop'('new', result, $S0)
765     .local string value
766     value = node.'value'()
767     if value == '' goto L2
768     unless type == 'LuaString' goto L3
769     value = ops.'escape'(value)
770   L3:
771     ops.'push_pirop'('set', result, value)
772   L2:
773     ops.'result'(result)
774     .return (ops)
775   L1:
776     .return tree.'get'(type, node)
780 transform key (PAST::Val) :language('PIR') {
781     .local pmc subpost
782     subpost = get_hll_global ['Lua::POST'], '$?SUB'
783     .local pmc storage_const
784     storage_const = subpost.'storage_const'()
785     .local string name
786     name = node.'value'()
787     $I0 = exists storage_const[name]
788     if $I0 goto L1
789     .local pmc ops_const
790     ops_const = subpost.'ops_const'()
791     $S0 = 'k_' . name
792     $S1 = ops_const.'escape'(name)
793     $P0 = ops_const.'push_pirop'('inline', $S0, $S1, 'inline'=>'    .const .LuaString %0 = %1')
794     storage_const[name] = $S0
795   L1:
796     .local pmc ops
797     $P0 = get_hll_global ['POST'], 'Ops'
798     ops = $P0.'new'('node'=>node)
799     $S0 = storage_const[name]
800     ops.'result'($S0)
801     .return (ops)
805 transform constructor (PAST::Val) :language('PIR') {
806     .local pmc ops
807     $P0 = get_hll_global ['POST'], 'Ops'
808     ops = $P0.'new'('node'=>node)
809     .local string table
810     table = ops.'unique'('$P')
811     ops.'push_pirop'('new', table, '"LuaTable"')
812     ops.'result'(table)
813     .local pmc iter, kpost, vpost
814     .local string key, result
815     .local int i
816     i = 1
817     iter = node.'iterator'()
818   L1:
819     unless iter goto L2
820     $P0 = shift iter
821     $I0 = does $P0, 'array'
822     if $I0 goto L3
823     $P2 = get_hll_global ['POST'], 'Ops'
824     kpost = $P2.'new'('node'=>node)
825     result = kpost.'unique'('$P')
826     kpost.'push_pirop'('new', result, '"LuaNumber"')
827     $S0 = i
828     inc i
829     kpost.'push_pirop'('set', result, $S0)
830     kpost.'result'(result)
831     vpost = tree.'get'('post', $P0)
832     if iter goto L4
833     $I0 = vpost.'has_call_in_last_op'()
834     unless $I0 goto L4
835     ops.'push'(kpost)
836     $P0 = vpost.'pop'()
837     vpost.'push'($P0)
838     $S0 = $P0.'result'()
839     $S1 = '(' . $S0
840     $S1 .= ' :slurpy)'
841     $P0.'result'($S1)
842     ops.'push'(vpost)
843     $S0 .= ' :flat'
844     $P1 = ops.'push_pirop'('call', 'tconstruct', table, kpost, $S0)
845     $P1.'result'($S1)
846     goto L2
847   L3:
848     $P1 = $P0[0]
849     kpost = tree.'get'('post', $P1)
850     $P1 = $P0[1]
851     vpost = tree.'get'('post', $P1)
852   L4:
853     ops.'push'(kpost)
854     ops.'push'(vpost)
855     key = clone table
856     key .= '['
857     $S0 = kpost.'result'()
858     key .= $S0
859     key .= ']'
860     ops.'push_pirop'('set', key, vpost)
861     goto L1
862   L2:
863     .return (ops)
867 transform cond (PAST::Var) :language('PIR') {
868     .return tree.'get'('post', node)
872 transform post (PAST::Var) :language('PIR') {
873     $S0 = node.'scope'()
874     .return tree.'get'($S0, node)
878 transform parameter (PAST::Var) :language('PIR') {
879     .local pmc subpost
880     subpost = get_hll_global ['Lua::POST'], '$?SUB'
881     .local pmc ops
882     $P0 = get_hll_global ['POST'], 'Ops'
883     ops = $P0.'new'('node'=>node)
884     .local string name
885     name = node.'name'()
886     $I0 = node.'slurpy'()
887     unless $I0 goto L1
888     subpost.'add_param'(name, 'slurpy'=>1)
889     .return (ops)
890   L1:
891     .local pmc storage_lex
892     storage_lex = subpost.'storage_lex'()
893     .local string pname
894     pname = 'param_' . name
895     subpost.'add_param'(pname, 'optional'=>1)
896     $S0 = ops.'escape'(name)
897     ops.'push_pirop'('.lex', $S0, pname)
898     .local string vivilabel
899     vivilabel = ops.'unique'('vivify_')
900     ops.'push_pirop'('unless_null', pname, vivilabel)
901     ops.'push_pirop'('new', pname, '"LuaNil"')
902     ops.'push_new'('POST::Label', 'result'=>vivilabel)
903     ops.'result'(pname)
904     storage_lex[name] = pname
905     .return (ops)
909 transform lexical (PAST::Var) :language('PIR') {
910     .local pmc subpost
911     subpost = get_hll_global ['Lua::POST'], '$?SUB'
912     .local pmc storage_lex
913     storage_lex = subpost.'storage_lex'()
914     .local pmc ops
915     $P0 = get_hll_global ['POST'], 'Ops'
916     ops = $P0.'new'('node'=>node)
917     .local string name, lname
918     name = node.'name'()
919     lname = ops.'escape'(name)
920     $I0 = node.'lvalue'()
921     if $I0 goto L1
922     $I0 = exists storage_lex[name]
923     if $I0 goto L2
924     .local string result
925     result = ops.'unique'('$P')
926     ops.'push_pirop'('find_lex', result, lname)
927     ops.'result'(result)
928     .return (ops)
929   L2:
930     $S0 = storage_lex[name]
931     ops.'result'($S0)
932     .return (ops)
933   L1:
934     $I0 = node.'isdecl'()
935     unless $I0 goto L3
936     $I0 = exists storage_lex[name]
937     if $I0 goto L3
938     .local string pname
939     pname = 'var_' . name
940     ops.'push_pirop'('.local pmc', pname)
941     ops.'push_pirop'('.lex', lname, pname, 'result'=>pname)
942     storage_lex[name] = pname
943   L3:
944     ops.'push_pirop'('store_lex', lname, 'node'=>node)
945     ops.'result'(lname)
946     .return (ops)
950 transform package (PAST::Var) :language('PIR') {
951     .local pmc ops
952     .local string result
953     $P0 = get_hll_global ['POST'], 'Ops'
954     ops = $P0.'new'('node'=>node)
955     .local pmc basepost, keypost
956     $S0 = node.'scope'()
957     unless $S0 == 'keyed' goto L1
958     $P0 = node[0]
959     basepost = tree.'get'('post', $P0)
960     ops.'push'(basepost)
961     $P0 = node[1]
962     keypost = tree.'get'('post', $P0)
963     ops.'push'(keypost)
964     goto L2
965   L1:
966     .local pmc subpost
967     subpost = get_hll_global ['Lua::POST'], '$?SUB'
968     basepost = get_hll_global ['Lua::POST'], '$?environ'
969     unless null basepost goto L3
970     .local pmc ops_subr
971     ops_subr = subpost.'ops_subr'()
972     $I0 = defined ops_subr
973     unless $I0 goto L4
974     ops_subr.'push_pirop'('inline', 'inline'=><<'PIRCODE')
975     .local pmc subr
976     subr = interpinfo .INTERPINFO_CURRENT_SUB
977 PIRCODE
978     new $P0, 'Undef'
979     subpost.'ops_subr'($P0)
980   L4:
981     result = ops.'unique'('$P')
982     basepost = ops.'push_pirop'('callmethod', 'getfenv', 'subr', 'result'=>result)
983     set_hll_global ['Lua::POST'], '$?environ', basepost
984   L3:
985     .local pmc storage_const
986     storage_const = subpost.'storage_const'()
987     .local string name
988     name = node.'name'()
989     $I0 = exists storage_const[name]
990     if $I0 goto L5
991     .local pmc ops_const
992     ops_const = subpost.'ops_const'()
993     $S0 = 'k_' . name
994     $S1 = ops_const.'escape'(name)
995     $P0 = ops_const.'push_pirop'('inline', $S0, $S1, 'inline'=>'    .const .LuaString %0 = %1')
996     storage_const[name] = $S0
997   L5:
998     $P0 = get_hll_global ['POST'], 'Ops'
999     keypost = $P0.'new'('node'=>node)
1000     $S0 = storage_const[name]
1001     keypost.'result'($S0)
1002   L2:
1003     .local string key
1004     key = basepost.'result'()
1005     key .= '['
1006     $S0 = keypost.'result'()
1007     key .= $S0
1008     key .= ']'
1009     ops.'result'(key)
1010     $I0 = node.'lvalue'()
1011     if $I0 goto L6
1012     result = ops.'unique'('$P')
1013     ops.'push_pirop'('set', result, key, 'result'=>result)
1014     ops.'result'(result)
1015     .return (ops)
1016   L6:
1017     ops.'push_pirop'('set', key, 'node'=>node)
1018     ops.'result'(key)
1019     .return (ops)
1023 transform keyed (PAST::Var) :language('PIR') {
1024     .return tree.'get'('package', node)
1028 =head1 AUTHORS
1030 Francois Perrad
1032 =cut