# Copyright (C) 2006-2008, The Perl Foundation.
# $Id: /mirror/trunk/languages/lua/src/PASTGrammar.tg 34462 2008-12-27T17:23:27.572097Z fperrad  $

=head1 NAME

PASTGrammar.tg - A grammar for transforming the output of a PGE parse
into an abstract syntax tree (PAST).

=head1 DESCRIPTION


=cut

grammar Lua::PAST::Grammar is TGE::Grammar;


transform past (ROOT) :language('PIR') {
    new $P0, 'Integer'
    set $P0, 0
    set_hll_global ['Lua';'PAST'], '$looplevel', $P0
    new $P0, 'Boolean'
    set $P0, 1
    set_hll_global ['Lua';'PAST'], '?vararg', $P0
    .local pmc symbtab
    symbtab = new ['Lua';'Symbtab']
    symbtab.'push_scope'()
    set_hll_global ['Lua';'PAST'], '$symbtab', symbtab
    .local pmc past
    $P0 = node['block']
    past = tree.'get'('past', $P0, 'Lua::Grammar::block')
    $I0 = symbtab
    if $I0 goto L1
    .local pmc arg
    $P0 = get_hll_global ['PAST'], 'Var'
    arg = $P0.'new'('node'=>node, 'name'=>'vararg', 'scope'=>'parameter', 'slurpy'=>1)
    $P0 = get_hll_global ['PAST'], 'Block'
    .tailcall $P0.'new'(arg, past, 'node'=>node, 'name'=>'&main')
  L1:
    $S1 = $I0
    $S0 = "symbol table (" . $S1
    $S0 .= ")"
    internal_error($S0)
}


transform past (Lua::Grammar::block) :language('PIR') {
    .local pmc past
    $P0 = get_hll_global ['PAST'], 'Stmts'
    past = $P0.'new'('node'=>node)
    $P0 = node['statement']
    if null $P0 goto L1
    .local pmc iter, cpast
    new iter, 'Iterator', $P0
  L2:
    unless iter goto L1
    $P0 = shift iter
    cpast = tree.'get'('past', $P0, 'Lua::Grammar::statement')
    past.'push'(cpast)
    goto L2
  L1:
    $P0 = node['last_statement']
    if null $P0 goto L3
    $P0 = shift $P0
    cpast = tree.'get'('past', $P0, 'Lua::Grammar::statement')
    past.'push'(cpast)
  L3:
    .local pmc symbtab
    symbtab = get_hll_global ['Lua';'PAST'], '$symbtab'
    symbtab.'pop_scope'()
    .return (past)
}


transform past (Lua::Grammar::statement) :language('PIR') {
    $S0 = node.'find_key'()
    $P0 = node[$S0]
    $S0 = concat 'Lua::Grammar::', $S0
    .tailcall tree.'get'('past', $P0, $S0)
}


transform past (Lua::Grammar::do_block) :language('PIR') {
    .local pmc symbtab
    symbtab = get_hll_global ['Lua';'PAST'], '$symbtab'
    symbtab.'push_scope'()
    $P0 = node['block']
    .tailcall tree.'get'('past', $P0, 'Lua::Grammar::block')
}


transform past (Lua::Grammar::if_stat) :language('PIR') {
    .local pmc expr
    $P0 = node['expression']
    expr = tree.'get'('past', $P0, 'Lua::Grammar::expression')
    .local pmc symbtab
    symbtab = get_hll_global ['Lua';'PAST'], '$symbtab'
    symbtab.'push_scope'()
    .local pmc past, cpast, blk
    $P0 = node['block']
    blk = tree.'get'('past', $P0, 'Lua::Grammar::block')
    $P0 = get_hll_global ['PAST'], 'Op'
    past = $P0.'new'(expr, blk, 'node'=>node, 'pasttype'=>'if')
    cpast = past
    $P0 = node['elseif_block']
    if null $P0 goto L1
    .local pmc iter
    new iter, 'Iterator', $P0
  L2:
    unless iter goto L1
    $P0 = shift iter
    $P1 = tree.'get'('past', $P0, 'Lua::Grammar::elseif_block')
    cpast.'push'($P1)
    cpast = $P1
    goto L2
  L1:
    $P0 = node['else_block']
    if null $P0 goto L3
    symbtab.'push_scope'()
    $P0 = shift $P0
    $P0 = $P0['block']
    blk = tree.'get'('past', $P0, 'Lua::Grammar::block')
    cpast.'push'(blk)
  L3:
    .return (past)
}


