# New Ticket Created by  Stephen Weeks 
# Please include the string:  [perl #50492]
# in the subject line of all future correspondence about this issue. 
# <URL: http://rt.perl.org/rt3/Ticket/Display.html?id=50492 >


Add support for parameters to functions, as in:

HOW DO I dostuff YR bar AN YR baz
    VISIBLE bar
    VISIBLE baz
IF U SAY SO

Add support for calling functions with multiple parameters, as in:

dostuff "value for bar" AN "value for baz"

This patch does not add support for operators.
This patch does not add support for return a value from a function,
although it does handle return values from functions properly.

 config/makefiles/root.in    |    1 
 src/builtins/expr_parse.pir |   78 ++++++++++++++++++++++++++++++++++++++++++++
 src/parser/actions.pm       |   40 ++++++++++++----------
 src/parser/grammar.pg       |   10 +++--
 4 files changed, 109 insertions(+), 20 deletions(-)
Index: config/makefiles/root.in
===================================================================
--- config/makefiles/root.in    (revision 25454)
+++ config/makefiles/root.in    (working copy)
@@ -41,6 +41,7 @@
 
 BUILTINS_PIR = \
   src/builtins/say.pir \
+  src/builtins/expr_parse.pir \
   src/builtins/var_or_function.pir
 
 # PMCS = lolcode
Index: src/builtins/expr_parse.pir
===================================================================
--- src/builtins/expr_parse.pir (revision 0)
+++ src/builtins/expr_parse.pir (revision 0)
@@ -0,0 +1,78 @@
+=head1
+
+expr_parse.pir - parse an expression and dispatch function calls with their 
appropriate arguments.
+
+=cut
+
+.namespace
+
+.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'
+
+  it_loop:
+    unless t_iter goto it_done
+      .local pmc item
+      item = shift t_iter
+      $I0 = isa item, 'Sub'
+    unless $I0 goto has_val
+      $I1 = item.arity()
+      push sub_stack, item
+      unshift arity_stack, $I1
+      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
+      .local pmc sub_to_call
+      sub_to_call = pop sub_stack
+      $I1 = sub_to_call.arity()
+      .local pmc args_array
+      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
+      #$P2 = sub_to_call(args_array)
+      .begin_call
+      .arg args_array :flat
+      .call sub_to_call
+      .result $P2
+      .end_call
+      push val_stack, $P2
+      $I0 = arity_stack[0]
+      $I0 -= 1
+      arity_stack[0] = $I0
+      goto call_check
+    skip_call:
+    goto it_loop
+it_done:
+    .local pmc return_val 
+    return_val = pop val_stack
+    .return (return_val)
+.end
+# Local Variables:
+#   mode: pir
+#   fill-column: 100
+# End:
+# vim: expandtab shiftwidth=4:
+
Index: src/parser/actions.pm
===================================================================
--- src/parser/actions.pm       (revision 25454)
+++ src/parser/actions.pm       (working copy)
@@ -73,23 +73,29 @@
     my $block := $( $<block> );
     $block.blocktype('declaration');
 
+    my $arglist := PAST::Stmts.new( :node($<arglist>) );
     # if there are any parameters, get the PAST for each of them and
     # adjust the scope to parameter.
-    if $<parameters> {
-        my @params := $<parameters>[0]<identifier>;
-        for @params {
-            my $param := $($_);
-            $param.scope('parameter');
-            $block.push($param);
-        }
+    $block.arity(0);
+    for $<parameters> {
+        #my $param := $($_);
+        #$param.scope('parameter');
+        my $param := PAST::Var.new(:name(~$_<identifier><name>), 
:scope('parameter'), :node($($_)));
+        $param.isdecl(1);
+        $arglist.push($param);
+        $block.arity($block.arity() + 1);
     }
 
+
     my $it := PAST::Var.new( :name( 'IT' ), :scope('lexical'), 
:viviself('Undef'), :isdecl(1));
-    $block.unshift($it);
+    $block[0].unshift($it);
 
     $it := PAST::Var.new( :name( 'IT' ), :scope('lexical'));
-    $block.push($it);
+    $block[0].push($it);
 
+    $block.unshift($arglist);
+
+    $block.name(~$<variable><identifier><name>);
     my $past := PAST::Op.new( :pasttype('bind'), :node( $/ ) );
     $($<variable>).isdecl(1);
     $past.push( $( $<variable> ) );
@@ -133,9 +139,11 @@
 
 method block($/) {
     my $past := PAST::Block.new( :blocktype('declaration'), :node( $/ ) );
+    my $stmts := PAST::Stmts.new( :node( $/ ) );
     for $<statement> {
-        $past.push( $( $_ ) );
+        $stmts.push( $( $_ ) );
     }
+    $past.push($stmts);
     make $past;
 }
 
@@ -143,14 +151,12 @@
     make $( $/{$key} );
 }
 
-method expression($/, $key) {
-    if ($key eq 'var_or_function') {
-        my $past := PAST::Op.new( :name('var_or_function'), :pasttype('call'), 
:node( $/ ) );
-        $past.push( $( $<variable> ) );
-        make $past;
-    } else {
-        make $( $/{$key} );
+method expression($/) {
+    my $past := PAST::Op.new( :name('expr_parse'), :pasttype('call'), :node( 
$/ ) );
+    for $<tokens> {
+        $past.push( $( $_ ) );
     }
+    make $past;
 }
 
 method integer($/) {
Index: src/parser/grammar.pg
===================================================================
--- src/parser/grammar.pg       (revision 25454)
+++ src/parser/grammar.pg       (working copy)
@@ -44,7 +44,7 @@
 }
 
 rule function {
-    'HOW' 'DUZ' 'I' <variable> <statement_terminator>
+    'HOW' 'DUZ' 'I' <variable> $<arglist>=['YR' $<parameters>=<variable>['AN' 
'YR' $<parameters>=<variable>]* ]?<statement_terminator>
     <block>
     'IF' 'U' 'SAY' 'SO'
     {*}
@@ -90,8 +90,12 @@
 }
 
 rule expression {
-    | <variable> {*}                             #= var_or_function
-    | <value> {*}                                #= value
+    [
+    | $<tokens>=<variable>
+    | $<tokens>=<value>
+    | 'AN'
+    | 'MKAY'
+    ]+ {*}
 }
 
 rule value {

Reply via email to