transform root (ROOT) :language('PIR') {
    .local pmc past, traplabel

    past = new 'PAST::Block'
    past.'init'('node'=>node)
    past.'push_new'('PAST::Op', 'pirop'=>'inline', 'inline'=> <<'END_INLINE')
        goto trap_end
      trap:
        get_results '(0,0)', $P0, $S0
        print $S0
        exit 1
      trap_end:
        push_eh trap
        # %r
END_INLINE
    .local pmc iter
    $P0 = node['statement']
    iter = new .Iterator, $P0
  iter_loop:
    unless iter goto iter_end
    .local pmc cnode, cpast
    cnode = shift iter
    cpast = tree.'get'('past', cnode, 'APL::Grammar::statement')
    if null cpast goto iter_loop
    past.'push'(cpast)
    goto iter_loop
  iter_end:
    $P0 = past.'push_new'('PAST::Op', 'pirop'=>'inline', 'inline'=> '    clear_eh # %r')
    .return (past)
}


transform past (APL::Grammar::statement) :language('PIR') {
    .local pmc cnode, cpast
    cnode = node['expression']
    cpast = tree.'get'('past', cnode, 'APL::Grammar::expression')
    $I0 = isa cpast, 'PAST::Op'
    if $I0 == 0 goto aplprint
    $S0 = cpast.'pasttype'()
    if $S0 == 'assign' goto end
  aplprint:
    cpast = cpast.'new'('PAST::Op', cpast, 'name'=>'aplprint')
  end:
    .return (cpast)
}


transform past (APL::Grammar::expression) :language('PIR') {
    $P0 = node['target']
    unless null $P0 goto assignment
    $P0 = node['dyadic_identifier']
    unless null $P0 goto dyadic
    $P0 = node['monadic_identifier']
    unless null $P0 goto monadic

  subexpression:
    .local pmc cnode
    cnode = node['subexpression']
    .return tree.'get'('past', cnode, 'APL::Grammar::subexpression')

  assignment:
    .local pmc tnode, tpast, enode, epast
    tnode = node['target']
    tpast = tree.'get'('past', tnode, 'APL::Grammar::target')
    enode = node['expression']
    epast = tree.'get'('past', enode, 'APL::Grammar::expression')
    .return tpast.'new'('PAST::Op', tpast, epast, 'node'=>node, 'pasttype'=>'assign')

  dyadic:
    .local pmc cpast0, cpast1, past
    .local string name
    name = node['dyadic_identifier';0]
    name = concat 'dyadic:', name
    $P0 = node['subexpression']
    cpast0 = tree.'get'('past', $P0, 'APL::Grammar::subexpression')
    $P1 = node['expression';0]
    cpast1 = tree.'get'('past', $P1, 'APL::Grammar::expression')
    past = cpast0.'new'('PAST::Op', cpast0, cpast1, 'node'=>node, 'name'=>name)
    goto check_inline

  monadic:
    .local pmc cpast0
    .local string name
    name = node['monadic_identifier']
    name = concat 'monadic:', name
    $P0 = node['expression']
    cpast0 = tree.'get'('past', $P0, 'APL::Grammar::expression')
    past = cpast0.'new'('PAST::Op', cpast0, 'node'=>node, 'name'=>name)

  check_inline:
    .local pmc itable, inlinepir
    itable = get_hll_global ['APL'], '%inlinetable'
    inlinepir = itable[name]
    if null inlinepir goto end
    past.'inline'(inlinepir)
    past.'pasttype'('inline')
    past.'returns'('.Float')
  end:
    .return (past)
}


transform past (APL::Grammar::subexpression) :language('PIR') {
    $P0 = node['simple_expression']
    .return tree.'get'('past', $P0, 'APL::Grammar::simple_expression')
}


transform past (APL::Grammar::simple_expression) :language('PIR') {
  expression:
    $P0 = node['expression']
    if null $P0 goto array_identifier
    .return tree.'get'('past', $P0, 'APL::Grammar::expression')

  array_identifier:
    $P0 = node['array_identifier']
    .return tree.'get'('past', $P0, 'APL::Grammar::array_identifier')
}


