Author: tene
Date: Fri Feb 22 05:54:43 2008
New Revision: 25988

Added:
   trunk/languages/lolcode/src/builtins/expr_parse.pir
   trunk/languages/lolcode/t/05-math.t
   trunk/languages/lolcode/t/99-four-fours.t
Modified:
   trunk/languages/lolcode/config/makefiles/root.in
   trunk/languages/lolcode/src/builtins/say.pir
   trunk/languages/lolcode/src/parser/actions.pm
   trunk/languages/lolcode/src/parser/grammar.pg

Log:
Lots of fixes for lolcode.
Properly handle dispatching arguments to functions at runtime.
Allow definition of functions with parameters.
Miscellenous cleanups.
Add math functions.


Modified: trunk/languages/lolcode/config/makefiles/root.in
==============================================================================
--- trunk/languages/lolcode/config/makefiles/root.in    (original)
+++ trunk/languages/lolcode/config/makefiles/root.in    Fri Feb 22 05:54:43 2008
@@ -41,6 +41,8 @@
 
 BUILTINS_PIR = \
   src/builtins/say.pir \
+  src/builtins/expr_parse.pir \
+  src/builtins/math.pir \
   src/builtins/var_or_function.pir
 
 # PMCS = lolcode

Added: trunk/languages/lolcode/src/builtins/expr_parse.pir
==============================================================================
--- (empty file)
+++ trunk/languages/lolcode/src/builtins/expr_parse.pir Fri Feb 22 05:54:43 2008
@@ -0,0 +1,122 @@
+=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
+      $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
+# Local Variables:
+#   mode: pir
+#   fill-column: 100
+# End:
+# vim: expandtab shiftwidth=4:
+

Modified: trunk/languages/lolcode/src/builtins/say.pir
==============================================================================
--- trunk/languages/lolcode/src/builtins/say.pir        (original)
+++ trunk/languages/lolcode/src/builtins/say.pir        Fri Feb 22 05:54:43 2008
@@ -10,13 +10,19 @@
 
 .sub 'VISIBLE'
     .param pmc args            :slurpy
-    .param int no_newline      :optional :named('no_newline')
+    .local int no_newline
+    no_newline = 0
     .local pmc iter
     iter = new 'Iterator', args
   iter_loop:
     unless iter goto iter_end
-    $P0 = shift iter
-    print $P0
+    $S0 = shift iter
+    $I0 = iseq $S0, '!'
+    if $I0 goto no_print
+    print $S0
+    goto iter_loop
+    no_print:
+    no_newline = 1
     goto iter_loop
   iter_end:
     if no_newline goto done

