Author: bernhard
Date: Wed Jan 31 13:30:57 2007
New Revision: 16856
Added:
trunk/languages/PIR/PROPOSALS
trunk/languages/PIR/examples/hllmap.pir
trunk/languages/PIR/t/branch.t
trunk/languages/PIR/t/call.t
trunk/languages/PIR/t/compunit.t
trunk/languages/PIR/t/sym.t
Modified:
trunk/MANIFEST
trunk/MANIFEST.SKIP
trunk/languages/PIR/lib/pasm.pg
trunk/languages/PIR/lib/pir.pg
trunk/languages/PIR/t/assign.t
trunk/languages/PIR/t/sub.t
trunk/languages/PIR/t/whitespace.t
Log:
fixes for language/PIR grammar on several points, amongst which are:
* support for .invocant + .meth_call
* support for .local decls before .result directives
* added assignment operators like +=
* minor other fixes
* added more tests
* added a PROPOSALS file, containing some ideas on
how to improve/clean up PIR grammar,
which might be interesting to discuss in the future.
Thanks to Klaas Jan Stol
Modified: trunk/MANIFEST
==============================================================================
--- trunk/MANIFEST (original)
+++ trunk/MANIFEST Wed Jan 31 13:30:57 2007
@@ -1,7 +1,7 @@
# ex: set ro:
# $Id$
#
-# generated by tools/dev/mk_manifest_and_skip.pl Wed Jan 31 20:18:40 2007 UT
+# generated by tools/dev/mk_manifest_and_skip.pl Wed Jan 31 20:29:02 2007 UT
#
# See tools/dev/install_files.pl for documentation on the
# format of this file.
Modified: trunk/MANIFEST.SKIP
==============================================================================
--- trunk/MANIFEST.SKIP (original)
+++ trunk/MANIFEST.SKIP Wed Jan 31 13:30:57 2007
@@ -1,6 +1,6 @@
# ex: set ro:
# $Id$
-# generated by tools/dev/mk_manifest_and_skip.pl Wed Jan 31 20:18:40 2007 UT
+# generated by tools/dev/mk_manifest_and_skip.pl Wed Jan 31 20:29:02 2007 UT
#
# This file should contain a transcript of the svn:ignore properties
# of the directories in the Parrot subversion repository. (Needed for
Added: trunk/languages/PIR/PROPOSALS
==============================================================================
--- (empty file)
+++ trunk/languages/PIR/PROPOSALS Wed Jan 31 13:30:57 2007
@@ -0,0 +1,224 @@
+PROPOSALS FOR PIR GRAMMAR
+-------------------------
+
+This document lists peculiarities of the current PIR implementation
+in IMCC while implementing it using PGE.
+IMHO, it'd be nice to clean up some of these before the 1.0 release
+of Parrot, in order to prevend 'backward compatibilty' features.
+
+Also, I propose some extensions to PIR, which may or may not
+be accepted. These new features are prefixed with "NEW:".
+The rationale for them is included. The proposals for the extensions
+have an ID starting at 100, so they can be listed together, separate
+from the clean-up proposals.
+
+This document is intended to start discussion of the listed
+features. That way, the grammar of PIR can be cleaned up and
+made more user-friendly.
+
+Please note that these are just *proposals*, not an attempt to
+extend PIR with non-features.
+
+
+
+1. ".emit/.eom" directives to put PASM instructions in PIR files.
+ Do we still need these? What use-case do they have? If any,
+ can't they use .sub <id> :anon :load or whatever?
+
+ Proposal: remove them.
+
+2. The optional comma between sub pragmas.
+ Sub definitions allow for pragmas after the sub id, like so:
+
+ .sub main :main :load :init
+ .end
+
+ However, the pragmas *may* be separated by a comma, like so:
+
+ .sub main :main, :load, :init
+ .end
+
+ Proposal: remove the optional comma from the grammar. Parameter
+ flags are not separated by commas neither, so it would look more
+ consistent. An optional comma is kinda strange; either demand it,
+ or not.
+
+3. PIR vs PASM registers
+
+ Since the new calling conventions/register allocation scheme (don't
+ know when exactly), subs have as many registers as they need; no
+ spilling is needed anymore (IIUC). Therefore, the difference between
+ PIR and PASM registers is not necessary anymore.
+
+ Proposal: stick to 1 category of registers, either PIR or PASM.
+ My preference is to stick with PIR registers, to make a difference
+ with .local's or .sym's (which may not start with a '$').
+
+
+4. Macro parameter list.
+
+ Macro definitions may have parameters. However, if they don't take
+ parameters, the parentheses are optional. So either of these examples
+ are allowed:
+
+ # 1
+ .macro doIt
+ .endm
+
+ # 2
+ .macro doIt()
+ .endm
+
+ Currently, IMCC differentiates between these 2: if the macro was
+ declared like #1, then it needs to be called *without* parentheses
+ (which is, arguably, consistent). However, if it's defined like #2,
+ then the empty parentheses are needed in the macro 'invocation' (i.e.
+ expansion).
+
+ Proposal: Always demand parentheses. This way, macro expansions always
+ have parentheses, even if there are no parameters. This looks more
+ uniform than having both forms in the PIR source code.
+
+
+5. .pcc_sub vs .sub
+
+ What's the difference? Are both directives needed? Are there clear
+ advantages to have both?
+
+ Proposal: remove '.pcc_sub', and stick to '.sub'
+
+6. Disallow .pcc_begin_yield + .pcc_end_return
+
+ Currently, IMCC allows:
+
+ .pcc_begin_yield
+ .return 1
+ .pcc_end_return
+
+ It would be more consistent to demand '.pcc_begin_yield' to match
'.pcc_end_yield'.
+
+7. Change #line into .line
+
+ IMHO, it would be nicer to have the #line directive spelled as
".line". This way,
+ it's more clear it's not a comment but rather a directive saying to
the assembler
+ which line is being parsed/assembled. It'd be more consistent with
respect to
+ other PIR directives ('.include' etc.). The current spelling seems
rather arbitrary.
+
+
+
+NEW FEATURE PROPOSALS GO HERE:
+
+
+100. NEW: Allow nested subs.
+
+ With the reimplementation of PIR in PGE it'd be *very* easy to allow
+ for nested subs. This would prevent the need for the :outer() flag,
+ and would make code generation for *many* languages targeting Parrot
+ much easier.
+
+ So, instead of:
+
+ sub foo {
+ sub bar {
+ }
+ }
+
+ to translate to:
+
+ .sub foo
+ .end
+
+ .sub bar :outer('foo')
+ .end
+
+ have it translate to:
+
+ .sub foo
+ .sub bar
+ .end
+ .end
+
+101. NEW: Allow for ".class" directive.
+
+ Sometimes, you just want to have some class defined in the HLL source
+ to be just there, when the code starts running. Currently, this can be
+ solved like:
+
+ .sub _create_classes :anon :load :init
+ $P0 = newclass "MyClass"
+ addattribute $P0, "x"
+ .end
+
+ .namespace ["MyClass"]
+
+ .sub sayHello :method
+ print "Hello"
+ .end
+
+ This feature is so common, why not have a .class/.end pair for this?
It would
+ make code generation for languages a bit easier, I think.
+
+ This would allow for writing:
+
+ .class MyClass
+ .attribute x
+
+ # .sub could be used to specify a "Class method" (i.e.
static method in Java)
+ # or, maybe, allow for ".method sayHello :static" or
":class" to
+ # indicate class methods. Or, just use the ".sub <id>
:method" syntax.
+ .method sayHello
+ print "Hello"
+ .end
+
+ .end
+
+ Of course, as classes may be nested in several namespaces, the
use of the .namespace
+ directive may still be needed, like:
+
+ .namespace ['PIR';'Grammar']
+
+ could become:
+
+ .namespace ['PIR']
+
+ .class Grammar
+ .end
+
+ This feature could easily be built "on top" of PIR, i.e. just
have it translated to the
+ current scheme. (using an anonymous :load/:init sub creating
the class).
+
+
+
+102. NEW: Allow for .try/.catch blocks
+
+ Instead of writing:
+
+ ...
+ push_eh on_error
+ # do some scary stuff
+ clear_eh
+ goto after_handler
+on_error:
+ # exception handling
+ .local pmc Exc
+ .get_results "()", Exc # get the exception object.
+after_handler:
+ ...
+
+ One could have the labels stuff generated by PIR:
+
+ .try # no need for some label, it's done for you!
+ # do some scary stuff
+ .catch Exc # some id for the exception object
+ # exception handling
+ .end
+
+ Not only is the programmer freed of handling the labels, it
+ just looks neater and cleaner!
+
+
+103. NEW: '.yield' instead of '.return' in '.pcc_begin_yield/.pcc_end_yield'
+
+ Currently, IMCC demands '.return' directives in a
.pcc_begin_yield/.pcc_end_yield
+ block. It might be more clear to introduce a '.yield'
directive, to make it
+ very clear that it's a yield, not a plain return.
\ No newline at end of file
Added: trunk/languages/PIR/examples/hllmap.pir
==============================================================================
--- (empty file)
+++ trunk/languages/PIR/examples/hllmap.pir Wed Jan 31 13:30:57 2007
@@ -0,0 +1,2 @@
+
+.HLL_map 22 , 22
Modified: trunk/languages/PIR/lib/pasm.pg
==============================================================================
--- trunk/languages/PIR/lib/pasm.pg (original)
+++ trunk/languages/PIR/lib/pasm.pg Wed Jan 31 13:30:57 2007
@@ -41,20 +41,20 @@
rule bitwise_op {
- band <var> \, <simple_expr> [ \, <simple_expr> ]?
- | bands <var> \, <simple_expr> [ \, <simple_expr> ]?
- | bnot <var> [ \, <simple_expr> ]?
- | n_bnot <var> \, <simple_expr>
- | bnots <var> [ \, <simple_expr> ]?
- | n_bnots <var> \, <simple_expr>
- | bor <var> \, <simple_expr> [ \, <simple_expr> ]?
- | bors <var> \, <simple_expr> [ \, <simple_expr> ]?
- | shl <var> \, <simple_expr> [ \, <simple_expr> ]?
- | shr <var> \, <simple_expr> [ \, <simple_expr> ]?
- | lsr <var> \, <simple_expr> [ \, <simple_expr> ]?
- | rot <var> \, <simple_expr> \, <simple_expr> \,
<simple_expr>
- | bxor <var> \, <simple_expr> [ \, <simple_expr> ]?
- | bxors <var> \, <simple_expr> [ \, <simple_expr> ]?
+ band <target> \, <simple_expr> [ \, <simple_expr> ]?
+ | bands <target> \, <simple_expr> [ \, <simple_expr> ]?
+ | bnot <target> [ \, <simple_expr> ]?
+ | n_bnot <target> \, <simple_expr>
+ | bnots <target> [ \, <simple_expr> ]?
+ | n_bnots <target> \, <simple_expr>
+ | bor <target> \, <simple_expr> [ \, <simple_expr> ]?
+ | bors <target> \, <simple_expr> [ \, <simple_expr> ]?
+ | shl <target> \, <simple_expr> [ \, <simple_expr> ]?
+ | shr <target> \, <simple_expr> [ \, <simple_expr> ]?
+ | lsr <target> \, <simple_expr> [ \, <simple_expr> ]?
+ | rot <target> \, <simple_expr> \, <simple_expr> \,
<simple_expr>
+ | bxor <target> \, <simple_expr> [ \, <simple_expr> ]?
+ | bxors <target> \, <simple_expr> [ \, <simple_expr> ]?
}
rule comparison_op {
@@ -82,16 +82,16 @@
| ge_str <arg_exp_exp_lab>
| ge_num <arg_exp_exp_lab>
| ge_addr <arg_exp_exp_lab>
- | if_null <var> \, <id>
- | unless_null <var> \, <id>
+ | if_null <target> \, <id>
+ | unless_null <target> \, <id>
| cmp <isXX_args>
| cmp_str <isXX_args>
| cmp_num <isXX_args>
| issame <isXX_args>
| isntsame <isXX_args>
- | istrue [ <int_reg> | <id> ] \, <var>
- | isfalse [ <int_reg> | <id> ] \, <var>
- | isnull [ <int_reg> | <id> ] \, <var>
+ | istrue [ <int_reg> | <id> ] \, <target>
+ | isfalse [ <int_reg> | <id> ] \, <target>
+ | isnull [ <int_reg> | <id> ] \, <target>
| isge <isXX_args>
| isgt <isXX_args>
| isle <isXX_args>
@@ -99,27 +99,27 @@
| iseq <isXX_args>
| isne <isXX_args>
| and [ <int_reg> | <id> ] \, <simple_expr> \, <simple_expr>
- | not <var> [ \, <var> ]?
- | n_not <var> \, <var>
+ | not <target> [ \, <target> ]?
+ | n_not <target> \, <target>
| or [ <int_reg> | <id> ] \,<simple_expr> \, <simple_expr>
| xor [ <int_reg> | <id> ] \, <simple_expr> \, <simple_expr>
}
rule debug_op {
debug_init
- | debug_load <var>
+ | debug_load <target>
| debug_break
| debug_print
| backtrace
- | getline <var>
- | getfile <var>
+ | getline <target>
+ | getfile <target>
}
rule loading_op {
clone
| exchange
- | set <var> \, <simple_expr>
+ | set <target> \, <simple_expr>
| assign <arg_hack> #
| setref <arg_hack> #
| deref <arg_hack> #
@@ -178,7 +178,7 @@
#
# define "argument" rules, so that not each instruction has to
# define it's specific number and types of args.
-# for instance: args_v_i_s for matching a <var> argument,
+# for instance: args_v_i_s for matching a <target> argument,
# <int_constant> argument and a <string_constant> argument
#
Modified: trunk/languages/PIR/lib/pir.pg
==============================================================================
--- trunk/languages/PIR/lib/pir.pg (original)
+++ trunk/languages/PIR/lib/pir.pg Wed Jan 31 13:30:57 2007
@@ -110,7 +110,7 @@
rule body {
<param_decl>*
- <pir_instr>*
+ <labeled_pir_instr>*
[ <'.end'> | <syntax_error: '.end' expected to close method/sub body> ]
}
@@ -132,20 +132,32 @@
#
-rule pir_instr {
+rule labeled_pir_instr {
[ <label> <instr>?
| <instr>
]
[ <?nl> | <syntax_error: newline expected after instruction> ]
}
+rule labeled_pasm_instr {
+ [ <label> <pasm_instr>?
+ | <pasm_instr>
+ ]
+ [ <?nl> | <syntax_error: newline expected after instruction> ]
+}
+
+rule instr {
+ [ <pir_instr> | <pasm_instr> ]
+
+}
+
# this is a token, because no spaces are allowed between
# the id and the colon.
token label {
<id> <':'>
}
-rule instr {
+rule pir_instr {
<local_decl>
| <lexical_decl>
| <const_def>
@@ -156,8 +168,7 @@
| <return_stat>
| <sub_invocation>
| <macro_invocation>
- | <jump_stat>
- | <pasm_instr>
+ | <jump_stat>
| <source_info>
}
@@ -193,7 +204,7 @@
<'.lex'>
[ <string_constant> | <syntax_error: string constant expected> ]
[ <','> | <syntax_error: ',' expected> ]
- [ <reg> | <syntax_error: register expected> ]
+ [ <target> | <syntax_error: register expected> ]
}
@@ -274,14 +285,29 @@
| <'>>>'>
| <'>>'>
| <'&&'>
- | <'!!'>
+ | <'||'>
| <'~~'>
- | <'!'>
+ | <'|'>
| <'&'>
| <'~'>
| <'.'>
}
+rule assign_operator {
+ <'+='>
+ | <'-='>
+ | <'/='>
+ | <'%='>
+ | <'*='>
+ | <'.='>
+ | <'&='>
+ | <'|='>
+ | <'~='>
+ | <'<<='>
+ | <'>>='>
+ | <'>>>='>
+}
+
rule unary_operator {
<'!'>
| <'-'>
@@ -290,7 +316,7 @@
rule expression {
- [ <simple_expr> [ <binary_operator> <simple_expression> ]? ]
+ [ <simple_expr> [ <binary_operator> <simple_expr> ]? ]
| [ <unary_operator> <simple_expr> ]
}
@@ -325,6 +351,7 @@
| <target> <'='> <'find_type'> [ <string_constant> | <string_reg> | <id> ]
| <target> <'='> <heredoc_string>
| <target> <'='> <'global'> <string_constant> # deprecated?
+ | <target> <assign_operator> <simple_expr>
| <target> <keylist> <'='> <simple_expr>
| <'global'> <string_constant> <'='> <target> # deprecated?
| <result_var_list> [ <'='> | <syntax_error: '=' expected> ] <short_sub_call>
@@ -399,16 +426,22 @@
<'.pcc_begin'>
[ <?nl> | <syntax_error: newline after '.pcc_begin' expected> ]
<arguments>
- [ <'.pcc_call'>
- | <'.nci_call'>
- | <syntax_error: '.pcc_call' or '.nci_call' expected>
+ [ [ <'.pcc_call'> | <'.nci_call'> ]
+ | [ <invocant> <'.meth_call'> ]
]
[ <target> | <syntax_error: id or register expected that holds the sub
object> ]
[ <?nl> | <syntax_error: newline after '.pcc_call sub' expected> ]
+ [ <local_decl> <?nl> ]*
<result_values>
[ <'.pcc_end'> | <syntax_error: '.pcc_end' expected> ]
}
+rule invocant {
+ <'.invocant'>
+ <target>
+ <?nl>
+}
+
rule short_sub_call {
[ <target>\. ]? # optional object
[ <target> | <string_constant> ] # method or sub name/id
@@ -562,7 +595,7 @@
rule emit {
<'.emit'>
[ <?nl> | <syntax_error: newline expected> ]
- <pir_instr>*
+ <labeled_pasm_instr>*
[ <'.eom'> | <syntax_error: '.eom' expected> ]
}
@@ -599,8 +632,8 @@
| <new_operators>
| <loadlib>
| <namespace>
- | <hll_specifier>
| <hll_mapping>
+ | <hll_specifier>
| <source_info>
}
@@ -618,9 +651,10 @@
rule namespace {
<'.namespace'>
- [ <'['> | <syntax_error: '[' expected> ]
- [ <namespace_id> | <syntax_error: namespace identifier expected> ]
- [ <']'> | <syntax_error: ']' expected> ]
+ [ <'['>
+ [ <namespace_id> | <syntax_error: namespace identifier expected> ]
+ [ <']'> | <syntax_error: ']' expected> ]
+ ]?
}
rule hll_specifier {
@@ -804,10 +838,12 @@
| <'.HLL'>
| <'.immediate'>
| <'.include'>
+ | <'.invocant'>
| <'.lex'>
| <'.line'>
| <'.loadlib'>
| <'.local'>
+ | <'.meth_call'>
| <'.namespace'>
| <'.nci_call'>
| <'.param'>
Modified: trunk/languages/PIR/t/assign.t
==============================================================================
--- trunk/languages/PIR/t/assign.t (original)
+++ trunk/languages/PIR/t/assign.t Wed Jan 31 13:30:57 2007
@@ -3,6 +3,93 @@
use strict;
use warnings;
use lib qw(t . lib ../lib ../../lib ../../../lib);
+use Parrot::Test tests => 5;
+use Test::More;
+
+language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'simple assignments' );
+.sub main
+ a = 1
+ b = 1.1
+ c = "hello"
+ d = e
+.end
+CODE
+"parse" => PMC 'PIRGrammar' { ... }
+Parse successful!
+OUT
+
+
+language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'get keyed assignments' );
+.sub main
+ e = x[1]
+ f = x[1.1]
+ g = x["hello"]
+ h = x[e]
+.end
+CODE
+"parse" => PMC 'PIRGrammar' { ... }
+Parse successful!
+OUT
+
+language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'set keyed assignments' );
+.sub main
+ x[1] = 1
+ x[1.1] = 2.222
+ x["hello"] = "hello"
+ x[e] = f
+.end
+CODE
+"parse" => PMC 'PIRGrammar' { ... }
+Parse successful!
+OUT
+
+language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'simple expressions' );
+.sub main
+ .local int x,y,z,a,b,c
+ x = 1 + 2
+ x = 1 * 2
+ y = 2 / 4
+ y = 2 - 4
+ z = 2 ** 4
+ z = 2 % 1
+ a = b & c
+ a = b && c
+ a = b | c
+ a = b || c
+ a = b << c
+ a = b >> c
+ a = b >>> c
+ a = - x
+ a = ! x
+ a = ~ x
+.end
+CODE
+"parse" => PMC 'PIRGrammar' { ... }
+Parse successful!
+OUT
+
+language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'assign operators' );
+.sub main
+ .local int x
+ x = 0
+ x += 1
+ x *= 5
+ x /= 2
+ x -= 1
+ x %= 2
+ x <<= 1
+ x >>= 1
+ x >>>= 1
+.end
+CODE
+"parse" => PMC 'PIRGrammar' { ... }
+Parse successful!
+OUT
+#!perl
+
+use strict;
+use warnings;
+use lib qw(t . lib ../lib ../../lib ../../../lib);
use Parrot::Test tests => 3;
use Test::More;
Added: trunk/languages/PIR/t/branch.t
==============================================================================
--- (empty file)
+++ trunk/languages/PIR/t/branch.t Wed Jan 31 13:30:57 2007
@@ -0,0 +1,64 @@
+#!perl
+
+use strict;
+use warnings;
+use lib qw(t . lib ../lib ../../lib ../../../lib);
+use Parrot::Test tests => 3;
+use Test::More;
+
+language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'if statement' );
+.sub main
+
+ if 1 < 2 goto L1
+L1:
+ if 2 > 3 goto L2
+L2:
+ if 1 <= 2 goto L3
+L3:
+ if 2 >= 2 goto L4
+L4:
+ if 3 == 3 goto L5
+L5:
+ if 3 != 4 goto L6
+L6:
+
+.end
+CODE
+"parse" => PMC 'PIRGrammar' { ... }
+Parse successful!
+OUT
+
+
+language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'unless statement' );
+.sub main
+
+ unless 1 < 2 goto L1
+L1:
+ unless 2 > 3 goto L2
+L2:
+ unless 1 <= 2 goto L3
+L3:
+ unless 2 >= 2 goto L4
+L4:
+ unless 3 == 3 goto L5
+L5:
+ unless 3 != 4 goto L6
+L6:
+
+.end
+CODE
+"parse" => PMC 'PIRGrammar' { ... }
+Parse successful!
+OUT
+
+language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'goto statement' );
+.sub main
+
+ goto L1
+L1:
+
+.end
+CODE
+"parse" => PMC 'PIRGrammar' { ... }
+Parse successful!
+OUT
Added: trunk/languages/PIR/t/call.t
==============================================================================
--- (empty file)
+++ trunk/languages/PIR/t/call.t Wed Jan 31 13:30:57 2007
@@ -0,0 +1,169 @@
+#!perl
+
+use strict;
+use warnings;
+use lib qw(t . lib ../lib ../../lib ../../../lib);
+use Parrot::Test tests => 9;
+use Test::More;
+
+language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'long sub invocation' );
+
+.sub main :main
+ .local int x, y, z
+ .pcc_begin
+ .arg 1
+ .arg 2
+ .arg 3
+ .pcc_call foo
+ .local int a, b, c
+ .result a
+ .result b
+ .result c
+ .pcc_end
+.end
+
+.sub foo
+ .pcc_begin_return
+ .return 4
+ .return 5
+ .return 6
+ .pcc_end_return
+.end
+
+CODE
+"parse" => PMC 'PIRGrammar' { ... }
+Parse successful!
+OUT
+
+language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'long sub invocation 2' );
+
+.sub main :main
+ .pcc_begin
+ .pcc_call foo
+ .pcc_end
+.end
+
+.sub foo
+ .pcc_begin_return
+ .pcc_end_return
+.end
+
+CODE
+"parse" => PMC 'PIRGrammar' { ... }
+Parse successful!
+OUT
+
+
+language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'short sub invocation' );
+
+.sub main :main
+ .local int x, y, z
+ (x, y, z) = foo(1, 2, 3)
+
+ foo(1,2,3)
+.end
+
+.sub foo
+ .return(4, 5, 6)
+.end
+
+CODE
+"parse" => PMC 'PIRGrammar' { ... }
+Parse successful!
+OUT
+
+language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'short yield' );
+
+.sub main :main
+ .yield(1,2,3)
+ .yield()
+.end
+
+
+CODE
+"parse" => PMC 'PIRGrammar' { ... }
+Parse successful!
+OUT
+
+language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'long yield' );
+
+.sub main :main
+ .pcc_begin_yield
+ .return 1
+ .return 2
+ .return 3
+ .pcc_end_yield
+.end
+
+CODE
+"parse" => PMC 'PIRGrammar' { ... }
+Parse successful!
+OUT
+
+
+language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'tail call' );
+
+.sub main :main
+ .return foo()
+.end
+
+.sub foo
+ .return bar()
+.end
+
+.sub bar
+ .return(1)
+.end
+
+CODE
+"parse" => PMC 'PIRGrammar' { ... }
+Parse successful!
+OUT
+
+language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'tail method call' );
+
+.sub main :main
+ .return obj.foo()
+.end
+
+.sub foo
+ .return obj.bar()
+.end
+
+.sub bar
+ .return(1)
+.end
+
+CODE
+"parse" => PMC 'PIRGrammar' { ... }
+Parse successful!
+OUT
+
+language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'nci call' );
+
+.sub main :main
+ .local pmc x
+ .pcc_begin
+ .nci_call x
+ .pcc_end
+.end
+
+CODE
+"parse" => PMC 'PIRGrammar' { ... }
+Parse successful!
+OUT
+
+language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'long method call' );
+
+.sub main :main
+ .local pmc x
+ .pcc_begin
+ .invocant obj
+ .meth_call meth
+ .pcc_end
+.end
+
+CODE
+"parse" => PMC 'PIRGrammar' { ... }
+Parse successful!
+OUT
Added: trunk/languages/PIR/t/compunit.t
==============================================================================
--- (empty file)
+++ trunk/languages/PIR/t/compunit.t Wed Jan 31 13:30:57 2007
@@ -0,0 +1,167 @@
+#!perl
+
+use strict;
+use warnings;
+use lib qw(t . lib ../lib ../../lib ../../../lib);
+use Parrot::Test tests => 15;
+use Test::More;
+
+language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'global defs' );
+
+.global g_X
+
+.global g_Y
+
+CODE
+"parse" => PMC 'PIRGrammar' { ... }
+Parse successful!
+OUT
+
+language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'const defs' );
+
+.const int iConst = 42
+
+.const num nConst = 3.14
+
+.const string sConst = "Hello World"
+
+.const pmc pConst = "is a PMC const a string?"
+
+CODE
+"parse" => PMC 'PIRGrammar' { ... }
+Parse successful!
+OUT
+
+language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'simple macro, no params' );
+
+.macro myMacro
+.endm
+
+CODE
+"parse" => PMC 'PIRGrammar' { ... }
+Parse successful!
+OUT
+
+language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'simple macro, params' );
+
+.macro doIt(A,B)
+.endm
+
+CODE
+"parse" => PMC 'PIRGrammar' { ... }
+Parse successful!
+OUT
+
+
+language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'include directive' );
+
+.include "Hitchhikers.pir"
+
+CODE
+"parse" => PMC 'PIRGrammar' { ... }
+Parse successful!
+OUT
+
+language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'loadlib directive' );
+
+.loadlib "Hitchhikers"
+
+CODE
+"parse" => PMC 'PIRGrammar' { ... }
+Parse successful!
+OUT
+
+language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'n_operators directive' );
+
+.pragma n_operators 1
+
+CODE
+"parse" => PMC 'PIRGrammar' { ... }
+Parse successful!
+OUT
+
+
+language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'namespaces 1' );
+
+.namespace ['']
+.namespace [""]
+
+CODE
+"parse" => PMC 'PIRGrammar' { ... }
+Parse successful!
+OUT
+
+
+language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'namespaces 2' );
+
+.namespace ['PIR']
+.namespace ["PIR"]
+
+CODE
+"parse" => PMC 'PIRGrammar' { ... }
+Parse successful!
+OUT
+
+
+language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'namespaces 3' );
+
+.namespace ['PIR';'Grammar']
+.namespace ["PIR";"Grammar"]
+
+CODE
+"parse" => PMC 'PIRGrammar' { ... }
+Parse successful!
+OUT
+
+language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'Root namespace' );
+
+.namespace
+
+CODE
+"parse" => PMC 'PIRGrammar' { ... }
+Parse successful!
+OUT
+
+language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'HLL' );
+
+.HLL 'PIR', 'PIRlib'
+.HLL "PIR", "PIRlib"
+
+CODE
+"parse" => PMC 'PIRGrammar' { ... }
+Parse successful!
+OUT
+
+language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'HLL map' );
+
+.HLL_map 42, 10
+
+CODE
+"parse" => PMC 'PIRGrammar' { ... }
+Parse successful!
+OUT
+
+language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'source line info' );
+
+.line 42
+
+.line 42, "Hitchhikers.pir"
+
+CODE
+"parse" => PMC 'PIRGrammar' { ... }
+Parse successful!
+OUT
+
+
+language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'emit' );
+
+.emit
+ set P0, 1
+.eom
+
+CODE
+"parse" => PMC 'PIRGrammar' { ... }
+Parse successful!
+OUT
+
+
Modified: trunk/languages/PIR/t/sub.t
==============================================================================
--- trunk/languages/PIR/t/sub.t (original)
+++ trunk/languages/PIR/t/sub.t Wed Jan 31 13:30:57 2007
@@ -3,7 +3,7 @@
use strict;
use warnings;
use lib qw(t . lib ../lib ../../lib ../../../lib);
-use Parrot::Test tests => 20;
+use Parrot::Test tests => 21;
use Test::More;
language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'basic sub' );
@@ -175,3 +175,17 @@
"parse" => PMC 'PIRGrammar' { ... }
Parse successful!
OUT
+
+
+language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'wrap flag -- new!' );
+
+# This test makes sure pir.pbc is running, not IMCC, as :wrap is still
unimplemented and undecided.
+.sub x :wrap('y')
+
+.end
+
+
+CODE
+"parse" => PMC 'PIRGrammar' { ... }
+Parse successful!
+OUT
Added: trunk/languages/PIR/t/sym.t
==============================================================================
--- (empty file)
+++ trunk/languages/PIR/t/sym.t Wed Jan 31 13:30:57 2007
@@ -0,0 +1,78 @@
+#!perl
+
+use strict;
+use warnings;
+use lib qw(t . lib ../lib ../../lib ../../../lib);
+use Parrot::Test tests => 5;
+use Test::More;
+
+language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'local decls 1' );
+
+.sub main
+ .local int a
+ .local string b
+ .local num c
+ .local pmc d
+.end
+
+CODE
+"parse" => PMC 'PIRGrammar' { ... }
+Parse successful!
+OUT
+
+language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'local decls 2' );
+
+.sub main
+ .local int a, k, l, m
+ .local string b, n, o, p
+ .local num c, q, r, s
+ .local pmc d, t, u
+.end
+
+CODE
+"parse" => PMC 'PIRGrammar' { ... }
+Parse successful!
+OUT
+
+
+language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'local decls - unique_reg' );
+
+.sub main
+ .local int a :unique_reg, b, c
+ .local num e, f :unique_reg, g
+ .local pmc h, i, j :unique_reg
+.end
+
+CODE
+"parse" => PMC 'PIRGrammar' { ... }
+Parse successful!
+OUT
+
+language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'sym decls - unique_reg' );
+
+.sub main
+ .sym int a :unique_reg, b, c
+ .sym num e, f :unique_reg, g
+ .sym pmc h, i, j :unique_reg
+.end
+
+CODE
+"parse" => PMC 'PIRGrammar' { ... }
+Parse successful!
+OUT
+
+
+language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'lexicals' );
+
+.sub main
+ .local pmc a
+ .lex "x", $P0
+ .lex "y", a
+.end
+
+CODE
+"parse" => PMC 'PIRGrammar' { ... }
+Parse successful!
+OUT
+
+
Modified: trunk/languages/PIR/t/whitespace.t
==============================================================================
--- trunk/languages/PIR/t/whitespace.t (original)
+++ trunk/languages/PIR/t/whitespace.t Wed Jan 31 13:30:57 2007
@@ -522,3 +522,527 @@
Parse successful!
OUT
+#!perl
+
+use strict;
+use warnings;
+use lib qw(t . lib ../lib ../../lib ../../../lib);
+use Parrot::Test tests => 10;
+use Test::More;
+
+language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'comments before code' );
+#
+# pre-code comment
+#
+.sub main
+.end
+CODE
+"parse" => PMC 'PIRGrammar' { ... }
+Parse successful!
+OUT
+
+language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'comments after code' );
+.sub main
+.end
+#
+# comments after code
+#
+CODE
+"parse" => PMC 'PIRGrammar' { ... }
+Parse successful!
+OUT
+
+language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'comments in code' );
+.sub main
+#
+# in-code comment
+#
+.end
+CODE
+"parse" => PMC 'PIRGrammar' { ... }
+Parse successful!
+OUT
+
+
+language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'comments after code' );
+.sub main
+
+ x = 1 # this is an assignment!
+ # this is comment # this is even more comment
+
+.end
+CODE
+"parse" => PMC 'PIRGrammar' { ... }
+Parse successful!
+OUT
+
+language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'pre-code whitespace' );
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+.sub main
+.end
+CODE
+"parse" => PMC 'PIRGrammar' { ... }
+Parse successful!
+OUT
+
+language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'in-code whitespace' );
+.sub main
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+.end
+CODE
+"parse" => PMC 'PIRGrammar' { ... }
+Parse successful!
+OUT
+
+language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'after-code whitespace' );
+.sub main
+.end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+CODE
+"parse" => PMC 'PIRGrammar' { ... }
+Parse successful!
+OUT
+
+
+language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'pre-code pod comments' );
+=pod
+
+hi there
+
+documentation rocks!
+
+
+
+
+
+
+
+
+=cut
+
+
+
+.sub main
+.end
+CODE
+"parse" => PMC 'PIRGrammar' { ... }
+Parse successful!
+OUT
+
+language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'in-code pod comments' );
+.sub main
+
+=pod
+
+hello!!
+
+Parrot rocks too!
+
+=cut
+.end
+CODE
+"parse" => PMC 'PIRGrammar' { ... }
+Parse successful!
+OUT
+
+
+language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'after-code pod comments' );
+.sub main
+.end
+
+=pod
+
+Don't forget to hit enter after typing last OUT marker in the test file!
+
+=cut
+
+CODE
+"parse" => PMC 'PIRGrammar' { ... }
+Parse successful!
+OUT
+