=head1 NAME

PIRGrammar -- A grammar for transforming an opcode syntax tree to PIR.

=head1 SYNOPSYS

  .sub _main :main
      load_bytecode 'PIRGrammar.pir'
      .local pmc grammar
       grammar = new 'PIRGrammar'

      # Build the PIR output
      .local pmc pirbuilder
      pirbuilder = grammar.apply(match)
      .local pmc pir
      pir = pirbuilder.get('result')

      end
  .end

=head1 DESCRIPTION


=cut

# This is just a stub to allow Punie to execute code. It will be
# replaced.
grammar PIRGrammar is TGE::Grammar;

transform result (ROOT) :language('PIR') {
    .local string output
    .local pmc iter
    iter = node.'child_iter'()
  iter_loop:
    unless iter, iter_end         # while (entries) ...
      shift $P2, iter
      $S3 = tree.get('result', $P2)
      output .= $S3
      goto iter_loop
  iter_end:
    .return (output)
}

transform result (POST::Sub) :language('PIR') {
    .local string output
    output = ".sub "
    $S1 = node.'name'()
    output .= $S1
    $S2 = node.'attribute'()
    unless $S2 goto no_attribute
      output .= " :"
      output .= $S2
  no_attribute:
    output .= "\n"

    .local pmc iter
    iter = node.'child_iter'()
  iter_loop:
    unless iter, iter_end         # while (entries) ...
      shift $P2, iter
      $S3 = tree.get('result', $P2)
      output .= $S3
      goto iter_loop
  iter_end:
    output .= ".end\n\n"
    .return (output)
}

# Flatten out the ops into a simple sequence.
transform result (POST::Ops) :language('PIR') {
    .local string output
    .local pmc iter
    iter = node.'child_iter'()
  iter_loop:
    unless iter, iter_end         # while (entries) ...
      shift $P2, iter
      $S3 = tree.get('result', $P2)
      output .= $S3
      goto iter_loop
  iter_end:
    .return (output)
}

transform result (POST::Op) :language('PIR') {
    .local string output
    .local int counter
    counter = 0
    .local string opname
    opname = node.op()
    output = "    " . opname
    output .= " "
    .local pmc iter
    iter = node.'child_iter'()
  iter_loop:
    unless iter goto iter_end         # while (entries) ...
      shift $P2, iter
      inc counter
      $S3 = tree.get('result', $P2)
      if counter <= 1 goto no_comma_out
      output .= ", "
    no_comma_out:
      output .= $S3
      goto iter_loop
  iter_end:
    output .= "\n"
    .return (output)
}

transform result (POST::Call) :language('PIR') {
    .local string output
    .local int counter
    counter = 0

    output = "    " # initial indentation
    .local pmc iter
    iter = node.'child_iter'()
    unless iter goto no_first         # first entry
      shift $P1, iter
      $S1 = tree.get('result', $P1)
      output .= $S1
      output .= " = "
  no_first:

    .local string subname
    subname = node.'name'()
    output .= "'"
    output .= subname
    output .= "'("
  iter_loop:
    unless iter goto iter_end         # while (entries) ...
      shift $P2, iter
      inc counter
      $S3 = tree.get('result', $P2)
      if counter <= 1 goto no_comma_out
      output .= ", "
    no_comma_out:
      output .= $S3
      goto iter_loop
  iter_end:
    output .= ")\n"
    .return (output)
}

transform result (POST::Var) :language('PIR') {
    $S1 = node.varname()
    .return ($S1)
}

transform result (POST::Label) :language('PIR') {
    $S1 = node.name()
    $I1 = node.dest()
    unless $I1 goto not_dest
       $S1 .= ":\n"
    not_dest:
    .return ($S1)
}

transform result (POST::Val) :language('PIR') {
    $S1 = node.value()
    $S2 = node.valtype()
    if $S2 == 'strq' goto wrap_string_single
    if $S2 == 'strqq' goto wrap_string_double
    # Otherwise, it's not a string value, so return it straight.
    .return ($S1)
  wrap_string_double:
    # Wrap double quoted strings in double quotes
    $S3 = '"' . $S1
    $S3 .= '"'
    .return ($S3)
  wrap_string_single:
    # Wrap single quoted strings in single quotes
    $S3 = "'" . $S1
    $S3 .= "'"
    .return ($S3)
}

=head1 LICENSE

Copyright (C) 2006, The Perl Foundation.

This is free software; you may redistribute it and/or modify
it under the same terms as Parrot.

=head1 AUTHOR

Allison Randal <allison@perl.org>

=cut