Modified: trunk/languages/lolcode/src/parser/actions.pm
==============================================================================
--- trunk/languages/lolcode/src/parser/actions.pm       (original)
+++ trunk/languages/lolcode/src/parser/actions.pm       Fri Feb 22 05:54:43 2008
@@ -26,7 +26,7 @@
 
 
 method statement ($/, $key) {
-    if ($key eq 'bare_expression') {
+    if (($key eq 'expression')&&($<expression><tokens>[0]<identifier> ne 
'VISIBLE')) {
         my $it := PAST::Var.new( :name( 'IT' ), :scope('lexical'), 
:viviself('Undef'));
         my $past := PAST::Op.new( :pasttype('bind'), :node( $/ ) );
         $past.push( $it );
@@ -38,17 +38,6 @@
 }
 
 
-method visible($/) {
-    my $past := PAST::Op.new( :name('VISIBLE'), :pasttype('call'), :node( $/ ) 
);
-    if ( $<no_newline> ) {
-        $past.push( PAST::Val.new( :value( 1 ), :named( PAST::Val.new( 
:value('no_newline') ) ) ) );
-    }
-    for $<expression> {
-        $past.push( $( $_ ) );
-    }
-    make $past;
-}
-
 method declare($/) {
     if ($<expression>) {
         $($<variable>).isdecl(1);
@@ -73,28 +62,35 @@
     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>), 
: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);
 
-    my $past := PAST::Op.new( :pasttype('bind'), :node( $/ ) );
-    $($<variable>).isdecl(1);
-    $past.push( $( $<variable> ) );
-    $past.push( $block );
-    make $past;
+    $block.unshift($arglist);
+
+    $block.name(~$<variable><identifier>);
+    make $block;
+    #my $past := PAST::Op.new( :pasttype('bind'), :node( $/ ) );
+    #$($<variable>).isdecl(1);
+    #$past.push( $( $<variable> ) );
+    #$past.push( $block );
+    #make $past;
 }
 
 method ifthen($/) {
@@ -133,9 +129,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 +141,26 @@
     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 bang($/) {
+    make PAST::Val.new( :value( ~$/ ), :returns('String'), :node($/) );
+}
+
+method expression($/) {
+    my $past := PAST::Op.new( :name('expr_parse'), :pasttype('call'), :node( 
$/ ) );
+    for $<tokens> {
+        if($_<identifier>) {
+            my $inline := '%r = find_name "' ~ $_<identifier> ~ '"';
+            $past.push(PAST::Op.new( :inline($inline) ));
+        }
+        elsif($_ eq "MKAY"){
+            my $inline := '%r = find_name "MKAY"';
+            $past.push(PAST::Op.new( :inline($inline) ));
+        }
+        else {
+            $past.push( $( $_ ) );
+        }
     }
+    make $past;
 }
 
 method integer($/) {
@@ -174,15 +184,11 @@
 }
 
 
-method identifier($/) {
-    make PAST::Val.new( :value( ~$/ ), :node($/) );
-}
-
 method variable ($/) {
-    if ($<identifier><name> eq 'IT') {
+    if ($<identifier> eq 'IT') {
         make PAST::Var.new( :name( 'IT' ), :scope('lexical'), 
:viviself('Undef'));
     } else {
-        make PAST::Var.new( :name( ~$<identifier><name> ),
+        make PAST::Var.new( :name( $<identifier> ),
                             :scope('lexical'),
                             :viviself('Undef'),
                             :node( $/ )

Modified: trunk/languages/lolcode/src/parser/grammar.pg
==============================================================================
--- trunk/languages/lolcode/src/parser/grammar.pg       (original)
+++ trunk/languages/lolcode/src/parser/grammar.pg       Fri Feb 22 05:54:43 2008
@@ -19,21 +19,15 @@
 token version { \d+ [ '.' \d+ ]? }
 
 rule statement {
-    | <visible>    {*}   #= visible
     | <declare>    {*}   #= declare
     | <assign>     {*}   #= assign
     | <function>   {*}   #= function
     | <ifthen>     {*}   #= ifthen
-    | <expression> {*}   #= bare_expression
+    | <expression> {*}   #= expression
 }
 
 token statement_terminator { [ ',' | \n+ | $ ] }
 
-rule visible {
-    'VISIBLE' <expression> [ <expression> ]* [$<no_newline>='!']?
-    {*}
-}
-
 rule declare {
     'I' 'HAS' 'A' <variable> [ 'ITZ' <expression> ]?
     {*}
@@ -44,7 +38,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,29 +84,40 @@
 }
 
 rule expression {
-    | <variable> {*}                             #= var_or_function
-    | <value> {*}                                #= value
+    [
+    | $<tokens>=<operator>
+    | $<tokens>=<variable>
+    | $<tokens>=<value>
+    | 'AN'
+    | $<tokens>='MKAY'
+    ]+ {*}
 }
 
-rule value {
+token value {
     | <float>    {*}                             #= float
     | <integer>  {*}                             #= integer
     | <boolean>  {*}                             #= boolean
     | <quote>    {*}                             #= quote
+    | <bang>     {*}                             #= bang
+}
+
+token bang {
+    '!' {*}
 }
 
-rule variable { <identifier> {*} }
+token operator { $<identifier>=(<.identifier> <.ws> 'OF') {*} }
+token variable { <identifier> {*} }
 
-token identifier { <!keyword> $<name>=( <[a..zA..Z]> \w* ) {*} }
+token identifier { <!keyword> <[a..zA..Z]> \w* }
 
 # RT #46213 : Because PGE doesn't yet know how to do longest token matching,
 # order all tokens in reverse alpha order to avoid a parsing bug.
 token keyword {
-    [ 'YR' | 'YA' | 'WTF?' | 'WIN' | 'WAI' | 'VISIBLE' | 'U' | 'SUM' | 'SO'
-    | 'SMALLR' | 'SAY' | 'RLY?' | 'RLY' | 'R' | 'QUOSHUNT' | 'PRODUKT'
-    | 'OMGWTF' | 'OMG' | 'OIC' | 'O' | 'NO' | 'MOD' | 'MEBBE' | 'KTHXBYE'
-    | 'ITZ' | 'IF' | 'I' | 'HOW' | 'HAS' | 'GTFO' | 'FOUND' | 'FAIL' | 'DIFF'
-    | 'BIGGR' | 'AN' | 'A' ] >>
+    [ 'YR' | 'YA' | 'WTF?' | 'WIN' | 'WAI' | 'U' | 'SO'
+    | 'SAY' | 'RLY?' | 'RLY' | 'R' 
+    | 'OMGWTF' | 'OMG' | 'OIC' | 'OF' | 'O' | 'NO' | 'MKAY' | 'MEBBE' | 
'KTHXBYE'
+    | 'ITZ' | 'IF' | 'I' | 'HOW' | 'HAS' | 'GTFO' | 'FOUND' | 'FAIL' 
+    | 'AN' | 'A' ] >>
 }
 
 token integer { '-'? \d+ {*} }

Added: trunk/languages/lolcode/t/05-math.t
==============================================================================
--- (empty file)
+++ trunk/languages/lolcode/t/05-math.t Fri Feb 22 05:54:43 2008
@@ -0,0 +1,38 @@
+HAI 1.2
+  VISIBLE "1..11"
+
+  BTW 1
+  VISIBLE "ok " SUM OF -2 AN 3
+
+  BTW 2
+  VISIBLE "ok " DIFF OF -1 AN -3
+
+  BTW 3
+  VISIBLE "ok " SUM OF 1 AN SUM OF 1 AN 1
+
+  BTW 4
+  VISIBLE "ok " PRODUKT OF 2 AN 2
+
+  BTW 5
+  VISIBLE "ok " QUOSHUNT OF 10 AN 2
+
+  BTW 6
+  VISIBLE "ok " MOD OF 27 AN 7
+
+  BTW 7
+  VISIBLE "ok " BIGGR OF 6 AN 7
+
+  BTW 8
+  VISIBLE "ok " SMALLR OF 8 AN 9
+
+  BTW 9
+  VISIBLE "ok " PRODUKT OF 4.5 AN 2
+
+  BTW 10
+  I HAS A CHEEZBURGER ITZ PRODUKT OF 5 AN 2
+  VISIBLE "ok " CHEEZBURGER
+
+  BTW 11
+  CHEEZBURGER R SUM OF CHEEZBURGER AN 1
+  VISIBLE "ok " CHEEZBURGER
+KTHXBYE

Added: trunk/languages/lolcode/t/99-four-fours.t
==============================================================================
--- (empty file)
+++ trunk/languages/lolcode/t/99-four-fours.t   Fri Feb 22 05:54:43 2008
@@ -0,0 +1,49 @@
+HAI 1.2
+  VISIBLE "1..20"
+
+  BTW 1
+  VISIBLE "ok " SUM OF QUOSHUNT OF 4 AN 4 AN DIFF OF 4 AN 4
+
+  BTW 2
+  VISIBLE "ok " SUM OF QUOSHUNT OF 4 AN 4 AN QUOSHUNT OF 4 AN 4
+
+  BTW 3
+  VISIBLE "ok " QUOSHUNT OF SUM OF SUM OF 4 AN 4 AN 4 AN 4
+
+  BTW 4
+  VISIBLE "ok " SUM OF PRODUKT OF DIFF OF 4 AN 4 AN 4 AN 4
+
+  BTW 5
+  VISIBLE "ok " QUOSHUNT OF SUM OF PRODUKT OF 4 AN 4 AN 4 AN 4
+
+  BTW 6
+  VISIBLE "ok " SUM OF QUOSHUNT OF SUM OF 4 AN 4 AN 4 AN 4
+  BTW 7
+  VISIBLE "ok " DIFF OF SUM OF 4 AN 4 AN QUOSHUNT OF 4 AN 4
+  BTW 8
+  VISIBLE "ok " DIFF OF SUM OF 4 AN 4.4 AN 0.4
+  BTW 9
+  VISIBLE "ok " SUM OF SUM OF 4 AN 4 AN QUOSHUNT OF 4 AN 4
+  BTW 10
+  VISIBLE "ok " QUOSHUNT OF DIFF OF 44 AN 4 AN 4
+  BTW 11
+  VISIBLE "ok " SUM OF QUOSHUNT OF 4 AN 0.4 AN QUOSHUNT OF 4 AN 4
+  BTW 12
+  VISIBLE "ok " QUOSHUNT OF SUM OF 44 AN 4 AN 4
+  BTW 13
+  VISIBLE "ok " DIFF OF FAKTORIAL OF 4 AN QUOSHUNT OF 44 AN 4
+  BTW 14
+  VISIBLE "ok " DIFF OF PRODUKT OF 4 AN DIFF OF 4 AN 0.4 AN 0.4
+  BTW 15
+  VISIBLE "ok " DIFF OF PRODUKT OF 4 AN 4 AN QUOSHUNT OF 4 AN 4
+  BTW 16
+  VISIBLE "ok " QUOSHUNT OF PRODUKT OF PRODUKT OF 4 AN 4 AN 4 AN 4
+  BTW 17
+  VISIBLE "ok " SUM OF PRODUKT OF 4 AN 4 AN QUOSHUNT OF 4 AN 4
+  BTW 18
+  VISIBLE "ok " SUM OF PRODUKT OF 44 AN 0.4 AN 0.4
+  BTW 19
+  VISIBLE "ok " DIFF OF DIFF OF FAKTORIAL OF 4 AN 4 AN QUOSHUNT OF 4 AN 4
+  BTW 20
+  VISIBLE "ok " PRODUKT OF 4 AN SUM OF QUOSHUNT OF 4 AN 4 AN 4
+KTHXBYE

Reply via email to