transform past (Lua::Grammar::elseif_block) :language('PIR') {
    .local pmc expr
    $P0 = node['expression']
    expr = tree.'get'('past', $P0, 'Lua::Grammar::expression')
    .local pmc symbtab
    symbtab = get_hll_global ['Lua';'PAST'], '$symbtab'
    symbtab.'push_scope'()
    .local pmc blk
    $P0 = node['block']
    blk = tree.'get'('past', $P0, 'Lua::Grammar::block')
    $P0 = get_hll_global ['PAST'], 'Op'
    .tailcall $P0.'new'(expr, blk, 'node'=>node, 'pasttype'=>'if')
}


transform past (Lua::Grammar::while_stat) :language('PIR') {
    .local pmc looplevel
    looplevel = get_hll_global ['Lua';'PAST'], '$looplevel'
    inc looplevel
    .local pmc expr
    $P0 = node['expression']
    expr = tree.'get'('past', $P0, 'Lua::Grammar::expression')
    .local pmc symbtab
    symbtab = get_hll_global ['Lua';'PAST'], '$symbtab'
    symbtab.'push_scope'()
    .local pmc blk
    $P0 = node['block']
    blk = tree.'get'('past', $P0, 'Lua::Grammar::block')
    dec looplevel
    $P0 = get_hll_global ['PAST'], 'Op'
    .tailcall $P0.'new'(expr, blk, 'node'=>node, 'pasttype'=>'while')
}


transform past (Lua::Grammar::repeat_stat) :language('PIR') {
    .local pmc looplevel
    looplevel = get_hll_global ['Lua';'PAST'], '$looplevel'
    inc looplevel
    .local pmc symbtab
    symbtab = get_hll_global ['Lua';'PAST'], '$symbtab'
    symbtab.'push_scope'()
    .local pmc blk
    $P0 = node['block']
    blk = tree.'get'('past', $P0, 'Lua::Grammar::block')
    .local pmc expr
    $P0 = node['expression']
    expr = tree.'get'('past', $P0, 'Lua::Grammar::expression')
    dec looplevel
    $P0 = get_hll_global ['PAST'], 'Op'
    .tailcall $P0.'new'(blk, expr, 'node'=>node, 'pasttype'=>'repeat')
}


transform past (Lua::Grammar::for_stat) :language('PIR') {
    .local pmc looplevel
    looplevel = get_hll_global ['Lua';'PAST'], '$looplevel'
    inc looplevel
    .local pmc past
    $S0 = node.'find_key'()
    $P0 = node[$S0]
    $S1 = concat 'Lua::Grammar::', $S0
    past = tree.'get'('past', $P0, $S1)
    .local pmc blk
    $P0 = node['for_body']
    $P0 = $P0['block']
    blk = tree.'get'('past', $P0, 'Lua::Grammar::block')
    dec looplevel
    past.'push'(blk)
    .return (past)
}


transform past (Lua::Grammar::fornum) :language('PIR') {
    .local pmc symbtab
    symbtab = get_hll_global ['Lua';'PAST'], '$symbtab'
    symbtab.'push_scope'()
    $P0 = node['Name']
    $S0 = $P0.'result_object'()
    .local pmc name
    $S1 = symbtab.'insert'($S0)
    $P0 = get_hll_global ['PAST'], 'Var'
    name = $P0.'new'('node'=>node, 'name'=>$S1, 'scope'=>'lexical', 'isdecl'=>1, 'lvalue'=>1)
    .local pmc explist
    new explist, 'ResizablePMCArray'
    $P0 = node['expression']
    $I0 = $P0
    .local pmc iter, expr
    new iter, 'Iterator', $P0
  L1:
    unless iter goto L2
    $P0 = shift iter
    expr = tree.'get'('past', $P0, 'Lua::Grammar::expression')
    push explist, expr
    goto L1
  L2:
    unless $I0 < 3 goto L3
    $P0 = get_hll_global ['PAST'], 'Val'
    expr = $P0.'new'('node'=>node, 'name'=>'LuaNumber', 'value'=>'1')
    push explist, expr
  L3:
    $P0 = get_hll_global ['PAST'], 'Op'
    .tailcall $P0.'new'(name, explist, 'node'=>node, 'pasttype'=>'fornum')
}


