# 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 {