Permalink
Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
1133 lines (1058 sloc) 28.5 KB
# Copyright (C) 2007-2009, Parrot Foundation.
# $Id$
=head1 PAST to POST
=head2 Description
A grammar for transforming the abstract syntax tree (PAST)
into an opcode syntax tree (POST).
=cut
grammar Lua::POST::Grammar is TGE::Grammar;
transform post (PAST;Block) :language('PIR') {
null $P0
set_hll_global ['Lua';'POST'], '$?environ', $P0
.local pmc endlabels
endlabels = get_hll_global ['Lua';'POST'], '@endlabels'
new $P0, 'ResizableStringArray'
set_hll_global ['Lua';'POST'], '@endlabels', $P0
.local pmc outerpost
outerpost = get_hll_global ['Lua';'POST'], '$?SUB'
.local string name
$S0 = node.'name'()
unless $S0 == '' goto L1
$S0 = 'anon'
L1:
.local pmc post
$P0 = get_hll_global ['Lua';'POST'], 'Sub'
post = $P0.'new'('node'=>node, 'outer'=>outerpost, 'pirflags'=>':anon :lex', 'blocktype'=>'declaration')
$S1 = $S0 . '_'
name = post.'unique'($S1)
post.'name'(name)
new $P0, 'Hash'
post.'storage_lex'($P0)
new $P0, 'Hash'
post.'storage_const'($P0)
$P0 = get_hll_global ['POST'], 'Ops'
$P1 = $P0.'new'()
post.'push'($P1)
post.'ops_const'($P1)
$P1 = $P0.'new'()
post.'push'($P1)
post.'ops_subr'($P1)
set_hll_global ['Lua';'POST'], '$?SUB', post
.local pmc it, cpost
it = node.'iterator'()
L2:
unless it goto L3
$P0 = shift it
cpost = tree.'get'('post', $P0)
post.'push'(cpost)
goto L2
L3:
set_hll_global ['Lua';'POST'], '$?SUB', outerpost
set_hll_global ['Lua';'POST'], '@endlabels', endlabels
if null outerpost goto L4
.local pmc ops_subr
ops_subr = outerpost.'ops_subr'()
$I0 = defined ops_subr
unless $I0 goto L5
ops_subr.'push_pirop'('inline', 'inline'=><<'PIRCODE')
.local pmc subr
subr = interpinfo .INTERPINFO_CURRENT_SUB
PIRCODE
new $P0, 'Undef'
outerpost.'ops_subr'($P0)
L5:
.local pmc ops
$P0 = get_hll_global ['POST'], 'Ops'
ops = $P0.'new'('node'=>node)
ops.'push'(post)
$S0 = post.'unique'('fct_')
$S1 = post.'subid'()
ops.'push_pirop'('inline', $S0, $S1, 'inline'=>' .const "Sub" %0 = "%1"')
.local string result
result = ops.'unique'('$P')
ops.'push_pirop'('newclosure', result, $S0)
$S0 = ops.'unique'('$P')
ops.'push_pirop'('callmethod', '"getfenv"', 'subr', 'result'=>$S0)
ops.'push_pirop'('callmethod', '"setfenv"', result, $S0, 'result'=>'')
ops.'result'(result)
.return (ops)
L4:
.local pmc start
$P0 = get_hll_global ['Lua'; 'POST'], 'Sub'
start = $P0.'new'('name'=>'&start', 'pirflags'=>':anon :main')
start.'add_param'('args', 'optional'=>1)
$P0 = find_caller_lex '$?FILES'
if null $P0 goto L6
$S0 = start.'escape'($P0)
start.'push_pirop'('inline', $S0, 'inline'=>' .annotate "file", %0')
L6:
$S0 = post.'subid'()
start.'push_pirop'('inline', $S0, 'inline'=><<'PIRCODE')
# print "start\n"
load_language 'lua'
lua_openlibs()
.local pmc env
env = get_hll_global "_G"
.local pmc vararg
vararg = argstolua(env, args)
.const "Sub" main = "%0"
main."setfenv"(env)
($I0, $P0) = docall(main, vararg :flat)
unless $I0 goto L3
.local pmc stderr
stderr = getstderr
print stderr, "luap: "
print stderr, $P0
L3:
PIRCODE
post.'outer'(start)
.local pmc onload
$P0 = get_hll_global ['Lua'; 'POST'], 'Sub'
onload = $P0.'new'('name'=>'&on_require', 'pirflags'=>':anon :load')
$P0 = find_caller_lex '$?FILES'
$S1 = mkfuncname($P0)
$S1 = onload.'escape'($S1)
onload.'push_pirop'('inline', $S0, $S1, 'inline'=><<'PIRCODE')
.const "Sub" entry = "%0"
set_hll_global %1, entry
PIRCODE
start.'push'(onload)
start.'push'(post)
$P0 = get_hll_global ['Lua'; 'POST'], 'Chunk'
.tailcall $P0.'new'(start, 'node'=>node, 'prologue'=><<'PIRCODE')
.include "interpinfo.pasm"
.HLL "lua"
.loadlib "io_ops"
.loadlib "lua_group"
PIRCODE
}
transform post (PAST;Stmts) :language('PIR') {
.local pmc ops
$P0 = get_hll_global ['POST'], 'Ops'
ops = $P0.'new'('node'=>node)
.local pmc it
it = node.'iterator'()
L1:
unless it goto L2
$P0 = shift it
$P1 = tree.'get'('void', $P0)
ops.'push'($P1)
goto L1
L2:
null $P0
set_hll_global ['Lua';'POST'], '$?environ', $P0
.return (ops)
}
transform void (PAST;Stmts) :language('PIR') {
.tailcall tree.'get'('post', node)
}
transform void (PAST;Op) :language('PIR') {
$S0 = node.'pasttype'()
.tailcall tree.'get'($S0, node)
}
transform cond (PAST;Op) :language('PIR') {
$S0 = node.'pirop'()
$I0 = index $S0, 'is'
unless $I0 >= 0 goto L1
.tailcall tree.'get'('cmp', node)
L1:
.tailcall tree.'get'('post', node)
}
transform post (PAST;Op) :language('PIR') {
$S0 = node.'pasttype'()
if $S0 == 'call' goto L1
if $S0 == 'callmethod' goto L1
.tailcall tree.'get'($S0, node)
L1:
.local pmc post
post = tree.'get'($S0, node)
$P0 = post.'pop'()
.local string result
result = post.'unique'('$P')
post.'push_pirop'('new', result, '"LuaNil"')
$P0.'result'(result)
post.'push'($P0)
post.'result'(result)
.return (post)
}
transform pirop (PAST;Op) :language('PIR') {
.local string result
$S0 = node.'pirop'()
$I0 = index $S0, 'is'
unless $I0 >= 0 goto L1
.local pmc post
post = tree.'get'('cmp', node)
$S0 = post.'result'()
result = post.'unique'('$P')
post.'push_pirop'('new', result, '"LuaBoolean"')
post.'push_pirop'('set', result, $S0)
post.'result'(result)
.return (post)
L1:
.local pmc ops
$P0 = get_hll_global ['POST'], 'Ops'
ops = $P0.'new'('node'=>node)
.local pmc arglist, it
new arglist, 'ResizableStringArray'
it = node.'iterator'()
L2:
unless it goto L3
.local pmc cpost
$P0 = shift it
cpost = tree.'get'('post', $P0)
ops.'push'(cpost)
$S1 = cpost.'result'()
push arglist, $S1
goto L2
L3:
result = ops.'unique'('$P')
post = ops.'push_pirop'($S0, result, arglist :flat, 'node'=>node, 'result'=>result)
ops.'result'(result)
.return (ops)
}
transform cmp (PAST;Op) :language('PIR') {
.local pmc ops
$P0 = get_hll_global ['POST'], 'Ops'
ops = $P0.'new'('node'=>node)
.local pmc expr1
$P0 = node[0]
expr1 = tree.'get'('post', $P0)
ops.'push'(expr1)
.local pmc expr2
$P0 = node[1]
expr2 = tree.'get'('post', $P0)
ops.'push'(expr2)
.local string pirop
pirop = node.'pirop'()
$S0 = ops.'unique'('$I')
ops.'push_pirop'(pirop, $S0, expr1, expr2, 'node'=>node)
ops.'result'($S0)
.return (ops)
}
transform call (PAST;Op) :language('PIR') {
.local pmc ops
$P0 = get_hll_global ['POST'], 'Ops'
ops = $P0.'new'('node'=>node)
.local pmc arglist, it, cpost
new arglist, 'ResizableStringArray'
it = node.'iterator'()
$P0 = shift it
$P1 = tree.'get'('post', $P0)
ops.'push'($P1)
$S0 = $P1.'result'()
push arglist, $S0
L1:
unless it goto L2
$P0 = shift it
cpost = tree.'get'('post', $P0)
ops.'push'(cpost)
$S0 = cpost.'result'()
if it goto L3
($I0, $P0) = cpost.'has_call_in_last_op'()
unless $I0 goto L3
$S1 = '(' . $S0
$S1 .= ' :slurpy)'
$P0.'result'($S1)
$S0 .= ' :flat'
L3:
push arglist, $S0
goto L1
L2:
ops.'push_pirop'('call', arglist :flat, 'node'=>node, 'result'=>'')
null $P0
set_hll_global ['Lua';'POST'], '$?environ', $P0
.return (ops)
}
transform callmethod (PAST;Op) :language('PIR') {
.local pmc ops
$P0 = get_hll_global ['POST'], 'Ops'
ops = $P0.'new'('node'=>node)
.local pmc arglist, it, obj, cpost
new arglist, 'ResizableStringArray'
it = node.'iterator'()
$P0 = shift it
obj = tree.'get'('post', $P0)
ops.'push'(obj)
$P0 = shift it
$P1 = tree.'get'('post', $P0)
ops.'push'($P1)
.local string key
key = obj.'result'()
key .= '['
$S0 = $P1.'result'()
key .= $S0
key .= ']'
$S0 = ops.'unique'('$P')
ops.'push_pirop'('set', $S0, key, 'result'=>$S0)
push arglist, $S0
$S0 = obj.'result'()
push arglist, $S0
L1:
unless it goto L2
$P0 = shift it
cpost = tree.'get'('post', $P0)
ops.'push'(cpost)
$S0 = cpost.'result'()
if it goto L3
($I0, $P0) = cpost.'has_call_in_last_op'()
unless $I0 goto L3
$S1 = '(' . $S0
$S1 .= ' :slurpy)'
$P0.'result'($S1)
$S0 .= ' :flat'
L3:
push arglist, $S0
goto L1
L2:
ops.'push_pirop'('call', arglist :flat, 'node'=>node, 'result'=>'')
null $P0
set_hll_global ['Lua';'POST'], '$?environ', $P0
.return (ops)
}
transform len (PAST;Op) :language('PIR') {
.local pmc ops
$P0 = get_hll_global ['POST'], 'Ops'
ops = $P0.'new'('node'=>node)
.local pmc expr
$P0 = node[0]
expr = tree.'get'('post', $P0)
ops.'push'(expr)
.local string result
result = ops.'unique'('$P')
$S0 = ops.'escape'('len')
ops.'push_pirop'('callmethod', $S0, expr, 'node'=>node, 'result'=>result)
ops.'result'(result)
.return (ops)
}
transform and (PAST;Op) :language('PIR') {
.local pmc ops
$P0 = get_hll_global ['POST'], 'Ops'
ops = $P0.'new'('node'=>node)
.local string type
type = node.'pasttype'()
.local pmc expr1
$P0 = node[0]
expr1 = tree.'get'('post', $P0)
ops.'push'(expr1)
.local string label, endlabel
$S1 = type . '_'
label = ops.'unique'($S1)
endlabel = label . '_end'
$S0 = ops.'unique'('$P')
unless type == 'and' goto L1
ops.'push_pirop'('if', expr1, label)
goto L2
L1:
ops.'push_pirop'('unless', expr1, label)
L2:
ops.'push_pirop'('clone', $S0, expr1)
ops.'push_pirop'('goto', endlabel)
$P1 = get_hll_global ['POST'], 'Label'
$P0 = $P1.'new'('result'=>label)
ops.'push'($P0)
.local pmc expr2
$P0 = node[1]
expr2 = tree.'get'('post', $P0)
ops.'push'(expr2)
ops.'push_pirop'('clone', $S0, expr2)
$P0 = $P1.'new'('result'=>endlabel)
ops.'push'($P0)
ops.'result'($S0)
null $P0
set_hll_global ['Lua';'POST'], '$?environ', $P0
.return (ops)
}
transform or (PAST;Op) :language('PIR') {
.tailcall tree.'get'('and', node)
}
transform vararg (PAST;Op) :language('PIR') {
.local pmc ops
$P0 = get_hll_global ['POST'], 'Ops'
ops = $P0.'new'('node'=>node)
.local string result
result = ops.'unique'('$P')
ops.'push_pirop'('new', result, '"LuaNil"')
ops.'push_pirop'('call', 'mkarg', 'vararg', 'result'=>result)
ops.'result'(result)
.return (ops)
}
transform if (PAST;Op) :language('PIR') {
.local pmc ops
$P0 = get_hll_global ['POST'], 'Ops'
ops = $P0.'new'('node'=>node)
.local string thenlabel, endlabel
thenlabel = ops.'unique'('if_')
endlabel = thenlabel . '_end'
.local pmc expr
$P0 = node[0]
expr = tree.'get'('cond', $P0)
ops.'push'(expr)
ops.'push_pirop'('if', expr, thenlabel)
.local pmc else
$P0 = node[2]
$I0 = defined $P0
if $I0 == 0 goto L1
else = tree.'get'('post', $P0)
ops.'push'(else)
L1:
ops.'push_pirop'('goto', endlabel)
$P1 = get_hll_global ['POST'], 'Label'
$P0 = $P1.'new'('result'=>thenlabel)
ops.'push'($P0)
.local pmc then
$P0 = node[1]
$I0 = defined $P0
if $I0 == 0 goto L2
then = tree.'get'('post', $P0)
ops.'push'(then)
L2:
$P0 = $P1.'new'('result'=>endlabel)
ops.'push'($P0)
.return (ops)
}
transform while (PAST;Op) :language('PIR') {
.local pmc endlabels
endlabels = get_hll_global ['Lua';'POST'], '@endlabels'
.local pmc ops
$P0 = get_hll_global ['POST'], 'Ops'
ops = $P0.'new'('node'=>node)
.local string looplabel, endlabel
looplabel = ops.'unique'('while_')
endlabel = looplabel . '_end'
unshift endlabels, endlabel
$P1 = get_hll_global ['POST'], 'Label'
$P0 = $P1.'new'('result'=>looplabel)
ops.'push'($P0)
.local pmc expr
$P0 = node[0]
expr = tree.'get'('cond', $P0)
ops.'push'(expr)
ops.'push_pirop'('unless', expr, endlabel)
.local pmc blk
$P0 = node[1]
blk = tree.'get'('post', $P0)
ops.'push'(blk)
ops.'push_pirop'('goto', looplabel)
$P0 = $P1.'new'('result'=>endlabel)
ops.'push'($P0)
$P0 = shift endlabels
.return (ops)
}
transform repeat (PAST;Op) :language('PIR') {
.local pmc endlabels
endlabels = get_hll_global ['Lua';'POST'], '@endlabels'
.local pmc ops
$P0 = get_hll_global ['POST'], 'Ops'
ops = $P0.'new'('node'=>node)
.local string looplabel, endlabel
looplabel = ops.'unique'('repeat_')
endlabel = looplabel . '_end'
unshift endlabels, endlabel
$P1 = get_hll_global ['POST'], 'Label'
$P0 = $P1.'new'('result'=>looplabel)
ops.'push'($P0)
.local pmc blk
$P0 = node[0]
blk = tree.'get'('post', $P0)
ops.'push'(blk)
.local pmc expr
$P0 = node[1]
expr = tree.'get'('cond', $P0)
ops.'push'(expr)
ops.'push_pirop'('if', expr, endlabel)
ops.'push_pirop'('goto', looplabel)
$P0 = $P1.'new'('result'=>endlabel)
ops.'push'($P0)
$P0 = shift endlabels
.return (ops)
}
transform fornum (PAST;Op) :language('PIR') {
.local pmc endlabels
endlabels = get_hll_global ['Lua';'POST'], '@endlabels'
.local pmc ops
$P0 = get_hll_global ['POST'], 'Ops'
ops = $P0.'new'('node'=>node)
.local pmc e_var, e_limit, e_step
$P0 = node[1]
$P1 = $P0[0]
e_var = tree.'get'('post', $P1)
ops.'push'(e_var)
$P1 = $P0[1]
e_limit = tree.'get'('post', $P1)
ops.'push'(e_limit)
$P1 = $P0[2]
e_step = tree.'get'('post', $P1)
ops.'push'(e_step)
.local string loc_v
$P0 = node[0]
$P0 = tree.'get'('post', $P0)
$P1 = $P0.'pop'()
ops.'push'($P0)
$P1 = $P0.'pop'()
$P0.'push'($P1)
loc_v = $P1.'result'()
.local string var, limit, step
var = ops.'unique'('$P')
limit = ops.'unique'('$P')
step = ops.'unique'('$P')
ops.'push_pirop'('inline', var, limit, step, e_var, e_limit, e_step, 'inline'=>' (%0, %1, %2) = checkforloop(%3, %4, %5)')
.local string incr
$S0 = ops.'unique'('$N')
ops.'push_pirop'('set', $S0, step)
incr = ops.'unique'('$I')
ops.'push_pirop'('isgt', incr, $S0, '0.0')
.local string looplabel, endlabel, orlabel, blklabel
looplabel = ops.'unique'('fornum_')
orlabel = looplabel . '_or'
blklabel = looplabel . '_blk'
endlabel = looplabel . '_end'
unshift endlabels, endlabel
$P1 = get_hll_global ['POST'], 'Label'
$P0 = $P1.'new'('result'=>looplabel)
ops.'push'($P0)
ops.'push_pirop'('unless', incr, orlabel)
ops.'push_pirop'('gt', var, limit, endlabel)
ops.'push_pirop'('goto', blklabel)
$P0 = $P1.'new'('result'=>orlabel)
ops.'push'($P0)
ops.'push_pirop'('lt', var, limit, endlabel)
$P0 = $P1.'new'('result'=>blklabel)
ops.'push'($P0)
ops.'push_pirop'('clone', loc_v, var)
.local pmc blk
$P0 = node[2]
blk = tree.'get'('post', $P0)
ops.'push'(blk)
ops.'push_pirop'('add', var, step)
ops.'push_pirop'('goto', looplabel)
$P0 = $P1.'new'('result'=>endlabel)
ops.'push'($P0)
$P0 = shift endlabels
.return (ops)
}
transform forlist (PAST;Op) :language('PIR') {
.local pmc endlabels
endlabels = get_hll_global ['Lua';'POST'], '@endlabels'
.local pmc ops
$P0 = get_hll_global ['POST'], 'Ops'
ops = $P0.'new'('node'=>node)
.local pmc explist, rpost
explist = node[1]
.local string func, state, var
.local pmc it
it = iter explist
$P0 = shift it
rpost = tree.'get'('post', $P0)
ops.'push'(rpost)
func = rpost.'result'()
if it goto L1
$I0 = rpost.'has_call_in_last_op'()
unless $I0 goto L1
$P0 = rpost.'pop'()
$S0 = '(' . func
state = rpost.'unique'('$P')
rpost.'push_pirop'('new', state, '"LuaNil"')
$S0 .= ', '
$S0 .= state
var = rpost.'unique'('$P')
rpost.'push_pirop'('new', var, '"LuaNil"')
$S0 .= ', '
$S0 .= var
$S0 .= ')'
$P0.'result'($S0)
rpost.'push'($P0)
L1:
unless it goto L4
$P0 = shift it
rpost = tree.'get'('post', $P0)
ops.'push'(rpost)
state = rpost.'result'()
if it goto L2
$I0 = rpost.'has_call_in_last_op'()
unless $I0 goto L2
$P0 = rpost.'pop'()
$S0 = '(' . state
var = rpost.'unique'('$P')
rpost.'push_pirop'('new', var, '"LuaNil"')
$S0 .= ', '
$S0 .= var
$S0 .= ')'
$P0.'result'($S0)
rpost.'push'($P0)
L2:
unless it goto L4
$P0 = shift it
rpost = tree.'get'('post', $P0)
ops.'push'(rpost)
var = rpost.'result'()
L3:
unless it goto L4
$P0 = shift it
rpost = tree.'get'('post', $P0)
ops.'push'(rpost)
goto L3
L4:
unless state == '' goto L5
var = ops.'unique'('$P')
ops.'push_pirop'('new', var, '"LuaNil"')
L5:
unless var == '' goto L6
var = ops.'unique'('$P')
ops.'push_pirop'('new', var, '"LuaNil"')
L6:
.local pmc namelist, lpost, tmp
namelist = node[0]
it = iter namelist
new tmp, 'ResizableStringArray'
L7:
unless it goto L8
$P0 = shift it
lpost = tree.'get'('post', $P0)
lpost.'pop'()
ops.'push'(lpost)
$P1 = lpost.'pop'()
lpost.'push'($P1)
$S1 = $P1.'result'()
push tmp, $S1
goto L7
L8:
.local string looplabel, endlabel
looplabel = ops.'unique'('forlist_')
endlabel = looplabel . '_end'
unshift endlabels, endlabel
$P1 = get_hll_global ['POST'], 'Label'
$P0 = $P1.'new'('result'=>looplabel)
ops.'push'($P0)
it = iter tmp
$S0 = '('
L9:
unless it goto L10
$S1 = shift it
ops.'push_pirop'('new', $S1, '"LuaNil"')
if $S0 == '(' goto L11
$S0 .= ', '
L11:
$S0 .= $S1
goto L9
L10:
$S0 .= ')'
ops.'push_pirop'('call', func, state, var, 'node'=>node, 'result'=>$S0)
$S0 = tmp[0]
ops.'push_pirop'('clone', var, $S0)
$S0 = ops.'unique'('$I')
ops.'push_pirop'('isa', $S0, var, '"LuaNil"')
ops.'push_pirop'('if', $S0, endlabel)
.local pmc blk
$P0 = node[2]
blk = tree.'get'('post', $P0)
ops.'push'(blk)
ops.'push_pirop'('goto', looplabel)
$P0 = $P1.'new'('result'=>endlabel)
ops.'push'($P0)
$P0 = shift endlabels
.return (ops)
}
transform return (PAST;Op) :language('PIR') {
.local pmc ops
$P0 = get_hll_global ['POST'], 'Ops'
ops = $P0.'new'('node'=>node)
.local pmc arglist
new arglist, 'ResizableStringArray'
.local pmc it, cpost
it = node.'iterator'()
L1:
unless it goto L2
$P0 = shift it
cpost = tree.'get'('post', $P0)
ops.'push'(cpost)
$S0 = cpost.'result'()
if it goto L3
($I0, $P0) = cpost.'has_call_in_last_op'()
unless $I0 goto L3
if arglist goto L4
$P0.'pirop'('tailcall')
.return (ops)
L4:
$S1 = '(' . $S0
$S1 .= ' :slurpy)'
$P0.'result'($S1)
$S0 .= ' :flat'
L3:
push arglist, $S0
goto L1
L2:
ops.'push_pirop'('return', arglist :flat)
.return (ops)
}
transform break (PAST;Op) :language('PIR') {
.local pmc endlabels
endlabels = get_hll_global ['Lua';'POST'], '@endlabels'
$S0 = endlabels[0]
$P0 = get_hll_global ['POST'], 'Op'
.tailcall $P0.'new'($S0, 'node'=>node, 'pirop'=>'goto')
}
transform assign (PAST;Op) :language('PIR') {
.local pmc ops
$P0 = get_hll_global ['POST'], 'Ops'
ops = $P0.'new'('node'=>node)
.local pmc rpost
$P0 = node[1]
rpost = tree.'get'('post', $P0)
.local string val
val = rpost.'result'()
ops.'push'(rpost)
.local pmc lpost
$P0 = node[0]
lpost = tree.'get'('post', $P0)
.local pmc ass
ass = lpost.'pop'()
ops.'push'(lpost)
ass.'push'(val)
ops.'push'(ass)
.return (ops)
}
transform assignlist (PAST;Op) :language('PIR') {
.local pmc ops
$P0 = get_hll_global ['POST'], 'Ops'
ops = $P0.'new'('node'=>node)
.local pmc namelist, explist
namelist = node[0]
explist = node[1]
.local pmc it, tmp, rpost
new tmp, 'ResizableStringArray'
it = iter explist
L1:
unless it goto L2
$P0 = shift it
rpost = tree.'get'('post', $P0)
ops.'push'(rpost)
$S1 = rpost.'result'()
$S2 = ops.'unique'('$P')
ops.'push_pirop'('clone', $S2, $S1)
push tmp, $S2
if it goto L1
$I0 = rpost.'has_call_in_last_op'()
unless $I0 goto L1
$I1 = namelist
$I2 = explist
$I1 -= $I2
unless $I1 goto L1
$S0 = '(' . $S1
$P0 = rpost.'pop'()
L3:
unless $I1 > 0 goto L4
$S1 = ops.'unique'('$P')
rpost.'push_pirop'('new', $S1, '"LuaNil"')
push tmp, $S1
$S0 .= ', '
$S0 .= $S1
dec $I1
goto L3
L4:
$S0 .= ')'
$P0.'result'($S0)
rpost.'push'($P0)
L2:
.local pmc ass, lpost
$P0 = get_hll_global ['POST'], 'Ops'
ass = $P0.'new'('node'=>node)
it = iter namelist
L5:
unless it goto L6
$P0 = shift it
unless tmp goto L7
$S1 = shift tmp
goto L8
L7:
$S1 = ops.'unique'('$P')
ops.'push_pirop'('new', $S1, '"LuaNil"')
L8:
lpost = tree.'get'('post', $P0)
$P0 = lpost.'pop'()
$P0.'push'($S1)
ops.'push'(lpost)
ass.'push'($P0)
goto L5
L6:
ops.'push'(ass)
.return (ops)
}
transform parenthese (PAST;Op) :language('PIR') {
.local pmc ops
$P0 = get_hll_global ['POST'], 'Ops'
ops = $P0.'new'('node'=>node)
.local pmc expr
$P0 = node[0]
expr = tree.'get'('post', $P0)
ops.'push'(expr)
ops.'result'(expr)
.return (ops)
}
transform cond (PAST;Val) :language('PIR') {
.tailcall tree.'get'('post', node)
}
transform post (PAST;Val) :language('PIR') {
.local string type
type = node.'name'()
$I0 = index type, 'Lua'
if $I0 < 0 goto L1
.local pmc ops
$P0 = get_hll_global ['POST'], 'Ops'
ops = $P0.'new'('node'=>node)
.local string result
result = ops.'unique'('$P')
$S0 = ops.'escape'(type)
ops.'push_pirop'('new', result, $S0)
.local string value
value = node.'value'()
if value == '' goto L2
unless type == 'LuaString' goto L3
value = ops.'escape'(value)
L3:
ops.'push_pirop'('set', result, value)
L2:
ops.'result'(result)
.return (ops)
L1:
.tailcall tree.'get'(type, node)
}
transform key (PAST;Val) :language('PIR') {
.local pmc subpost
subpost = get_hll_global ['Lua';'POST'], '$?SUB'
.local pmc storage_const
storage_const = subpost.'storage_const'()
.local string name
name = node.'value'()
$I0 = exists storage_const[name]
if $I0 goto L1
.local pmc ops_const
ops_const = subpost.'ops_const'()
$S0 = 'k_' . name
$S1 = ops_const.'escape'(name)
$P0 = ops_const.'push_pirop'('.local pmc', $S0)
$P0 = ops_const.'push_pirop'('box', $S0, $S1)
storage_const[name] = $S0
L1:
.local pmc ops
$P0 = get_hll_global ['POST'], 'Ops'
ops = $P0.'new'('node'=>node)
$S0 = storage_const[name]
ops.'result'($S0)
.return (ops)
}
transform constructor (PAST;Val) :language('PIR') {
.local pmc ops
$P0 = get_hll_global ['POST'], 'Ops'
ops = $P0.'new'('node'=>node)
.local string table
table = ops.'unique'('$P')
ops.'push_pirop'('new', table, '"LuaTable"')
ops.'result'(table)
.local pmc it, kpost, vpost
.local string key, result
.local int i
i = 1
it = node.'iterator'()
L1:
unless it goto L2
$P0 = shift it
$I0 = does $P0, 'array'
if $I0 goto L3
$P2 = get_hll_global ['POST'], 'Ops'
kpost = $P2.'new'('node'=>node)
result = kpost.'unique'('$P')
kpost.'push_pirop'('new', result, '"LuaNumber"')
$S0 = i
inc i
kpost.'push_pirop'('set', result, $S0)
kpost.'result'(result)
vpost = tree.'get'('post', $P0)
if it goto L4
$I0 = vpost.'has_call_in_last_op'()
unless $I0 goto L4
ops.'push'(kpost)
$P0 = vpost.'pop'()
vpost.'push'($P0)
$S0 = $P0.'result'()
$S1 = '(' . $S0
$S1 .= ' :slurpy)'
$P0.'result'($S1)
ops.'push'(vpost)
$S0 .= ' :flat'
$P1 = ops.'push_pirop'('call', 'tconstruct', table, kpost, $S0)
$P1.'result'($S1)
goto L2
L3:
$P1 = $P0[0]
kpost = tree.'get'('post', $P1)
$P1 = $P0[1]
vpost = tree.'get'('post', $P1)
L4:
ops.'push'(kpost)
ops.'push'(vpost)
key = clone table
key .= '['
$S0 = kpost.'result'()
key .= $S0
key .= ']'
ops.'push_pirop'('set', key, vpost)
goto L1
L2:
.return (ops)
}
transform cond (PAST;Var) :language('PIR') {
.tailcall tree.'get'('post', node)
}
transform post (PAST;Var) :language('PIR') {
$S0 = node.'scope'()
.tailcall tree.'get'($S0, node)
}
transform parameter (PAST;Var) :language('PIR') {
.local pmc subpost
subpost = get_hll_global ['Lua';'POST'], '$?SUB'
.local pmc ops
$P0 = get_hll_global ['POST'], 'Ops'
ops = $P0.'new'('node'=>node)
.local string name
name = node.'name'()
$I0 = node.'slurpy'()
unless $I0 goto L1
subpost.'add_param'(name, 'slurpy'=>1)
.return (ops)
L1:
.local pmc storage_lex
storage_lex = subpost.'storage_lex'()
.local string pname
pname = 'param_' . name
subpost.'add_param'(pname, 'optional'=>1)
$S0 = ops.'escape'(name)
ops.'push_pirop'('.lex', $S0, pname)
.local string vivilabel
vivilabel = ops.'unique'('vivify_')
$S0 = concat 'has_', pname
ops.'push_pirop'('if', $S0, vivilabel)
ops.'push_pirop'('new', pname, '"LuaNil"')
$P0 = get_hll_global ['POST'], 'Label'
$P0 = $P0.'new'('result'=>vivilabel)
ops.'push'($P0)
ops.'result'(pname)
storage_lex[name] = pname
.return (ops)
}
transform lexical (PAST;Var) :language('PIR') {
.local pmc subpost
subpost = get_hll_global ['Lua';'POST'], '$?SUB'
.local pmc storage_lex
storage_lex = subpost.'storage_lex'()
.local pmc ops
$P0 = get_hll_global ['POST'], 'Ops'
ops = $P0.'new'('node'=>node)
.local string name, lname
name = node.'name'()
lname = ops.'escape'(name)
$I0 = node.'lvalue'()
if $I0 goto L1
$I0 = exists storage_lex[name]
if $I0 goto L2
.local string result
result = ops.'unique'('$P')
ops.'push_pirop'('find_lex', result, lname)
ops.'result'(result)
.return (ops)
L2:
$S0 = storage_lex[name]
ops.'result'($S0)
.return (ops)
L1:
$I0 = node.'isdecl'()
unless $I0 goto L3
$I0 = exists storage_lex[name]
if $I0 goto L3
.local string pname
pname = 'var_' . name
ops.'push_pirop'('.local pmc', pname)
ops.'push_pirop'('.lex', lname, pname, 'result'=>pname)
storage_lex[name] = pname
ops.'push_pirop'('set', pname, 'node'=>node)
ops.'result'(pname)
.return (ops)
L3:
ops.'push_pirop'('store_lex', lname, 'node'=>node)
ops.'result'(lname)
.return (ops)
}
transform package (PAST;Var) :language('PIR') {
.local pmc ops
.local string result
$P0 = get_hll_global ['POST'], 'Ops'
ops = $P0.'new'('node'=>node)
.local pmc basepost, keypost
$S0 = node.'scope'()
unless $S0 == 'keyed' goto L1
$P0 = node[0]
basepost = tree.'get'('post', $P0)
ops.'push'(basepost)
$P0 = node[1]
keypost = tree.'get'('post', $P0)
ops.'push'(keypost)
goto L2
L1:
.local pmc subpost
subpost = get_hll_global ['Lua';'POST'], '$?SUB'
basepost = get_hll_global ['Lua';'POST'], '$?environ'
unless null basepost goto L3
.local pmc ops_subr
ops_subr = subpost.'ops_subr'()
$I0 = defined ops_subr
unless $I0 goto L4
ops_subr.'push_pirop'('inline', 'inline'=><<'PIRCODE')
.local pmc subr
subr = interpinfo .INTERPINFO_CURRENT_SUB
PIRCODE
new $P0, 'Undef'
subpost.'ops_subr'($P0)
L4:
result = ops.'unique'('$P')
basepost = ops.'push_pirop'('callmethod', '"getfenv"', 'subr', 'result'=>result)
set_hll_global ['Lua';'POST'], '$?environ', basepost
L3:
.local pmc storage_const
storage_const = subpost.'storage_const'()
.local string name
name = node.'name'()
$I0 = exists storage_const[name]
if $I0 goto L5
.local pmc ops_const
ops_const = subpost.'ops_const'()
$S0 = 'k_' . name
$S1 = ops_const.'escape'(name)
$P0 = ops_const.'push_pirop'('.local pmc', $S0)
$P0 = ops_const.'push_pirop'('box', $S0, $S1)
storage_const[name] = $S0
L5:
$P0 = get_hll_global ['POST'], 'Ops'
keypost = $P0.'new'('node'=>node)
$S0 = storage_const[name]
keypost.'result'($S0)
L2:
.local string key
key = basepost.'result'()
key .= '['
$S0 = keypost.'result'()
key .= $S0
key .= ']'
ops.'result'(key)
$I0 = node.'lvalue'()
if $I0 goto L6
result = ops.'unique'('$P')
ops.'push_pirop'('set', result, key, 'result'=>result)
ops.'result'(result)
.return (ops)
L6:
ops.'push_pirop'('set', key, 'node'=>node)
ops.'result'(key)
.return (ops)
}
transform keyed (PAST;Var) :language('PIR') {
.tailcall tree.'get'('package', node)
}