transform past (Lua::Grammar::forlist) :language('PIR') {
    .local pmc symbtab
    symbtab = get_hll_global ['Lua';'PAST'], '$symbtab'
    symbtab.'push_scope'()
    .local pmc namelist
    new namelist, 'ResizablePMCArray'
    $P0 = node['name_list']
    $P0 = $P0['Name']
    .local pmc iter, cpast
    new iter, 'Iterator', $P0
  L1:
    unless iter goto L2
    $P0 = shift iter
    $S0 = $P0.'result_object'()
    $S1 = symbtab.'insert'($S0)
    $P0 = get_hll_global ['PAST'], 'Var'
    cpast = $P0.'new'('node'=>node, 'name'=>$S1, 'scope'=>'lexical', 'isdecl'=>1, 'lvalue'=>1)
    push namelist, cpast
    goto L1
  L2:
    $P0 = node['expression_list']
    .local pmc explist
    explist = tree.'get'('explist', $P0, 'Lua::Grammar::expression_list')
    $P0 = get_hll_global ['PAST'], 'Op'
    .tailcall $P0.'new'(namelist, explist, 'node'=>node, 'pasttype'=>'forlist')
}


transform past (Lua::Grammar::local_stat) :language('PIR') {
    $S0 = node.'find_key'()
    $P0 = node[$S0]
    $S0 = concat 'Lua::Grammar::', $S0
    .tailcall tree.'get'('past', $P0, $S0)
}


transform past (Lua::Grammar::local_declaration) :language('PIR') {
    .local pmc symbtab
    symbtab = get_hll_global ['Lua';'PAST'], '$symbtab'
    .local pmc explist
    $P0 = node['expression_list']
    if null $P0 goto L1
    $P0 = shift $P0
    explist = tree.'get'('explist', $P0, 'Lua::Grammar::expression_list')
  L1:
    unless null explist goto L2
    new explist, 'ResizablePMCArray'
  L2:
    $P0 = node['Name']
    .local pmc namelist
    new namelist, 'ResizablePMCArray'
    .local pmc iter, cpast
    new iter, 'Iterator', $P0
  L3:
    unless iter goto L4
    $P0 = shift iter
    $S0 = $P0.'result_object'()
    $S1 = symbtab.'insert'($S0)
    $P0 = get_hll_global ['PAST'], 'Var'
    cpast = $P0.'new'('node'=>node, 'name'=>$S1, 'scope'=>'lexical', 'isdecl'=>1, 'lvalue'=>1)
    push namelist, cpast
    goto L3
  L4:
    $P0 = get_hll_global ['PAST'], 'Op'
    .tailcall $P0.'new'(namelist, explist, 'node'=>node, 'pasttype'=>'assignlist')
}


transform past (Lua::Grammar::local_function) :language('PIR') {
    .local pmc symbtab
    symbtab = get_hll_global ['Lua';'PAST'], '$symbtab'
    .local pmc var
    $P0 = node['Name']
    $S0 = $P0.'result_object'()
    $S1 = symbtab.'insert'($S0)
    $P1 = get_hll_global ['PAST'], 'Var'
    var = $P1.'new'('node'=>$P0, 'name'=>$S1, 'scope'=>'lexical', 'isdecl'=>1, 'lvalue'=>1)
    .local pmc past
    $P0 = node['function_body']
    past = tree.'get'('past', $P0, 'Lua::Grammar::function_body')
    past.'name'($S0)
    $P0 = get_hll_global ['PAST'], 'Op'
    $P1 = $P0.'new'(var, past, 'node'=>node, 'pasttype'=>'assign')
    .return ($P1)
}


transform past (Lua::Grammar::return_statement) :language('PIR') {
    $P1 = get_hll_global ['PAST'], 'Op'
    $P0 = node['expression_list']
    if null $P0 goto L1
    .local pmc explist
    $P0 = shift $P0
    explist = tree.'get'('explist', $P0, 'Lua::Grammar::expression_list')
    .tailcall $P1.'new'(explist :flat, 'node'=>node, 'pasttype'=>'return')
  L1:
    .tailcall $P1.'new'('node'=>node, 'pasttype'=>'return')
}


transform past (Lua::Grammar::break_statement) :language('PIR') {
    .local pmc looplevel
    looplevel = get_hll_global ['Lua';'PAST'], '$looplevel'
    if looplevel <= 0 goto L1
    $P0 = get_hll_global ['PAST'], 'Op'
    .tailcall $P0.'new'('node'=>node, 'pasttype'=>'break')
  L1:
    node.'syntaxerror'("no loop to break")
}