transform past (APL::Grammar::target) :language('PIR') {
    .local pmc cnode, cpast
    cnode = node['variable_identifier']
    cpast = tree.'get'('past', cnode, 'APL::Grammar::variable_identifier')
    cpast.'islvalue'(1)
    .return (cpast)
}


transform past (APL::Grammar::array_identifier) :language('PIR') {
  constant:
    $P0 = node['constant']
    if null $P0 goto variable_name
    .return tree.'get'('past', $P0, 'APL::Grammar::constant')

  variable_name:
    $P0 = node['variable_identifier']
    .return tree.'get'('past', $P0, 'APL::Grammar::variable_identifier')
}


transform past (APL::Grammar::variable_identifier) :language('PIR') {
    .local string name
    name = node
    .local pmc past
    past = new 'PAST::Var'
    past.'init'('node'=>node, 'name'=>name, 'viviself'=>'.Undef')
    .return (past)
}


transform past (APL::Grammar::constant) :language('PIR') {
  numeric_constant:
    $P0 = node['numeric_constant']
    if null $P0 goto char_single
    .return tree.'get'('past', $P0, 'APL::Grammar::numeric_constant')

  char_single:
    $P0 = node['character_constant_single']
    if null $P0 goto char_double
    .return tree.'get'('past', $P0, 'APL::Grammar::character_constant_single')

  char_double:
    $P0 = node['character_constant_double']
    .return tree.'get'('past', $P0, 'APL::Grammar::character_constant_double')
}


transform past (APL::Grammar::numeric_constant) :language('PIR') {
    .local pmc vlist
    vlist = node['decimal_representation']
    $I0 = elements vlist
    if $I0 > 1 goto vector
    $P0 = vlist[0]
    .return tree.'get'('past', $P0, 'APL::Grammar::decimal_representation')

  vector:
    .local pmc past
    past = new 'PAST::Op'
    past.'init'('node'=>node, 'name'=>'aplvector')
    .local pmc iter
    iter = new .Iterator, vlist
  iter_loop:
    unless iter goto iter_end
    .local pmc cnode, cpast
    cnode = shift iter
    cpast = tree.'get'('past', cnode, 'APL::Grammar::decimal_representation')
    if null cpast goto iter_loop
    past.'push'(cpast)
    goto iter_loop
  iter_end:
    .return (past)
}


transform past (APL::Grammar::decimal_representation) :language('PIR') {
    .local pmc value
    $S0 = node
    $I0 = index $S0, '.'
    if $I0 >= 0 goto have_float
    $I0 = index $S0, 'E'
    if $I0 >= 0 goto have_float
    concat $S0, '.'
  have_float:
    value = new .String
    value = $S0
    value.'replace'(unicode:"\u207b", '-')
    .local pmc past
    past = new 'PAST::Val'
    past.'init'('node'=>node, 'name'=>value, 'vtype'=>'.Float')
    .return (past)
}


transform past (APL::Grammar::character_constant_single) :language('PIR') {
    .local pmc value
    $S0 = node[0]
    value = new .String
    value = $S0
    value.'replace'("''", "'")
    .local pmc past
    past = new 'PAST::Val'
    past.'init'('node'=>node, 'name'=>value, 'vtype'=>'.String', 'ctype'=>'s~')
    past = past.'new'('PAST::Op', past, 'node'=>node, 'name'=>'aplstring')
    .return (past)
}

transform past (APL::Grammar::character_constant_double) :language('PIR') {
    .local pmc value
    $S0 = node[0]
    value = new .String
    value = $S0
    value.'replace'('""','"')
    .local pmc past
    past = new 'PAST::Val'
    past.'init'('node'=>node, 'name'=>value, 'vtype'=>'.String', 'ctype'=>'s~')
    past = past.'new'('PAST::Op', past, 'node'=>node, 'name'=>'aplstring')
    .return (past)
}
