Author: pmichaud
Date: Wed May  3 12:35:46 2006
New Revision: 12488

Added:
   trunk/languages/perl6/lib/POST.pir
   trunk/languages/perl6/lib/past2post.tg
Modified:
   trunk/MANIFEST
   trunk/config/gen/makefiles/perl6.in
   trunk/languages/perl6/lib/PAST.pir
   trunk/languages/perl6/lib/builtins.pir
   trunk/languages/perl6/lib/grammar_optok.pg
   trunk/languages/perl6/lib/main.pir
   trunk/languages/perl6/lib/pge2past.tg
   trunk/languages/perl6/perl6.pir

Log:
[perl6]
* Updated code generation to use a more parse->PAST->POST->PIR like
  transformation.  (But it's still a different POST from punie,
  although it's a lot closer.)
* This change breaks lots of previously-working tests, but those 
  will be fixed shortly.


Modified: trunk/MANIFEST
==============================================================================
--- trunk/MANIFEST      (original)
+++ trunk/MANIFEST      Wed May  3 12:35:46 2006
@@ -1521,13 +1521,15 @@
 languages/perl6/t/00-parrot/04-op-cmp.t           [perl6]
 languages/perl6/lib/parse.pir                     [perl6]
 languages/perl6/lib/PAST.pir                      [perl6]
+languages/perl6/lib/POST.pir                      [perl6]
 languages/perl6/lib/builtins.pir                  [perl6]
-languages/perl6/lib/past2pir.tg                   [perl6]
 languages/perl6/lib/main.pir                      [perl6]
 languages/perl6/lib/grammar_sub.pg                [perl6]
 languages/perl6/lib/grammar_rules.pg              [perl6]
 languages/perl6/lib/grammar_optok.pg              [perl6]
 languages/perl6/lib/pge2past.tg                   [perl6]
+languages/perl6/lib/past2post.tg                  [perl6]
+languages/perl6/lib/past2pir.tg                   [perl6]
 languages/pheme/MANIFEST                          [pheme]
 languages/pheme/TODO                              [pheme]
 languages/pheme/pheme.pir                         [pheme]

Modified: trunk/config/gen/makefiles/perl6.in
==============================================================================
--- trunk/config/gen/makefiles/perl6.in (original)
+++ trunk/config/gen/makefiles/perl6.in Wed May  3 12:35:46 2006
@@ -17,9 +17,10 @@
   lib/grammar_optok.pg \
   lib/grammar_sub.pg \
   lib/parse.pir \
-  lib/pge2past.tg \
-  lib/past2pir.tg \
   lib/PAST.pir \
+  lib/POST.pir \
+  lib/pge2past.tg \
+  lib/past2post.tg \
   lib/main.pir \
   lib/builtins.pir
 
@@ -27,8 +28,8 @@
 perl6.pbc: $(PARROT) $(PGE_DIR)/pgc.pir $(SOURCES)
        $(PARROT) $(PGE_DIR)/pgc.pir --output=lib/grammar_gen.pir \
            lib/grammar_rules.pg lib/grammar_optok.pg lib/grammar_sub.pg
-       $(PARROT) $(TGE_DIR)/tgc.pir --output=lib/pge2past.pir lib/pge2past.tg
-       $(PARROT) $(TGE_DIR)/tgc.pir --output=lib/past2pir.pir lib/past2pir.tg
+       $(PARROT) $(TGE_DIR)/tgc.pir --output=lib/pge2past_gen.pir 
lib/pge2past.tg
+       $(PARROT) $(TGE_DIR)/tgc.pir --output=lib/past2post_gen.pir 
lib/past2post.tg
        $(PARROT) -o perl6.pbc perl6.pir
 
 # This is a listing of all targets, that are meant to be called by users
@@ -58,7 +59,7 @@
 testclean:
 
 clean: 
-       $(RM_RF) perl6.pbc lib/grammar_gen.pir
+       $(RM_RF) perl6.pbc lib/grammar_gen.pir lib/pge2past_gen.pir 
lib/past2post_gen.pir
 
 realclean: clean
        $(RM_RF) Makefile

Modified: trunk/languages/perl6/lib/PAST.pir
==============================================================================
--- trunk/languages/perl6/lib/PAST.pir  (original)
+++ trunk/languages/perl6/lib/PAST.pir  Wed May  3 12:35:46 2006
@@ -10,30 +10,6 @@
 needed for Perl 6.  The currently defined ast nodes:
 
     Perl6::PAST::Node       - base class for all ast nodes
-    Perl6::PAST::Sub        - a subroutine or executable block
-    Perl6::PAST::Stmts      - a block of statements
-    Perl6::PAST::Stmt       - a single statement
-    Perl6::PAST::Op         - an operation
-    Perl6::PAST::Val        - a constant value
-    Perl6::PAST::Var        - a variable
-    Perl6::PAST::Lex        - a lexical declaration ("my")
-    Perl6::PAST::Vector     - a vector of values
-    Perl6::PAST::Assign     - an assignment operation
-
-The C<Perl6::PAST::Node> class itself is derived from C<Hash>, so
-that it's easy to store and retrieve attributes from each
-node object.
-
-This file also defines (by inclusion) C<Perl6::PAST::Grammar>,
-which converts a Match object into an abstract syntax tree.
-
-=head1 PAST functions
-
-=over 4
-
-=item C<__onload()>
-
-Creates the C<Perl6::PAST::*> classes.
 
 =cut
 
@@ -41,178 +17,270 @@
 
 .sub '__onload' :load
     .local pmc base
-    $P0 = getclass 'Hash'
-    base = subclass $P0, 'Perl6::PAST::Node'
-    addattribute base, '$.source'                  # original source
-    addattribute base, '$.pos'                     # offset position
+    base = newclass 'Perl6::PAST::Node'
+    addattribute base, '@.children'
+    addattribute base, '$.source'
+    addattribute base, '$.pos'
 
-    $P0 = subclass base, 'Perl6::PAST::Sub'
-    $P0 = subclass base, 'Perl6::PAST::Stmts'
-    $P0 = subclass base, 'Perl6::PAST::Stmt'
-    $P0 = subclass base, 'Perl6::PAST::Exp'
     $P0 = subclass base, 'Perl6::PAST::Op'
+    addattribute $P0, '$.op'
+    addattribute $P0, '$.name'
+
     $P0 = subclass base, 'Perl6::PAST::Val'
-    $P0 = subclass base, 'Perl6::PAST::Var'
-    $P0 = subclass base, 'Perl6::PAST::Lex'
+    addattribute $P0, '$.valtype'
+    addattribute $P0, '$.val'
 
-    base = getclass 'TGE'
-    $P0 = subclass base, 'Perl6::PAST::Grammar'
-    $P0 = subclass base, 'Perl6::PIR::Grammar'
+    $P0 = subclass base, 'Perl6::PAST::Exp'
+    $P0 = subclass base, 'Perl6::PAST::Stmt'
+    $P0 = subclass base, 'Perl6::PAST::Stmts'
+    $P0 = subclass base, 'Perl6::PAST::Sub'
+    $P0 = subclass base, 'Perl6::PAST::Var'
 
     $P0 = new .Integer
-    store_global "Perl6::PAST", "$!serno", $P0
+    $P0 = 10
+    store_global '$!serno', $P0
+    .return ()
 .end
 
-.namespace [ 'Perl6::PAST::Node' ]
-
-=back
 
-=head2  Perl6::PAST::Node methods
-
-=over 4
-
-=item C<__init()>
-
-Initializes a new C<Perl6::PAST::Node> object.
+.namespace [ 'Perl6::PAST::Node' ]
 
-=cut
+.sub 'attr' :method
+    .param string attrname
+    .param pmc value
+    .param int setvalue
+    if setvalue goto set
+    value = getattribute self, attrname
+    unless null value goto end
+    value = new .Undef
+  set:
+    setattribute self, attrname, value
+  end:
+    .return (value)
+.end
 
-.sub __init :method
-    $P0 = new .String
-    $P1 = new .Integer
 
-    setattribute self, "Perl6::PAST::Node\x0$.source", $P0
-    setattribute self, "Perl6::PAST::Node\x0$.pos", $P1
+.sub 'init' :method
+    .param pmc children        :slurpy
+    .param pmc adverbs         :slurpy :named
+
+    unless null children goto set_children
+    children = new .ResizablePMCArray
+  set_children:
+    setattribute self, '@.children', children
+
+    if null adverbs goto end
+    .local pmc iter
+    iter = new .Iterator, adverbs
+    iter = 0
+  iter_loop:
+    unless iter goto iter_end
+    $S0 = shift iter
+    if $S0 == 'XXX' goto iter_loop
+    $P0 = iter[$S0]
+    $P1 = find_method self, $S0
+    self.$P1($P0)
+    goto iter_loop
+  iter_end:
+  end:
     .return ()
 .end
 
 
-=item C<set_node(PMC match)>
-
-Initializes the current ast node with the source code
-information from a match object (presumably a component
-of the parse tree).
+.sub 'new' :method
+    .param string class
+    .param pmc children        :slurpy
+    .param pmc adverbs         :slurpy :named
+
+    $I0 = find_type class
+    $P0 = new $I0
+    $P0.'init'(children :flat, 'node'=>self, 'XXX'=>1, adverbs :flat :named)
+    .return ($P0)
+.end
 
-=cut
 
-.sub 'set_node' :method
-    .param pmc match                               # match object of source
-    $P0 = getattribute self, "Perl6::PAST::Node\x0$.source"
-    $S0 = match
-    $P0 = $S0
-    $P1 = getattribute self, "Perl6::PAST::Node\x0$.pos"
-    $I1 = match.from()
-    $P1 = $I1
+.sub 'add_child' :method
+    .param pmc child
+    .local pmc array
+    array = getattribute self, '@.children'
+    push array, child
     .return ()
 .end
 
 
-=item C<source()>
-
-Return the source code associated with the current node.
+.sub 'add_child_new' :method
+    .param string class
+    .param pmc children        :slurpy
+    .param pmc adverbs         :slurpy :named
+    $P0 = self.'new'(class, children :flat, 'XXX'=>0, adverbs :flat :named)
+    self.'add_child'($P0)
+    .return ($P0)
+.end
 
-=cut
 
 .sub 'source' :method
-    $P0 = getattribute self, "Perl6::PAST::Node\x0$.source"
-    .return ($P0)
+    .param string source       :optional
+    .param int has_source      :opt_flag
+    .return self.'attr'('$.source', source, has_source)
 .end
 
 
-=item C<pos()>
+.sub 'pos' :method
+    .param int pos             :optional
+    .param int has_pos         :opt_flag
+    .return self.'attr'('$.pos', pos, has_pos)
+.end
 
-Return the source code offset associated with this
-node.
 
-=cut
+.sub 'node' :method
+    .param pmc node
+    $I0 = isa node, 'Perl6::PAST::Node'
+    if $I0 goto clone_past
+  clone_pge:
+    $S0 = node
+    self.'source'($S0)
+    $I0 = node.'from'()
+    self.'pos'($I0)
+    .return ()
+  clone_past:
+    $S0 = node.'source'()
+    self.'source'($S0)
+    $I0 = node.'pos'()
+    self.'pos'($I0)
+    .return ()
+.end
 
-.sub 'pos' :method
-    $P0 = getattribute self, "Perl6::PAST::Node\x0$.pos"
-    .return ($P0)
+
+.sub 'child_iter' :method
+    $P0 = getattribute self, '@.children'
+    $P1 = new .Iterator, $P0
+    $P1 = 0
+    .return ($P1)
 .end
 
 
-=item C<generate_unique(STR prefix)>
+=item C<unique([string fmt])>
 
-Generate a unique string that begins with C<prefix>.
+Each call to C<unique> returns a unique number, or if a C<fmt>
+parameter is given it returns a unique string beginning with
+C<fmt>.  (This may eventually be generalized to allow
+uniqueness anywhere in the string.)  The function starts
+counting at 10 (so that the values 0..9 can be considered "safe").
 
 =cut
 
-.sub "generate_unique" :method
-    .param string prefix
-    $P0 = find_global "Perl6::PAST", "$!serno"
+.sub 'unique' :method
+    .param string fmt          :optional
+    .param int has_fmt         :opt_flag
+
+    if has_fmt goto unique_1
+    fmt = ''
+  unique_1:
+    $P0 = find_global 'Perl6::PAST', '$!serno'
     $S0 = $P0
-    $S0 = concat prefix, $S0
+    $S0 = concat fmt, $S0
     inc $P0
     .return ($S0)
 .end
 
 
-=item C<__dump(PMC dumper, STR label)>
+.sub '__elements' :method
+    $P0 = getattribute self, '@.children'
+    $I0 = elements $P0
+    .return ($I0)
+.end
 
-Display the contents of the current node in a form compatible
-with C<Data::Dumper>.
 
-=cut
+.sub '__get_pmc_keyed_int' :method
+    .param int key
+    $P0 = getattribute self, '@.children'
+    $P0 = $P0[key]
+    .return ($P0)
+.end
+
+
+.sub '__set_pmc_keyed_int' :method
+    .param int key
+    .param pmc val
+    $P0 = getattribute self, '@.children'
+    $P0[key] = val
+    .return ()
+.end
+
+
+.sub '__dumplist' :method
+    .return ('$.pos @.children')
+.end
+
 
 .sub '__dump' :method
     .param pmc dumper
     .param string label
     .local string indent, subindent
-    .local pmc iter, val
-    .local string key
-    .local pmc hash
-    .local int hascapts
 
     (subindent, indent) = dumper.'newIndent'()
-    print '=> '
-    $S0 = self.source()
-    dumper.'genericString'('', $S0)
-    $I0 = self.pos()
-    print ' @ '
-    print $I0
-    hascapts = 0
-    iter = new .Iterator, self
+    print '=> { '
+    .local pmc attrlist, iter
+    $S0 = self.'__dumplist'()
+    attrlist = split ' ', $S0
+    iter = new .Iterator, attrlist
     iter = 0
-  dump_hash_1:
-    unless iter goto dump_end
-    if hascapts goto dump_hash_2
-    print ' {'
-    hascapts = 1
-  dump_hash_2:
+  iter_loop:
+    unless iter goto iter_end
+    .local string attrname
+    .local pmc val
+    attrname = shift iter
+    val = getattribute self, attrname
     print "\n"
     print subindent
-    key = shift iter
-    val = iter[key]
-    print '<'
-    print key
-    print '> => '
+    print attrname
+    print ' => '
     dumper.'dump'(label, val)
-    goto dump_hash_1
-  dump_end:
-    unless hascapts goto end
+    goto iter_loop
+  iter_end:
     print "\n"
     print indent
     print '}'
-  end:
     dumper.'deleteIndent'()
+    .return ()
 .end
 
-.namespace [ 'Perl6::PAST::Grammar' ]
-.include 'lib/pge2past.pir'
 
-.namespace [ 'Perl6::PIR::Grammar' ]
-.include 'lib/past2pir.pir'
+.namespace [ 'Perl6::PAST::Op' ]
 
-=back
+.sub 'op' :method
+    .param string op           :optional
+    .param int has_op          :opt_flag
+    .return self.'attr'('$.op', op, has_op)
+.end
 
-=head1 LICENSE
 
-Copyright (c) 2005-2006 The Perl Foundation
+.sub 'name' :method
+    .param string name         :optional
+    .param int has_name        :opt_flag
+    .return self.'attr'('$.name', name, has_name)
+.end
 
-This is free software; you may redistribute it and/or modify
-it under the same terms as Parrot.
 
-=cut
+.sub '__dumplist' :method
+    .return ('$.op $.name @.children')
+.end
+
+
+.namespace [ 'Perl6::PAST::Val' ]
+
+.sub 'valtype' :method
+    .param string valtype      :optional
+    .param int has_valtype     :opt_flag
+    .return self.'attr'('$.valtype', valtype, has_valtype)
+.end
+
+.sub 'val' :method
+    .param string val          :optional
+    .param int has_val         :opt_flag
+    .return self.'attr'('$.val', val, has_val)
+.end
 
-## vim: expandtab sw=4
+.sub '__dumplist' :method
+    .return ('$.valtype $.val')
+.end

Added: trunk/languages/perl6/lib/POST.pir
==============================================================================
--- (empty file)
+++ trunk/languages/perl6/lib/POST.pir  Wed May  3 12:35:46 2006
@@ -0,0 +1,203 @@
+=head1 NAME
+
+POST - A(nother) low-level opcode syntax tree.
+
+=head1 DESCRIPTION
+
+Compilers progress through various levels of
+tree representations of compilation of a source
+code program.  POST (Parrot Opcode Syntax Tree) is
+a low-level tree which closely corresponds to the
+semantics of PIR/PASM.
+
+The base class of POST is Perl6::PAST::Node -- see C<lib/PAST.pir>
+
+=cut
+
+.namespace [ 'Perl6::POST' ]
+
+.sub '__onload' :load
+    .local pmc base
+    $P0 = getclass 'Perl6::PAST::Node'
+    base = subclass $P0, 'Perl6::POST::Node'
+    addattribute base, '$.name'
+    addattribute base, '$.value'
+
+    $P0 = subclass base, 'Perl6::POST::Val'
+    addattribute $P0, '$.valtype'
+
+    $P0 = subclass base, 'Perl6::POST::Op'
+    $P0 = subclass base, 'Perl6::POST::Ops'
+    $P0 = subclass base, 'Perl6::POST::Label'
+    $P0 = subclass base, 'Perl6::POST::Sub'
+
+.end
+
+.namespace [ 'Perl6::POST::Node' ]
+
+.sub '__init' :method
+    $P0 = new .String
+    setattribute self, '$.name', $P0
+    $P0 = new String
+    setattribute self, '$.value', $P0
+    .return ()
+.end
+
+.sub 'name' :method
+    .param pmc name            :optional
+    .param int has_name        :opt_flag
+    .return self.'attr'('$.name', name, has_name)
+.end
+  
+=item C<value()>
+
+Set or return the invocant's value.  If no value has been
+previously set for this node, then the default for POST::Node
+is to use the value of its last child.  If it has no children,
+then we generate a unique PMC register (uninitialized) and
+use that.
+
+=cut
+
+.sub value :method
+    .param pmc value           :optional
+    .param int has_value       :opt_flag
+
+    value = self.'attr'('$.value', value, has_value)
+    if value > '' goto end
+    $S0 = self.'unique'('$P')
+    assign value, $S0
+  end:
+    .return (value)
+.end
+
+
+.sub '__dumplist' :method
+    .return ('$.name $.value @.children')
+.end
+
+
+.namespace [ 'Perl6::POST::Ops' ]
+
+.sub 'pir' :method
+    .local pmc code, iter
+
+    code = new 'PGE::CodeString'
+    iter = self.'child_iter'()
+  iter_loop:
+    unless iter goto iter_end
+    $P0 = shift iter
+    $P1 = $P0.'pir'()
+    code .= $P1
+    goto iter_loop
+  iter_end:
+    .return (code)
+.end
+
+
+.namespace [ 'Perl6::POST::Op' ]
+
+.sub 'pir' :method
+    .local pmc code
+
+    .local pmc childvalues, iter
+    childvalues = new .ResizablePMCArray
+    iter = self.'child_iter'()
+  iter_loop:
+    unless iter goto iter_end
+    $P0 = shift iter
+    $I0 = isa $P0, 'Perl6::POST::Node'
+    if $I0 == 0 goto iter_loop_1
+    $P0 = $P0.'value'()
+  iter_loop_1:
+    push childvalues, $P0
+    goto iter_loop
+  iter_end:
+
+    code = new 'PGE::CodeString'
+    .local string name
+    name = self.'name'()
+    $S0 = substr name, 0, 1
+    if $S0 == "'" goto sub_call
+    code.'emit'('    %n %,', childvalues :flat, 'n'=>name)
+    .return (code)
+
+  sub_call:
+    $P0 = shift childvalues
+    code.emit('    %r = %n(%,)', childvalues :flat, 'r'=>$P0, 'n'=>name)
+    .return (code)
+.end
+
+
+.namespace [ 'Perl6::POST::Label' ]
+
+=item C<value()>
+
+Returns the value for this label.  If one hasn't already been
+set, a new unique label is generated from the invocant's name
+and that is returned.
+
+=cut
+
+.sub 'value' :method    
+    .param pmc value           :optional
+    .param int has_value       :opt_flag
+    value = self.'attr'('$.value', value, has_value)
+    if value > '' goto value_end
+    .local pmc name
+    name = self.'name'()
+    $S0 = self.'unique'(name)
+    assign value, $S0
+  value_end:
+    .return (value)
+.end
+
+
+.sub 'pir' :method
+    .local string code
+    .local string value
+    value = self.'value'()
+    code = '  '
+    code .= value
+    code .= ":\n"
+    .return (code)
+.end
+
+
+.namespace [ 'Perl6::POST::Sub' ]
+
+.sub 'pir' :method
+    .local pmc code, iter
+    code = new 'PGE::CodeString'
+    code.'emit'(".sub 'anon' :anon")
+    iter = self.'child_iter'()
+  iter_loop:
+    unless iter goto iter_end
+    $P0 = shift iter
+    $P1 = $P0.'pir'()
+    code .= $P1
+    goto iter_loop
+  iter_end:
+    code.'emit'('.end')
+    .return (code)
+.end
+
+
+.namespace [ 'Perl6::POST::Val' ]
+
+.sub 'value' :method
+    .param string value        :optional
+    .param int has_value       :opt_flag
+    .local pmc v, valtype
+    .return self.'attr'('$.value', value, has_value)
+.end
+
+.sub 'valtype' :method
+    .param string valtype      :optional
+    .param int has_valtype     :opt_flag
+    .return self.'attr'('$.valtype', valtype, has_valtype)
+.end
+
+.sub '__dumplist' :method
+    .return ('$.name $.value $.valtype')
+.end

Modified: trunk/languages/perl6/lib/builtins.pir
==============================================================================
--- trunk/languages/perl6/lib/builtins.pir      (original)
+++ trunk/languages/perl6/lib/builtins.pir      Wed May  3 12:35:46 2006
@@ -38,6 +38,62 @@
 .end
 
 
+.sub 'infix:<'
+    .param pmc a
+    .param pmc b
+    $I0 = cmp_num a, b
+    $I0 = islt $I0, 0
+    .return ($I0)
+.end
+
+
+.sub 'infix:>'
+    .param pmc a
+    .param pmc b
+    $I0 = cmp_num a, b
+    $I0 = isgt $I0, 0
+    .return ($I0)
+.end
+
+
+.sub 'infix:<='
+    .param pmc a
+    .param pmc b
+    $I0 = cmp_num a, b
+    $I0 = isle $I0, 0
+    .return ($I0)
+.end
+
+
+.sub 'infix:>='
+    .param pmc a
+    .param pmc b
+    $I0 = cmp_num a, b
+    $I0 = isge $I0, 0
+    .return ($I0)
+.end
+
+
+.sub 'infix:=='
+    .param pmc a
+    .param pmc b
+    $I0 = cmp_num a, b
+    $I0 = iseq $I0, 0
+    .return ($I0)
+.end
+
+
+.sub 'infix:!='
+    .param pmc a
+    .param pmc b
+    $I0 = cmp_num a, b
+    $I0 = isne $I0, 0
+    .return ($I0)
+.end
+
+
+
+
 .sub 'infix:**'
     .param num base
     .param num exp

Modified: trunk/languages/perl6/lib/grammar_optok.pg
==============================================================================
--- trunk/languages/perl6/lib/grammar_optok.pg  (original)
+++ trunk/languages/perl6/lib/grammar_optok.pg  Wed May  3 12:35:46 2006
@@ -19,6 +19,7 @@
     is parsed(&listop) { ... }
 
 proto 'circumfix:( )' is equiv('term:')
+    is post('set')
     is pir("        # circumfix op") { ... }
 
 ## dot comment in postfix position
@@ -104,18 +105,22 @@
 
 ## multiplicative
 proto 'infix:*' is precedence('17=')
+    is post('mul')
     is pir("    %t = %0 * %1")
     { ... }
 
 proto 'infix:/' is equiv('infix:*')
+    is post('div')
     is pir("    %t = %0 / %1")
     { ... }
 
 proto 'infix:%' is equiv('infix:*')
+    is post('mod')
     is pir("    %t = mod %0, %1")
     { ... }
 
 proto 'infix:x' is equiv('infix:*')
+    is post('repeat')
     is pir("    %t = repeat %0, %1")
     { ... }
 
@@ -143,14 +148,17 @@
 
 ## additive
 proto 'infix:+' is precedence('16=')
+    is post('add')
     is pir("    %r = %0 + %1")
     { ... }
 
 proto 'infix:-' is equiv('infix:+')
+    is post('sub')
     is pir("    %r = %0 - %1")
     { ... }
 
 proto 'infix:~' is equiv('infix:+')
+    is post('concat')
     is pir("    %r = concat %0, %1")
     { ... }
 
@@ -364,8 +372,8 @@
 proto 'infix:||' is precedence('09=')
     is pasttype('cond') { ... }
 
-proto 'infix:^^' is equiv('infix:||')
-    is pasttype('cond') { ... }
+proto 'infix:^^' is precedence('09=') is assoc('list')
+    is pasttype('xor') { ... }
 
 proto 'infix://' is equiv('infix:||')
     is pasttype('cond') { ... }
@@ -489,7 +497,7 @@
     is pasttype('cond') { ... }
 
 proto 'infix:xor' is equiv('infix:or')
-    is pasttype('cond') { ... }
+    is pasttype('xor') { ... }
 
 proto 'infix:err' is equiv('infix:or')
     is pasttype('cond') { ... }

Modified: trunk/languages/perl6/lib/main.pir
==============================================================================
--- trunk/languages/perl6/lib/main.pir  (original)
+++ trunk/languages/perl6/lib/main.pir  Wed May  3 12:35:46 2006
@@ -35,6 +35,8 @@
     $P0()
     $P0 = find_global 'Perl6::PAST', '__onload'
     $P0()
+    $P0 = find_global 'Perl6::POST', '__onload'
+    $P0()
 
     load_bytecode 'dumper.pbc'
     load_bytecode 'PGE/Dumper.pbc'

Added: trunk/languages/perl6/lib/past2post.tg
==============================================================================
--- (empty file)
+++ trunk/languages/perl6/lib/past2post.tg      Wed May  3 12:35:46 2006
@@ -0,0 +1,246 @@
+Perl6::PAST::Sub: post(.) = {
+    $P0 = node[0]
+    $P0 = tree.'get'('post', $P0)
+    .local pmc post
+    post = new 'Perl6::POST::Sub'
+    post.'init'($P0, 'name'=>'anon')
+    .return (post)
+}
+
+
+Perl6::PAST::Stmts: post(.) = {
+    .local pmc iter, ops
+    ops = new 'Perl6::POST::Ops'
+    ops.'init'('node'=>node)
+    iter = node.'child_iter'()
+  iter_loop:
+    unless iter goto iter_end
+    $P0 = shift iter
+    $P1 = tree.'get'('post', $P0)
+    ops.'add_child'($P1)
+    goto iter_loop
+  iter_end:
+    .local string value
+    value = $P1.'value'()
+    ops.'value'(value)
+    .return (ops)
+}
+
+
+Perl6::PAST::Stmt: post(.) = {
+    $P0 = node[0]
+    $P1 = tree.'get'('post', $P0)
+    .return ($P1)
+}
+
+
+Perl6::PAST::Exp: post(.) = {
+    $P0 = node[0]
+    $P1 = tree.'get'('post', $P0)
+    .return ($P1)
+}
+
+
+Perl6::PAST::Op: post(.) = {
+    .local string opname, pasttype
+    .local pmc optable, optok
+    opname = node.'op'()
+    optable = find_global 'Perl6::Grammar', '$optable'
+    optok = optable[opname]
+    pasttype = optok['pasttype']
+    if pasttype > '' goto dispatch_post
+    pasttype = 'simple'
+  dispatch_post:
+    .return tree.'get'(pasttype, node)
+}
+    
+
+Perl6::PAST::Op: simple(.) = {
+    .local pmc ops
+    ops = new 'Perl6::POST::Ops'
+    ops.'init'('node'=>node)
+
+    .local string opname, postop
+
+    opname = node.'op'()
+    postop = node.'name'()
+
+    .local pmc iter, arglist
+    $P0 = node
+    if opname != 'prelist:' goto op_children
+    $P1 = node[0]
+    $I0 = isa $P1, 'Perl6::PAST::Op'
+    if $I0 == 0 goto op_children
+    $S0 = $P1.'op'()
+    if $S0 != 'infix:,' goto op_children
+    $P0 = $P1
+  op_children:
+    iter = $P0.'child_iter'()
+    arglist = new .ResizablePMCArray
+  iter_loop:
+    unless iter goto iter_end
+    .local pmc cpast, cpost
+    cpast = shift iter
+    cpost = tree.'get'('post', cpast)
+    ops.'add_child'(cpost)
+    push arglist, cpost
+    goto iter_loop
+  iter_end:
+    $S0 = substr postop, 0, 1
+    if $S0 == "'" goto postop_end
+    ##   direct POST op, create a temporary to store the result
+    ops.'add_child_new'('Perl6::POST::Op', ops, '.Undef', 'name'=>'new')
+  postop_end:
+    ops.'add_child_new'('Perl6::POST::Op', ops, arglist :flat, 'name'=>postop)
+    .return (ops)
+}
+
+
+Perl6::PAST::Op: cond(.) = {
+    .local pmc ops
+    ops = new 'Perl6::POST::Ops'
+    ops.'init'('node'=>node)
+
+    .local pmc exprpast, thenpast, elsepast
+    .local pmc exprpost, thenpost, elsepost
+    exprpast = node[0]
+    thenpast = node[1]
+    elsepast = node[2]
+
+    .local pmc thenlabel, endlabel
+    thenlabel = ops.'new'('Perl6::POST::Label', 'name'=>'if_then')
+    endlabel = ops.'new'('Perl6::POST::Label', 'name'=>'if_end')
+
+    exprpost = tree.'get'('post', exprpast)
+    ops.'add_child'(exprpost)
+    ops.'add_child_new'('Perl6::POST::Op', exprpost, thenlabel, 'name'=>'if')
+    elsepost = exprpost
+    $I0 = defined elsepast
+    if $I0 == 0 goto cond_no_else
+    elsepost = tree.'get'('post', elsepast)
+    ops.'add_child'(elsepost)
+  cond_no_else:
+    ops.'add_child_new'('Perl6::POST::Op', ops, elsepost, 'name'=>'set')
+    ops.'add_child_new'('Perl6::POST::Op', endlabel, 'name'=>'goto')
+    ops.'add_child'(thenlabel)
+    thenpost = exprpost
+    $I0 = defined thenpast
+    if $I0 == 0 goto cond_no_then
+    thenpost = tree.'get'('post', thenpast)
+    ops.'add_child'(thenpost)
+  cond_no_then:
+    ops.'add_child_new'('Perl6::POST::Op', ops, thenpost, 'name'=>'set')
+    ops.'add_child'(endlabel)
+    .return (ops)
+}
+
+
+Perl6::PAST::Op: xor(.) = {
+    .local pmc ops
+    ops = new 'Perl6::POST::Ops'
+    ops.'init'('node'=>node)
+
+    .local pmc endlabel, falselabel
+    falselabel = ops.'new'('Perl6::POST::Label', 'name'=>'xor_false')
+    endlabel = ops.'new'('Perl6::POST::Label', 'name'=>'xor_end')
+
+    .local pmc iter, apast, apost, i, t, u
+    i = ops.unique('$I')
+    t = ops.unique('$I')
+    u = ops.unique('$I')
+    iter = node.'child_iter'()
+    apast = shift iter
+    apost = tree.'get'('post', apast)
+    ops.'add_child'(apost)
+    ops.'add_child_new'('Perl6::POST::Op', ops, apost, 'name'=>'set')
+    ops.'add_child_new'('Perl6::POST::Op', t, apost, 'name'=>'istrue')
+  inner_child:
+    .local pmc bpast, bpost
+    bpast = shift iter
+    bpost = tree.'get'('post', bpast)
+    ops.'add_child'(bpost)
+    ops.'add_child_new'('Perl6::POST::Op', u, bpost, 'name'=>'istrue')
+    ops.'add_child_new'('Perl6::POST::Op', i, t, u, 'name'=>'and')
+    ops.'add_child_new'('Perl6::POST::Op', i, falselabel, 'name'=>'if')
+    unless iter goto last_child
+    .local pmc s
+    s = ops.'new'('Perl6::POST::Label', 'name'=>'xor_skip')
+    ops.'add_child_new'('Perl6::POST::Op', t, s, 'name'=>'if')
+    ops.'add_child_new'('Perl6::POST::Op', ops, bpost, 'name'=>'set')
+    ops.'add_child_new'('Perl6::POST::Op', t, u, 'name'=>'set')
+    ops.'add_child'(s)
+    goto inner_child
+  last_child:
+    ops.'add_child_new'('Perl6::POST::Op', t, endlabel, 'name'=>'if')
+    ops.'add_child_new'('Perl6::POST::Op', ops, bpost, 'name'=>'set')
+    ops.'add_child_new'('Perl6::POST::Op', endlabel, 'name'=>'goto')
+    ops.'add_child'(falselabel)
+    ops.'add_child_new'('Perl6::POST::Op', ops, '.Undef', 'name'=>'new')
+    ops.'add_child'(endlabel)
+    .return (ops)
+}
+
+
+Perl6::PAST::Op: chain(.) = {
+    .local pmc ops
+    ops = new 'Perl6::POST::Ops'
+    ops.'init'('node'=>node)
+
+    .local string opname, pasttype
+    .local pmc optable, optok
+    optable = find_global 'Perl6::Grammar', '$optable'
+
+    .local pmc clist
+    clist = new .ResizablePMCArray
+  chain_loop:
+    $I0 = isa node, 'Perl6::PAST::Op'
+    if $I0 == 0 goto chain_end
+    opname = node.'op'()
+    optok = optable[opname]
+    pasttype = optok['pasttype']
+    if pasttype != 'chain' goto chain_end
+    push clist, node
+    node = node[0]
+    goto chain_loop
+  chain_end:
+
+    .local pmc endlabel, apast, apost
+    node = pop clist
+    endlabel = ops.'new'('Perl6::POST::Label', 'name'=>'chain_end')
+    apast = node[0]
+    apost = tree.'get'('post', apast)
+    ops.'add_child'(apost)
+
+  clist_loop:
+    .local pmc bpast, bpost
+    .local string postop
+    bpast = node[1]
+    bpost = tree.'get'('post', bpast)
+    postop = node.'name'()
+    ops.'add_child'(bpost)
+    ops.'add_child_new'('Perl6::POST::Op', ops, apost, bpost, 'name'=>postop)
+    unless clist goto clist_end
+    ops.'add_child_new'('Perl6::POST::Op', ops, endlabel, 'name'=>'unless')
+    apost = bpost
+    node = pop clist
+    goto clist_loop
+  clist_end:
+    ops.'add_child'(endlabel)
+    .return (ops)
+}
+
+
+
+Perl6::PAST::Val: post(.) = {
+    .local string val, valtype
+    val = node.'val'()
+    valtype = node.'valtype'()
+    .local pmc ops
+    ops = new 'Perl6::POST::Ops'
+    ops.'init'('node'=>node)
+    ops.'add_child_new'('Perl6::POST::Op', ops, '.Undef', 'name'=>'new')
+    $P0 = ops.'new'('Perl6::POST::Val', 'valtype'=>valtype, 'value'=>val)
+    ops.'add_child_new'('Perl6::POST::Op', ops, $P0, 'name'=>'assign')
+    .return (ops)
+}
+    

Modified: trunk/languages/perl6/lib/pge2past.tg
==============================================================================
--- trunk/languages/perl6/lib/pge2past.tg       (original)
+++ trunk/languages/perl6/lib/pge2past.tg       Wed May  3 12:35:46 2006
@@ -2,24 +2,21 @@
 
 ROOT: past(.) = {
     .local pmc past
-    past = new 'Perl6::PAST::Sub'
-    past.set_node(node)
     $P0 = node['statement_list']
     $P1 = tree.'get'('past', $P0, 'Perl6::Grammar::statement_list')
-    past['statement_list'] = $P1
+    past = new 'Perl6::PAST::Sub'
+    past.'init'($P1, 'node'=>node)
     .return (past)
 }
 
 
 Perl6::Grammar::statement_list:  past(.) = {
     .local pmc past
-    .local pmc children
     .local pmc iter
 
     past = new 'Perl6::PAST::Stmts'
-    past.'set_node'(node)
+    past.'init'('node'=>node)
 
-    children = new .ResizablePMCArray
     $P0 = node['statement']
     iter = new .Iterator, $P0
     iter = 0
@@ -28,27 +25,20 @@
     $P1 = shift iter
     $P2 = tree.'get'('past', $P1, 'Perl6::Grammar::statement')
     if null $P2 goto iter_loop
-    push children, $P2
+    past.'add_child'($P2)
     goto iter_loop
   iter_end:
-    past['children'] = children
     .return (past)
 }
 
 
 Perl6::Grammar::statement: past(.) = {
-    .local pmc past
-    past = new 'Perl6::PAST::Stmt'
-    past.'set_node'(node)
-
-    $P0 = node['expression']
-    if $P0 goto expression
     $P0 = node['statement_control']
     if $P0 goto statement_control
-    .return (past)
 
   expression:
     .local pmc stmt
+    $P0 = node['expression']
     stmt = tree.'get'('past', $P0, 'Perl6::Grammar::expression')
     $P0 = node['statement_modifier']
     unless $P0 goto expression_1
@@ -62,61 +52,107 @@
     if $S0 != 'unless' goto stmt_modifier_1
     exchange thenpast, elsepast
   stmt_modifier_1:
-    stmt = new "Perl6::PAST::Op"
     $P0 = modifier['expression']
     exprpast = tree.'get'('past', $P0, 'Perl6::Grammar::expression')
-    stmt['opname'] = 'statement_control:if'
-    stmt['pasttype'] = 'cond'
-    $P0 = new .ResizablePMCArray
-    $P0[0] = exprpast
-    $P0[1] = thenpast
-    $P0[2] = elsepast
-    stmt['children'] = $P0
+    stmt = new 'Perl6::PAST::Op'
+    stmt.'init'(exprpast, thenpast, elsepast, 'op'=>'statement_control:if', 
'node'=>modifier)
+
   expression_1:
-    past['statement'] = stmt
+    .local pmc past
+    past = new 'Perl6::PAST::Stmt'
+    past.'init'(stmt, 'node'=>node)
     .return (past)
 
   statement_control:
     $P1 = tree.'get'('past', $P0, 'Perl6::Grammar::statement_control')
-    past['statement'] = $P1
+    past = new 'Perl6::PAST::Stmt'
+    past.'init'($P1, 'node'=>node)
     .return (past)
 }
 
 
-Perl6::Grammar::expression: past(.) = {
+Perl6::Grammar::statement_control: past(.) = {
+    .local pmc key, exprlist, blocklist
+    key = node['KEY']
+    exprlist = node['expression']
+    blocklist = node['block']
+
+    ##   do we have an else clause?
+    .local pmc exprpast, thenpast, elsepast
+    .local int exprc, blockc
+    null elsepast
+  else_block:
+    exprc = elements exprlist
+    blockc = elements blocklist
+    if blockc <= exprc goto expr_block_pair
+    dec blockc
+    $P0 = blocklist[blockc]
+    elsepast = tree.'get'('past', $P0, 'Perl6::Grammar::block')
+
+  expr_block_pair:
+    ##   each remaining block is paired with an "if" (or "elsif")
+    ##   expression, except the first which could be "unless".
+    dec exprc
+    dec blockc
+    $P0 = exprlist[exprc]
+    exprpast = tree.'get'('past', $P0, 'Perl6::Grammar::expression')
+    $P0 = blocklist[blockc]
+    thenpast = tree.'get'('past', $P0, 'Perl6::Grammar::block')
+    if exprc > 0 goto if_op
+    if key != 'unless' goto if_op
+    exchange thenpast, elsepast
+
+  if_op:
     .local pmc past
+    past = new "Perl6::PAST::Op"
+    past.init(exprpast, thenpast, elsepast, 'node'=>node, 
'op'=>'statement_control:if')
+    elsepast = past
+    if exprc > 0 goto expr_block_pair
+    .return (past)
+}
+    
 
-    past = new 'Perl6::PAST::Exp'
-    past.set_node(node)
+Perl6::Grammar::expression: past(.) = {
+    .local pmc past
 
     $P0 = node['expr']
     $P1 = tree.'get'('past', $P0, 'Perl6::Grammar::expr')
-    past['expression'] = $P1
+    past = new 'Perl6::PAST::Exp'
+    past.'init'($P1, 'node'=>node)
     .return (past)
 }
 
 
 Perl6::Grammar::expr: past(.) = {
     .local string type
-    .local pmc optable
-    .local pmc op
     type = node['type']
     if type != "" goto pastrule
     null $P0
     .return ($P0)
 
   pastrule:
-    optable = find_global "Perl6::Grammar", "$optable"
-    op = optable[type]
-    $S0 = op['pastrule']
-    unless $S0 goto op_standard
+    .local pmc optable, optok
+    optable = find_global 'Perl6::Grammar', '$optable'
+    optok = optable[type]
+    $S0 = optok['pastrule']
+    unless $S0 goto set_subname
     .return tree.'get'($S0, node, 'Perl6::Grammar::expr')
 
-  op_standard:
+  set_subname:
+    .local string subname
+    subname = optok['post']
+    if subname > '' goto set_subname_end
+    subname = node['ident']
+    if subname > '' goto set_subname_quote
+    subname = type
+  set_subname_quote:
+    subname = concat "'", subname
+    subname = concat subname, "'"
+  set_subname_end:
+    
     .local pmc past, children, iter
     past = new 'Perl6::PAST::Op'
-    past.set_node(node)
-    children = new .ResizablePMCArray
+    past.'init'('node'=>node, 'op'=>type, 'name'=>subname)
     $P0 = node.'get_array'()
     if null $P0 goto iter_end
     iter = new .Iterator, $P0
@@ -128,32 +164,18 @@
     if $S0 == "" goto iter_loop
     $P1 = tree.'get'('past', $P0, 'Perl6::Grammar::expr')
     if null $P1 goto iter_loop
-    push children, $P1
+    past.'add_child'($P1)
     goto iter_loop
   iter_end:
-    past['opname'] = type
-    past['children'] = children
-    $S0 = op['pasttype']
-    past['pasttype'] = $S0
-    if type == 'infix:or' goto op_or
-    if type != 'infix:||' goto subname
-  op_or:
-    children = 3
-    $P0 = children[1]
-    children[2] = $P0
+    if type == 'infix:or' goto infix_or
+    if type != 'infix:||' goto end
+  infix_or:
+    ##   We cheat a bit here, moving the "then" portion of an 'or'
+    ##   node to the 'else' portion.
+    $P0 = past[1]
+    past[2] = $P0
     null $P0
-    children[1] = $P0
-
-  subname:
-    $I0 = exists node['ident']
-    if $I0 goto node_ident
-    past['subname'] = type
-    goto end
-
-  node_ident:
-    $S0 = node['ident']
-    past['subname'] = $S0
-
+    past[1] = $P0
   end:
     .return (past)
 }
@@ -200,94 +222,38 @@
 
 Perl6::Grammar::integer: past(.) = {
     .local pmc past
-    past = new 'Perl6::PAST::Val'
-    past.set_node(node)
-    past['returns'] = 'int'
     $I0 = node
-    past['value'] = $I0
+    past = new 'Perl6::PAST::Val'
+    past.'init'('node'=>node, 'valtype'=>'int', 'val'=>$I0)
     .return (past)
 }
 
 
 Perl6::Grammar::number: past(.) = {
     .local pmc past
+    $N0 = node
     past = new 'Perl6::PAST::Val'
-    past.set_node(node)
-    past['returns'] = 'num'
-    $N0 = node.value()
-    past['value'] = $N0
+    past.'init'('node'=>node, 'valtype'=>'num', 'val'=>$N0)
     .return (past)
 }
 
 
 Perl6::Grammar::string_literal: past(.) = {
     .local pmc past
-    past = new 'Perl6::PAST::Val'
-    past.set_node(node)
-    past['returns'] = 'str'
     $S0 = node
-    past['value'] = $S0
+    past = new 'Perl6::PAST::Val'
+    past.'init'('node'=>node, 'valtype'=>'str', 'val'=>$S0)
     .return (past)
 }
 
 
 Perl6::Grammar::version: past(.) = {
-    .local pmc past
-    past = new 'Perl6::PAST::Val'
-    past.set_node(node)
-    past['returns'] = 'str'
     $S0 = node
     $S0 = concat "'", $S0
-    concat $S0, "'"
-    past['value'] = $S0
-    .return (past)
-}
-
-
-Perl6::Grammar::statement_control: past(.) = {
-    .local pmc key, exprlist, blocklist
-    .local int exprc, blockc
-    .local pmc exprpast, thenpast, elsepast
-    key = node[0]
-    exprlist = node['expression']
-    blocklist = node['block']
-
-  # do we have an else clause?
-    null elsepast
-  else_block:
-    exprc = elements exprlist
-    blockc = elements blocklist
-    if blockc <= exprc goto expr_block_pair
-    dec blockc
-    $P0 = blocklist[blockc]
-    elsepast = tree.'get'('past', $P0, 'Perl6::Grammar::block')
-
-  ## each remaining block is paired with an "if" (or "elsif")
-  ## expression, except the first which could be an "unless".
-  expr_block_pair:
-    dec exprc
-    dec blockc
-    $P0 = exprlist[exprc]
-    exprpast = tree.'get'('past', $P0, 'Perl6::Grammar::expression')
-    $P0 = blocklist[blockc]
-    thenpast = tree.'get'('past', $P0, 'Perl6::Grammar::block')
-    if exprc > 0 goto if_op
-    if key != 'unless' goto if_op
-    exchange thenpast, elsepast
-
-  if_op:
+    $S0 = concat $S0, "'"
     .local pmc past
-    past = new "Perl6::PAST::Op"
-    past['opname'] = 'statement_control:if'
-    past['pasttype'] = 'cond'
-    $P0 = new .ResizablePMCArray
-    $P0[0] = exprpast
-    $P0[1] = thenpast
-    $P0[2] = elsepast
-    past['children'] = $P0
-    elsepast = past
-    if exprc > 0 goto expr_block_pair
-
+    past = new 'Perl6::PAST::Val'
+    past.'init'('node'=>node, 'valtype'=>'str', 'val'=>$S0)
     .return (past)
 }
 
@@ -304,14 +270,4 @@
 }
 
 
-Perl6::Grammar::scoped_variables: past(.) = {
-    .local pmc past
-    past = new "Perl6::PAST::Lex"
-    past.set_node(node)
-    $P0 = node['variable']
-    $S0 = $P0
-    past['variable'] = $S0
-    .return (past)
-}
-
 ## vim: expandtab sw=4

Modified: trunk/languages/perl6/perl6.pir
==============================================================================
--- trunk/languages/perl6/perl6.pir     (original)
+++ trunk/languages/perl6/perl6.pir     Wed May  3 12:35:46 2006
@@ -36,6 +36,11 @@
     load_bytecode 'PGE/Util.pbc'
     load_bytecode 'TGE.pbc'
 
+    
+    $P0 = getclass 'TGE'
+    $P1 = subclass $P0, 'Perl6::PAST::Grammar'
+    $P1 = subclass $P0, 'Perl6::POST::Grammar'
+
     $P0 = compreg 'PGE::P6Regex'
     $P1 = $P0('^<Perl6::Grammar::program>')
     store_global 'Perl6', '&parse', $P1
@@ -81,12 +86,16 @@
     ast = astbuilder.get('past')
     if target == 'PAST' goto return_ast
 
+  build_post:
+    .local pmc postgrammar, postbuilder, post
+    postgrammar = new 'Perl6::POST::Grammar'
+    postbuilder = postgrammar.'apply'(ast)
+    post = postbuilder.get('post')
+    if target == 'POST' goto return_post
+
   build_pir:
-    .local pmc pirgrammar, pirbuilder
     .local string pir
-    pirgrammar = new 'Perl6::PIR::Grammar'
-    pirbuilder = pirgrammar.'apply'(ast)
-    pir = pirbuilder.get('pir')
+    pir = post.'pir'()
     if target == 'PIR' goto return_pir
 
  compile_pir:
@@ -98,22 +107,33 @@
     .return (match)
   return_ast:
     .return (ast)
+  return_post:
+    .return (post)
   return_pir:
     .return (pir)
 .end
 
 
-.namespace [ 'Perl6::Grammar' ]
-.include 'lib/grammar_gen.pir'
-
 .include 'lib/parse.pir'
 
 .include 'lib/PAST.pir'
 
+.include 'lib/POST.pir'
+
 .include 'lib/main.pir'
 
 .include 'lib/builtins.pir'
 
+.namespace [ 'Perl6::Grammar' ]
+.include 'lib/grammar_gen.pir'
+
+.namespace [ 'Perl6::PAST::Grammar' ]
+.include 'lib/pge2past_gen.pir'
+
+.namespace [ 'Perl6::POST::Grammar' ]
+.include 'lib/past2post_gen.pir'
+
+
 =back
 
 =cut

Reply via email to