transform past (Lua::Grammar::expression_stat) :language('PIR') {
    $P0 = node['assignment']
    unless null $P0 goto L1
    $P0 = node['primary_expression']
    .tailcall tree.'get'('past', $P0, 'Lua::Grammar::primary_expression')
  L1:
    .local pmc varlist, explist
    $P0 = shift $P0
    explist = tree.'get'('explist', $P0, 'Lua::Grammar::assignment')
    varlist = tree.'get'('varlist', $P0, 'Lua::Grammar::assignment')
    .local pmc expr
    $P0 = node['primary_expression']
    expr = tree.'get'('past', $P0, 'Lua::Grammar::primary_expression')
    expr.'lvalue'(1)
    unshift varlist, expr
    $P0 = get_hll_global ['PAST'], 'Op'
    .tailcall $P0.'new'(varlist, explist, 'node'=>node, 'pasttype'=>'assignlist')
}


transform varlist (Lua::Grammar::assignment) :language('PIR') {
    .local pmc varlist
    $P0 = node['expression_list']
    if null $P0 goto L1
    new varlist, 'ResizablePMCArray'
    .return (varlist)
  L1:
    $P0 = node['assignment']
    varlist = tree.'get'('varlist', $P0, 'Lua::Grammar::assignment')
    .local pmc expr
    $P0 = node['primary_expression']
    expr = tree.'get'('past', $P0, 'Lua::Grammar::primary_expression')
    expr.'lvalue'(1)
    unshift varlist, expr
    .return (varlist)
}


transform explist (Lua::Grammar::assignment) :language('PIR') {
    $P0 = node['expression_list']
    if null $P0 goto L1
    .tailcall tree.'get'('explist', $P0, 'Lua::Grammar::expression_list')
  L1:
    $P0 = node['assignment']
    .tailcall tree.'get'('explist', $P0, 'Lua::Grammar::assignment')
}


transform explist (Lua::Grammar::function_args) :language('PIR') {
    .local pmc explist, past
    $P0 = node['constructor']
    if null $P0 goto L1
    past = tree.'get'('past', $P0, 'Lua::Grammar::constructor')
    new explist, 'ResizablePMCArray'
    push explist, past
    .return (explist)
  L1:
    $P0 = node['string']
    if null $P0 goto L2
    past = tree.'get'('past', $P0, 'Lua::Grammar::string')
    new explist, 'ResizablePMCArray'
    push explist, past
    .return (explist)
  L2:
    $P0 = node['expression_list']
    unless null $P0 goto L3
    new explist, 'ResizablePMCArray'
    .return (explist)
  L3:
    $P0 = shift $P0
    .tailcall tree.'get'('explist', $P0, 'Lua::Grammar::expression_list')
}


transform past (Lua::Grammar::function_stat) :language('PIR') {
    .local pmc symbtab
    symbtab = get_hll_global ['Lua';'PAST'], '$symbtab'
    .local pmc past, var
    $P0 = node['functionname']
    var = tree.'get'('past', $P0, 'Lua::Grammar::functionname')
    $S0 = $P0.'result_object'()
    $I0 = index $S0, ':'
    if $I0 < 0 goto L1
    $P1 = get_hll_global ['PAST'], 'Var'
    $S1 = symbtab.'insert'('self')
    past = $P1.'new'('node'=>$P0, 'name'=>$S1, 'scope'=>'parameter')
    set_hll_global ['Lua';'PAST'], '$?self', past
  L1:
    $S0 = tree.'get'('Name', $P0, 'Lua::Grammar::functionname')
    $P0 = node['function_body']
    past = tree.'get'('past', $P0, 'Lua::Grammar::function_body')
    past.'name'($S0)
    $P0 = get_hll_global ['PAST'], 'Op'
    .tailcall $P0.'new'(var, past, 'node'=>node, 'pasttype'=>'assign')
}


transform Name (Lua::Grammar::functionname) :language('PIR') {
    .local string name
    name = ''
    $P0 = node['Name']
    .local pmc iter
    new iter, 'Iterator', $P0
  L2:
    unless iter goto L1
    if name == '' goto L3
    name = concat '.'
  L3:
    $P0 = shift iter
    $S0 = $P0.'result_object'()
    name = concat $S0
    goto L2
  L1:
    .return (name)
}


