Revision 29028 (by tene, 2008/07/03 18:25:25) [lolcode]
* Store params in $?BLOCK symtable.
* Store subs in $?BLOCK symtable.
* Start building a parse tree for expressions at compile time.
* Minor PCT typo fix.
=head1

expr_parse.pir - parse an expression and dispatch function calls with their appropriate arguments.

=cut

.namespace []

.sub 'setup_global_parsing_tokens' :init :load :anon
    $P0 = new 'String'
    $P0 = 'MKAY end of statement marker'
    store_global 'MKAY', $P0
.end

.sub 'expr_parse'
    .param pmc tokens :slurpy

    .local pmc t_iter
    t_iter = new 'Iterator', tokens

    .local pmc sub_stack
    .local pmc val_stack
    .local pmc arity_stack

    sub_stack = new 'ResizablePMCArray'
    val_stack = new 'ResizablePMCArray'
    arity_stack = new 'ResizableIntegerArray'

    .local pmc mkay
    mkay = find_name 'MKAY'
  it_loop:
    unless t_iter goto it_done
      .local pmc item
      .local pmc sub_to_call
      .local pmc args_array
      item = shift t_iter
      unless_null item, not_found
      item = new 'Undef'
    not_found:
      $I0 = isntsame item, mkay
    if $I0 goto check_type
      has_slurpy:
      sub_to_call = pop sub_stack
      $I0 = shift arity_stack
      args_array = new 'ResizablePMCArray'
      getting_varargs:
        $P1 = pop val_stack
        $I0 = issame $P1, mkay
        if $I0 goto call_the_sub
        unshift args_array, $P1
        goto getting_varargs
      got_varargs:
    check_type:
      $I0 = isa item, 'Sub'
    unless $I0 goto has_val
      $P0 = inspect item
      $I2 = $P0['pos_slurpy']
      unless $I2 goto no_slurpy
        push sub_stack, item
        unshift arity_stack, -1
        push val_stack, mkay
      goto end_fixed
      no_slurpy:
        $I1 = item.arity()
        push sub_stack, item
        unshift arity_stack, $I1
      end_fixed:
      goto skip_val
    has_val:
      push val_stack, item
      $I0 = arity_stack[0]
      $I0 -= 1
      arity_stack[0] = $I0
    skip_val:
    call_check:
      $I0 = arity_stack[0]
      unless $I0 == 0 goto skip_call
      sub_to_call = pop sub_stack
      $I1 = sub_to_call.arity()
      args_array = new 'ResizablePMCArray'
    args_loop:
      if $I1 == 0 goto args_loop_end
      $I1 -= 1
      $P1 = pop val_stack
      unshift args_array, $P1
      goto args_loop
    args_loop_end:
      $I2 = shift arity_stack
      call_the_sub:
      $P2 = sub_to_call(args_array :flat)
      push val_stack, $P2
      $I0 = arity_stack[0]
      $I0 -= 1
      arity_stack[0] = $I0
      goto call_check
    skip_call:
    goto it_loop
it_done:
    $I0 = elements sub_stack
    if $I0 == 0 goto no_leftover_function
    sub_to_call = pop sub_stack
    args_array = new 'ResizablePMCArray'
    $P2 = new 'Iterator', val_stack
    getting_more_varargs:
      $I1 = elements val_stack
      unless $I1 goto got_more_varargs
      $P1 = pop val_stack
      $I0 = issame $P1, mkay
      if $I0 goto got_more_varargs
      unshift args_array, $P1
      goto getting_more_varargs
    got_more_varargs:
    $P0 = sub_to_call(args_array :flat)
    push val_stack, $P0
    no_leftover_function:
    .local pmc return_val
    return_val = pop val_stack
    .return (return_val)
.end

.sub lookup
    .param string name
    $P0 = find_name name
    if_null $P0, null_token
    $P0 = typeof $P0
    .return($P0)
  null_token:
    .return("NULL")
.end
# Local Variables:
#   mode: pir
#   fill-column: 100
# End:
# vim: expandtab shiftwidth=4 ft=pir: