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