transform past (Lua::Grammar::functionname) :language('PIR') {
    .local pmc symbtab
    symbtab = get_hll_global ['Lua';'PAST'], '$symbtab'
    .local pmc iter
    $P0 = node['Name']
    new iter, 'Iterator', $P0
    $P0 = shift iter
    $S0 = $P0.'result_object'()
    .local pmc past
    $P0 = get_hll_global ['PAST'], 'Var'
    ($I0, $S1) = symbtab.'lookup'($S0)
    unless $I0 goto L1
    past = $P0.'new'('node'=>node, 'name'=>$S1, 'scope'=>'lexical')
    goto L2
  L1:
    past = $P0.'new'('node'=>node, 'name'=>$S0, 'scope'=>'package')
  L2:
    unless iter goto L3
    $P0 = shift iter
    $S0 = $P0.'result_object'()
    .local pmc key
    $P1 = get_hll_global ['PAST'], 'Val'
    key = $P1.'new'('node'=>$P0, 'name'=>'key', 'value'=>$S0)
    $P0 = get_hll_global ['PAST'], 'Var'
    past = $P0.'new'(past, key, 'node'=>node, 'scope'=>'keyed')
    goto L2
  L3:
    past.'lvalue'(1)
    .return (past)
}


transform past (Lua::Grammar::function_body) :language('PIR') {
    .local pmc symbtab
    symbtab = get_hll_global ['Lua';'PAST'], '$symbtab'
    symbtab.'push_scope'()
    .local pmc parlist
    new parlist, 'ResizablePMCArray'
    .local pmc var
    var = get_hll_global ['Lua';'PAST'], '$?self'
    if null var goto L1
    push parlist, var
    null var
    set_hll_global ['Lua';'PAST'], '$?self', var
  L1:
    $P0 = node['parameter_list']
    if null $P0 goto L2
    $P1 = $P0['name_list']
    if null $P1 goto L3
    $P1 = $P1['Name']
    .local pmc iter
    new iter, 'Iterator', $P1
  L4:
    unless iter goto L3
    $P1 = shift iter
    $S0 = $P1.'result_object'()
    $S1 = symbtab.'insert'($S0)
    $P2 = get_hll_global ['PAST'], 'Var'
    var = $P2.'new'('node'=>$P1, 'name'=>$S1, 'scope'=>'parameter')
    push parlist, var
    goto L4
  L3:
    $P1 = $P0['vararg']
    $I0 = 0
    if null $P1 goto L2
    $P1 = shift $P1
    $P2 = get_hll_global ['PAST'], 'Var'
    var = $P2.'new'('node'=>$P1, 'name'=>'vararg', 'scope'=>'parameter', 'slurpy'=>1)
    push parlist, var
    $I0 = 1
    goto L5
  L2:
    $P2 = get_hll_global ['PAST'], 'Var'
    var = $P2.'new'('node'=>$P0, 'name'=>'extra', 'scope'=>'parameter', 'slurpy'=>1)
    push parlist, var
  L5:
    .local pmc has_vararg
    has_vararg = get_hll_global ['Lua';'PAST'], '?vararg'
    new $P0, 'Boolean'
    set $P0, $I0
    set_hll_global ['Lua';'PAST'], '?vararg', $P0
    .local pmc looplevel
    looplevel = get_hll_global ['Lua';'PAST'], '$looplevel'
    new $P0, 'Integer'
    set $P0, 0
    set_hll_global ['Lua';'PAST'], '$looplevel', $P0
    .local pmc past
    $P0 = node['block']
    past = tree.'get'('past', $P0, 'Lua::Grammar::block')
    set_hll_global ['Lua';'PAST'], '$looplevel', looplevel
    set_hll_global ['Lua';'PAST'], '?vararg', has_vararg
    $P0 = get_hll_global ['PAST'], 'Block'
    .tailcall $P0.'new'(parlist :flat, past, 'node'=>node)
}


transform past (Lua::Grammar::constructor) :language('PIR') {
    .local pmc past
    $P0 = get_hll_global ['PAST'], 'Val'
    past = $P0.'new'('node'=>node, 'name'=>'constructor')
    $P0 = node['tablefieldlist']
    if null $P0 goto L1
    $P0 = shift $P0
    $P0 = $P0['tablefield']
    .local pmc iter, field
    $I0 = 1
    new iter, 'Iterator', $P0
  L2:
    unless iter goto L1
    $P0 = shift iter
    $S0 = $P0.'find_key'()
    $P0 = $P0[$S0]
    unless $S0 == 'expression' goto L3
    field = tree.'get'('past', $P0, 'Lua::Grammar::expression')
    past.'push'(field)
    goto L2
  L3:
    $S0 = concat 'Lua::Grammar::', $S0
    field = tree.'get'('record', $P0, $S0)
    past.'push'(field)
    goto L2
  L1:
    .return (past)
}


transform record (Lua::Grammar::record_field) :language('PIR') {
    .local pmc record
    new record, 'FixedPMCArray'
    set record, 2
    $S0 = node.'find_key'()
    $P0 = node[$S0]
    $S0 = concat 'Lua::Grammar::', $S0
    $P1 = tree.'get'('key', $P0, $S0)
    record[0] = $P1
    $P0 = node['expression']
    $P1 = tree.'get'('past', $P0, 'Lua::Grammar::expression')
    record[1] = $P1
    .return (record)
}


transform key (Lua::Grammar::Name) :language('PIR') {
    $S0 = node.'result_object'()
    $P0 = get_hll_global ['PAST'], 'Val'
    .tailcall $P0.'new'('node'=>node, 'name'=>'key', 'value'=>$S0)
}


transform key (Lua::Grammar::index) :language('PIR') {
    $P0 = node['expression']
    .tailcall tree.'get'('past', $P0, 'Lua::Grammar::expression')
}


transform explist (Lua::Grammar::expression_list) :language('PIR') {
    .local pmc explist
    new explist, 'ResizablePMCArray'
    $P0 = node['expression']
    .local pmc iter, expr
    new iter, 'Iterator', $P0
  L1:
    unless iter goto L2
    $P0 = shift iter
    expr = tree.'get'('past', $P0, 'Lua::Grammar::expression')
    push explist, expr
    goto L1
  L2:
    .return (explist)
}


transform past (Lua::Grammar::expression) :language('PIR') {
    $P0 = node['expr']
    .tailcall tree.'get'('past', $P0, 'Lua::Grammar::expr')
}


transform past (Lua::Grammar::expr) :language('PIR') {
    .local string type
    type = node['type']
    unless type == 'term:' goto L1
    $S0 = node.'find_key'()
    $P0 = node[$S0]
    $S0 = concat 'Lua::Grammar::', $S0
    .tailcall tree.'get'('past', $P0, $S0)
  L1:
    .local pmc optable, optok
    .local string pirop
    optable = get_hll_global [ 'Lua';'Grammar' ], '$optable'
    optok = optable[type]
    pirop = optok['pirop']
    .local pmc past
    $P0 = get_hll_global ['PAST'], 'Op'
    if pirop == '' goto L2
    past = $P0.'new'('node'=>node, 'name'=>type, 'pasttype'=>'pirop', 'pirop'=>pirop)
    goto L3
  L2:
    $S0 = optok['past']
    past = $P0.'new'('node'=>node, 'name'=>type, 'pasttype'=>$S0)
  L3:
    $P0 = node.'list'()
    .local pmc iter, expr
    new iter, 'Iterator', $P0
  L5:
    unless iter goto L4
    $P0 = shift iter
    expr = tree.'get'('past', $P0, 'Lua::Grammar::expr')
    past.'push'(expr)
    goto L5
  L4:
    .return (past)
}


transform past (Lua::Grammar::simple_expression) :language('PIR') {
    $S0 = node.'find_key'()
    $P0 = node[$S0]
    $S0 = concat 'Lua::Grammar::', $S0
    .tailcall tree.'get'('past', $P0, $S0)
}


transform past (Lua::Grammar::primary_expression) :language('PIR') {
    .local pmc past
    $P0 = node['prefix_expression']
    past = tree.'get'('past', $P0, 'Lua::Grammar::prefix_expression')
    $P0 = node['slice_expression']
    if null $P0 goto L1
    .local pmc iter, key, args
    new iter, 'Iterator', $P0
  L2:
    unless iter goto L1
    $P0 = shift iter
    $P1 = $P0['function_args']
    if null $P1 goto L3
    args = tree.'get'('explist', $P1, 'Lua::Grammar::function_args')
    $P1 = $P0['Name']
    if null $P1 goto L4
    .local pmc meth, obj
    key = tree.'get'('key', $P1, 'Lua::Grammar::Name')
    $P2 = get_hll_global ['PAST'], 'Var'
    meth = $P2.'new'(past, key, 'node'=>node, 'scope'=>'keyed')
    obj = clone past
    $P2 = get_hll_global ['PAST'], 'Op'
    past = $P2.'new'(meth, obj, args :flat, 'node'=>node, 'pasttype'=>'call')
    goto L2
  L4:
    $P2 = get_hll_global ['PAST'], 'Op'
    past = $P2.'new'(past, args :flat, 'node'=>node, 'pasttype'=>'call')
    goto L2
  L3:
    $P1 = $P0['Name']
    if null $P1 goto L5
    key = tree.'get'('key', $P1, 'Lua::Grammar::Name')
    $P2 = get_hll_global ['PAST'], 'Var'
    past = $P2.'new'(past, key, 'node'=>node, 'scope'=>'keyed')
    goto L2
  L5:
    $P1 = $P0['index']
    if null $P1 goto L6
    key = tree.'get'('key', $P1, 'Lua::Grammar::index')
    $P2 = get_hll_global ['PAST'], 'Var'
    past = $P2.'new'(past, key, 'node'=>node, 'scope'=>'keyed')
    goto L2
  L6:
    internal_error("primary expression")
  L1:
    .return (past)
}


transform past (Lua::Grammar::prefix_expression) :language('PIR') {
    $S0 = node.'find_key'()
    $P0 = node[$S0]
    $S0 = concat 'Lua::Grammar::', $S0
    .tailcall tree.'get'('past', $P0, $S0)
}


transform past (Lua::Grammar::parenthesed_expression) :language('PIR') {
    .local pmc past
    $P0 = node['expression']
    past = tree.'get'('past', $P0, 'Lua::Grammar::expression')
    $P0 = get_hll_global ['PAST'], 'Op'
    .tailcall $P0.'new'(past, 'node'=>node, 'pasttype'=>'parenthese')
}


transform past (Lua::Grammar::Name) :language('PIR') {
    .local pmc symbtab
    symbtab = get_hll_global ['Lua';'PAST'], '$symbtab'
    $P0 = get_hll_global ['PAST'], 'Var'
    $S0 = node.'result_object'()
    ($I0, $S1) = symbtab.'lookup'($S0)
    unless $I0 goto L1
    .tailcall $P0.'new'('node'=>node, 'name'=>$S1, 'scope'=>'lexical')
  L1:
    .tailcall $P0.'new'('node'=>node, 'name'=>$S0, 'scope'=>'package')
}


transform past (Lua::Grammar::vararg) :language('PIR') {
    .local pmc has_vararg
    has_vararg = get_hll_global ['Lua';'PAST'], '?vararg'
    unless has_vararg goto L1
    $P0 = get_hll_global ['PAST'], 'Op'
    .tailcall $P0.'new'('node'=>node, 'pasttype'=>'vararg')
  L1:
    node.'syntaxerror'("cannot use '...' outside a vararg function")
}


transform past (Lua::Grammar::nil) :language('PIR') {
    $P0 = get_hll_global ['PAST'], 'Val'
    .tailcall $P0.'new'('node'=>node, 'name'=>'LuaNil')
}


transform past (Lua::Grammar::true) :language('PIR') {
    $P0 = get_hll_global ['PAST'], 'Val'
    .tailcall $P0.'new'('node'=>node, 'name'=>'LuaBoolean', 'value'=>1)
}


transform past (Lua::Grammar::false) :language('PIR') {
    $P0 = get_hll_global ['PAST'], 'Val'
    .tailcall $P0.'new'('node'=>node, 'name'=>'LuaBoolean', 'value'=>0)
}


transform past (Lua::Grammar::number) :language('PIR') {
    $S0 = node.'result_object'()
    $P0 = get_hll_global ['PAST'], 'Val'
    .tailcall $P0.'new'('node'=>node, 'name'=>'LuaNumber', 'value'=>$S0)
}


transform past (Lua::Grammar::string) :language('PIR') {
    $S0 = node.'find_key'()
    $P0 = node[$S0]
    $S0 = $P0.'result_object'()
    $P0 = get_hll_global ['PAST'], 'Val'
    .tailcall $P0.'new'('node'=>node, 'name'=>'LuaString', 'value'=>$S0)
}

