1 2=head1 NAME 3 4PAST - Parrot abstract syntax tree 5 6=head1 DESCRIPTION 7 8This file implements the various abstract syntax tree nodes 9for compiling programs in Parrot. 10 11=cut 12 13.namespace [ 'PAST';'Node' ] 14 15.sub 'onload' :anon :load :init 16 ## create the PAST::Node base class 17 .local pmc p6meta, base 18 p6meta = new 'P6metaclass' 19 base = p6meta.'new_class'('PAST::Node', 'parent'=>'PCT::Node') 20 21 p6meta.'new_class'('PAST::Op', 'parent'=>base) 22 p6meta.'new_class'('PAST::Stmts', 'parent'=>base) 23 p6meta.'new_class'('PAST::Stmt', 'parent'=>base) 24 p6meta.'new_class'('PAST::Val', 'parent'=>base) 25 p6meta.'new_class'('PAST::Var', 'parent'=>base) 26 p6meta.'new_class'('PAST::Block', 'parent'=>base) 27 p6meta.'new_class'('PAST::Control', 'parent'=>base) 28 p6meta.'new_class'('PAST::VarList', 'parent'=>base) 29 30 .return () 31.end 32 33=head1 PAST Node types 34 35=head2 PAST::Node 36 37C<PAST::Node> is the base class for all PAST nodes, and is 38derived from PCT::Node. A node has an array component to 39hold its children, and a hash component for its attributes. 40However, we tend to use accessor methods for accessing the node's 41attributes instead of accessing the hash directly. 42 43Every PAST node inherits C<name>, C<source>, and C<pos> attributes 44from C<PCT::Node>. The C<name> attribute is the node's name, if 45any, while C<source> and C<pos> are used to identify the location 46in the original source code for the node. The C<source> and C<pos> 47values are generally set by the C<node> method inherited from 48C<PCT::Node>. 49 50Other node attributes are generally defined by subclasses of C<PAST::Node>. 51 52=over 4 53 54=item returns([value]) 55 56Accessor method -- sets/returns the return type for the invocant. 57 58=cut 59 60.sub 'returns' :method 61 .param pmc value :optional 62 .param int has_value :opt_flag 63 .tailcall self.'attr'('returns', value, has_value) 64.end 65 66 67=item arity([value]) 68 69Accessor method -- sets/returns the arity (number of expected arguments) 70for the node. 71 72=cut 73 74.sub 'arity' :method 75 .param pmc value :optional 76 .param int has_value :opt_flag 77 .tailcall self.'attr'('arity', value, has_value) 78.end 79 80 81=item named([value]) 82 83Accessor method -- for named arguments, sets/returns the name to be 84associated with the argument. 85 86=cut 87 88.sub 'named' :method 89 .param pmc value :optional 90 .param int has_value :opt_flag 91 .tailcall self.'attr'('named', value, has_value) 92.end 93 94 95=item flat([value]) 96 97Accessor method -- sets/returns the "flatten" flag on arguments. 98 99=cut 100 101.sub 'flat' :method 102 .param pmc value :optional 103 .param int has_value :opt_flag 104 .tailcall self.'attr'('flat', value, has_value) 105.end 106 107 108=item handlers([node array]) 109 110Accessor method -- sets/returns handlers associated with this node. 111Handlers can be used for PAST::Block and PAST::Stmts nodes. 112 113=cut 114 115.sub 'handlers' :method 116 .param pmc value :optional 117 .param int has_value :opt_flag 118 .tailcall self.'attr'('handlers', value, has_value) 119.end 120 121 122=item handle_types([value]) 123 124Accessor method -- sets/returns the exception types this node 125handles. This is evaluated if the node is used as a block 126handler, the node is a PAST::Control node, or the node is 127a PAST::Op node of type 'try'. 128 129=cut 130 131.sub 'handle_types' :method 132 .param pmc value :optional 133 .param int has_value :opt_flag 134 .tailcall self.'attr'('handle_types', value, has_value) 135.end 136 137 138=item handle_types_except([value]) 139 140Accessor method -- sets/returns the exception types this node 141does not handle. Same as handle_types, but all exceptions not 142matching the specified ones will be caught. 143 144=cut 145 146.sub 'handle_types_except' :method 147 .param pmc value :optional 148 .param int has_value :opt_flag 149 .tailcall self.'attr'('handle_types_except', value, has_value) 150.end 151 152 153=item lvalue([flag]) 154 155Get/set the C<lvalue> attribute, which indicates whether this 156variable is being used in an lvalue context. 157 158=cut 159 160.sub 'lvalue' :method 161 .param pmc value :optional 162 .param int has_value :opt_flag 163 .tailcall self.'attr'('lvalue', value, has_value) 164.end 165 166 167=item signature([signature]) 168 169Get/set the signature to be used for evaluating any 170children nodes. 171 172=cut 173 174.sub 'signature' :method 175 .param pmc value :optional 176 .param int has_value :opt_flag 177 .tailcall self.'attr'('signature', value, has_value) 178.end 179 180 181=item childorder([order]) 182 183Get/set the order in which children nodes should be evaluated 184(via Compiler::post_children). If C<order> is 'right' then 185children are evaluated last-to-first, otherwise they're 186evaluated first-to-last. 187 188=cut 189 190.sub 'childorder' :method 191 .param pmc value :optional 192 .param int has_value :opt_flag 193 .tailcall self.'attr'('childorder', value, has_value) 194.end 195 196=back 197 198=head2 PAST::Val 199 200C<PAST::Val> nodes represent constant values in the abstract 201syntax tree. The C<name> attribute represents the value of the 202node. 203 204=over 4 205 206=item value([value]) 207 208Get/set the constant value for this node. 209 210=cut 211 212.namespace [ 'PAST';'Val' ] 213 214.sub 'value' :method 215 .param pmc value :optional 216 .param int has_value :opt_flag 217 .tailcall self.'attr'('value', value, has_value) 218.end 219 220=item lvalue([value]) 221 222Throw an exception if we try to make a PAST::Val into an lvalue. 223 224=cut 225 226.sub 'lvalue' :method 227 .param pmc value :optional 228 .param int has_value :opt_flag 229 unless has_value goto normal 230 unless value goto normal 231 die "Unable to set lvalue on PAST::Val node" 232 normal: 233 .tailcall self.'attr'('lvalue', value, has_value) 234.end 235 236=back 237 238=head2 PAST::Var 239 240C<PAST::Var> nodes represent variables within the abstract 241syntax tree. The variable name (if any) is given as the node's 242C<name> attribute. 243 244=over 4 245 246=item scope([value]) 247 248Get/set the PAST::Var node's "scope" (i.e., how the variable 249is accessed or set). Allowable values include "package", "lexical", 250"parameter", "keyed", "attribute" and "register", representing 251HLL global, lexical, block parameter, array/hash variables, object 252members and (optionally named) Parrot registers respectively. 253 254=cut 255 256.namespace [ 'PAST';'Var' ] 257 258.sub 'scope' :method 259 .param pmc value :optional 260 .param int has_value :opt_flag 261 .tailcall self.'attr'('scope', value, has_value) 262.end 263 264 265=item isdecl([flag]) 266 267Get/set the node's C<isdecl> attribute (for lexical variables) to C<flag>. 268A true value of C<isdecl> indicates that the variable given by 269this node is to be created within the current lexical scope. 270Otherwise, the node refers to a lexical variable from an outer scope. 271 272=cut 273 274.sub 'isdecl' :method 275 .param pmc value :optional 276 .param int has_value :opt_flag 277 .tailcall self.'attr'('isdecl', value, has_value) 278.end 279 280 281=item directaccess([flag]) 282 283Get/set the node's C<directaccess> attribute (for lexical variables) to C<flag>. 284A true value of C<isdecl> indicates that the variable given by this node 285can be accessed directly through the assigned register without going 286through the lexpad. Otherwise, find_lex/store_lex instructions will be used 287for retrieval and storage. 288 289=cut 290 291.sub 'directaccess' :method 292 .param pmc value :optional 293 .param int has_value :opt_flag 294 .tailcall self.'attr'('directaccess', value, has_value) 295.end 296 297 298=item namespace([namespace]) 299 300Get/set the variable's namespace attribute to the array of strings 301given by C<namespace>. Useful only for variables with a C<scope> 302of 'package'. 303 304=cut 305 306.sub 'namespace' :method 307 .param pmc value :optional 308 .param int has_value :opt_flag 309 .tailcall self.'attr'('namespace', value, has_value) 310.end 311 312 313=item slurpy([flag]) 314 315Get/set the node's C<slurpy> attribute (for parameter variables) to C<flag>. 316A true value of C<slurpy> indicates that the parameter variable given by this 317node is to be created as a slurpy parameter (consuming all remaining arguments 318passed in). 319 320=cut 321 322.sub 'slurpy' :method 323 .param pmc value :optional 324 .param int has_value :opt_flag 325 .tailcall self.'attr'('slurpy', value, has_value) 326.end 327 328 329=item call_sig([flag]) 330 331Get/set the node's C<call_sig> attribute (for parameter variables) to C<flag>. 332A true value of C<call_sig> indicates that the parameter variable given by this 333node is to be created as a C<:call_sig> parameter. If you use this, it should be 334the only parameter. 335 336=cut 337 338.sub 'call_sig' :method 339 .param pmc value :optional 340 .param int has_value :opt_flag 341 .tailcall self.'attr'('call_sig', value, has_value) 342.end 343 344 345=item viviself([type]) 346 347If the variable needs to be instantiated, then C<type> indicates 348either the type of the value to create for the node or (future 349implementation) a PAST tree to create the value. 350 351=cut 352 353.sub 'viviself' :method 354 .param pmc value :optional 355 .param int has_value :opt_flag 356 .tailcall self.'attr'('viviself', value, has_value) 357.end 358 359 360=item vivibase([type]) 361 362For keyed nodes, C<type> indicates the type of aggregate to 363create for the base if the base doesn't specify its own 'viviself' 364attribute. 365 366=cut 367 368.sub 'vivibase' :method 369 .param pmc value :optional 370 .param int has_value :opt_flag 371 .tailcall self.'attr'('vivibase', value, has_value) 372.end 373 374=item multitype([type]) 375 376Get/set MMD type of Var when used as parameter of Block. 377 378=cut 379 380.sub 'multitype' :method 381 .param pmc value :optional 382 .param int has_value :opt_flag 383 .tailcall self.'attr'('multitype', value, has_value) 384.end 385 386 387=back 388 389=head2 PAST::Op 390 391C<PAST::Op> nodes represent the operations in an abstract syntax 392tree. The primary function of the node is given by its C<pasttype>, 393secondary functions may be given by the node's C<name>, C<pirop>, 394or other attributes. 395 396=over 4 397 398=item pasttype([type]) 399 400A C<PAST::Op> node's C<pasttype> determines the type of operation to 401be performed. Predefined values of C<pasttype> are: 402 403assign - Copy the value of the node's second child into 404 the variable expression given by its first child. 405 406bind - Bind the variable given by the node's first child 407 to the value given by its second child. 408 409if - Evaluate the first child; if the first child is 410 true then evaluate the second child (if any) 411 otherwise evaluate the third child (if any). 412 If either the second or third child are missing, 413 then they evaluate as the result of the first child. 414 415unless - Same as 'if' above, but reverse the evaluation 416 of the second and third children nodes. 417 418while - Evaluate the first child, if the result is 419 true then evaluate the second child and repeat. 420 421until - Evaluate the first child, if the result is 422 false then evaluate the second child and repeat. 423 424for - Iterate over the first child. For each element, 425 invoke the sub in the second child, passing the 426 element as the only parameter. 427 428call - Call a subroutine, passing the results of any 429 child nodes as arguments. The subroutine to be 430 called is given by the node's C<name> attribute, 431 if the node has no C<name> attribute then the 432 first child is assumed to evaluate to a callable 433 sub. 434 435pirop - Execute the named PIR opcode, passing the results 436 of any children nodes as arguments. 437 438inline - Execute the sequence of PIR statements given 439 by the node's C<inline> attribute (a string). 440 See the C<inline> method below for details. 441 442callmethod - Invokes a method on an object, using children 443 nodes as arguments. If the node has a C<name> 444 attribute, then the first child is the invocant 445 and any remaining children are arguments. If 446 the node doesn't have a C<name> attribute, then 447 the first child evaluates to the method to be 448 called, the second child is the invocant, and 449 the remaining children are arguments to the method call. 450 451try - (preliminary) Execute the code given by the first 452 child, and if any exceptions occur then handle them 453 using the code given by the second child. 454 455If a node doesn't have a value set for C<pasttype>, then it 456assumes "pirop" if its C<pirop> attribute is set, otherwise it 457assumes "call". 458 459=cut 460 461.namespace [ 'PAST';'Op' ] 462 463.sub 'pasttype' :method 464 .param pmc value :optional 465 .param int has_value :opt_flag 466 .tailcall self.'attr'('pasttype', value, has_value) 467.end 468 469 470=item pirop([opcode]) 471 472Get/set the PIR opcode to be executed for this node. The PAST 473implementation knows about the argument types for many of the 474PIR opcodes, and will try to automatically convert the results 475of any children nodes into the correct types if needed. (In 476general, the implementation tries to convert things to PMCs 477whenever it isn't certain what else to do.) The table of 478PIR opcodes that PAST "knows" about is in F<POST.pir>. 479 480=cut 481 482.sub 'pirop' :method 483 .param pmc value :optional 484 .param int has_value :opt_flag 485 .tailcall self.'attr'('pirop', value, has_value) 486.end 487 488 489=item lvalue([flag]) 490 491Get/set whether this node is an lvalue, or treats its first 492child as an lvalue (e.g., for assignment). 493 494=item inline([STRING code]) 495 496Get/set the code to be used for inline PIR when C<pasttype> is 497"inline". The C<code> argument is PIR text to be inserted in 498the final generated code sequence. Sequences of "%0", "%1", 499"%2", ... "%9" in C<code> are replaced with the evaluated 500results of the first, second, third, ..., tenth children nodes. 501(If you need more than ten arguments to your inline PIR, consider 502making it a subroutine call instead.) 503 504The register to hold the result of the inline PIR operation is 505given by "%r", "%t", or "%u" in the C<code> string: 506 507 %r - Generate a unique PMC register for the result. 508 %t - Generate a unique PMC register for the result, 509 and initialize it with an object of type C<returns> 510 before the execution of the inline PIR. 511 %u - Re-use the first child's PMC (%0) if it's a temporary 512 result, otherwise same as %t above. 513 %v - (void) Re-use the first child's PMC (%0) as the result 514 of this operation. 515 516=cut 517 518.sub 'inline' :method 519 .param pmc value :optional 520 .param int has_value :opt_flag 521 .tailcall self.'attr'('inline', value, has_value) 522.end 523 524 525=item opattr(hash) 526 527Set a variety of C<PAST::Op> attributes based on entries 528in C<hash>. Typically C<hash> is an entry in the operator 529precedence table, and the attributes being set correspond 530to traits in the grammar. 531 532=cut 533 534.sub 'opattr' :method 535 .param pmc hash 536 537 $P0 = split ' ', "pasttype pirop inline lvalue" 538 $P1 = iter $P0 539 iter_loop: 540 unless $P1 goto iter_end 541 $S0 = shift $P1 542 $P2 = hash[$S0] 543 if null $P2 goto iter_loop 544 $P3 = find_method self, $S0 545 self.$P3($P2) 546 goto iter_loop 547 iter_end: 548.end 549 550 551=back 552 553=head2 PAST::Stmt 554 555C<PAST::Stmt> encapsulates sequence points within a program, particularly 556with respect to allocation and use of temporary registers. 557 558=head2 PAST::Stmts 559 560C<PAST::Stmts> is a container of C<PAST::Node> without any specific methods. 561 562=head2 PAST::Block 563 564C<PAST::Block> nodes represent lexical scopes within an abstract 565syntax tree, and roughly translate to individual Parrot subroutines. 566A C<PAST::Block> node nested within another C<PAST::Block> node 567acts like a nested lexical scope. 568 569If the block has a C<name> attribute, that becomes the name of 570the resulting Parrot sub, otherwise a unique name is automatically 571generated for the block. 572 573=over 4 574 575=item blocktype([STRING type]) 576 577Get/set the type of the block. The currently understood values 578are 'declaration', 'immediate', and 'method'. 'Declaration' indicates 579that a block is simply being defined at this point, while 580'immediate' indicates a block that is to be immediately 581executed when it is evaluated in the AST (e.g., the immediate 582blocks in Perl6 C<if>, C<while>, and other similar statements). 583 584=cut 585 586.namespace [ 'PAST';'Block' ] 587 588.sub 'blocktype' :method 589 .param pmc value :optional 590 .param int has_value :opt_flag 591 .tailcall self.'attr'('blocktype', value, has_value) 592.end 593 594 595=item closure([value]) 596 597Get/set the closure flag for the block to C<value>. If set, 598any block reference returned by the node is to a clone of the 599block that has captured the current lexical context. 600 601=cut 602 603.sub 'closure' :method 604 .param pmc value :optional 605 .param int has_value :opt_flag 606 .tailcall self.'attr'('closure', value, has_value) 607.end 608 609 610=item control([value]) 611 612Get/set the control exception handler for this block to C<value>. 613The exception handler can be any PAST tree. The special (string) 614value "return_pir" generates code to handle C<CONTROL_RETURN> exceptions. 615 616=cut 617 618.sub 'control' :method 619 .param pmc value :optional 620 .param int has_value :opt_flag 621 .tailcall self.'attr'('control', value, has_value) 622.end 623 624 625=item loadinit([past]) 626 627Get/set the "load initializer" for this block to C<past>. 628The load initializer is a set of operations to be performed 629as soon as the block is compiled/loaded. For convenience, 630requests to C<loadinit> autovivify an empty C<PAST::Stmts> 631node if one does not already exist. 632 633Within the load initializer, the C<block> PMC register is 634automatically initialized to refer to the block itself 635(to enable attaching properties, adding the block as a method, 636storing in a symbol table, etc.). 637 638=cut 639 640.sub 'loadinit' :method 641 .param pmc value :optional 642 .param int has_value :opt_flag 643 if has_value goto getset_value 644 $I0 = exists self['loadinit'] 645 if $I0 goto getset_value 646 $P0 = get_hll_global ['PAST'], 'Stmts' 647 value = $P0.'new'() 648 has_value = 1 649 getset_value: 650 .tailcall self.'attr'('loadinit', value, has_value) 651.end 652 653 654=item namespace([namespace]) 655 656Get/set the namespace for this block. The C<namespace> argument 657can be either a string or an array of strings. 658 659=cut 660 661.sub 'namespace' :method 662 .param pmc value :optional 663 .param int has_value :opt_flag 664 .tailcall self.'attr'('namespace', value, has_value) 665.end 666 667=item multi([multi]) 668 669Get/set the multi signature for this block. The C<multi> argument 670can be either a string or an array of strings. 671 672=cut 673 674.sub 'multi' :method 675 .param pmc value :optional 676 .param int has_value :opt_flag 677 .tailcall self.'attr'('multi', value, has_value) 678.end 679 680 681=item hll([hll]) 682 683Get/set the C<hll> for this block. 684 685=cut 686 687.sub 'hll' :method 688 .param pmc value :optional 689 .param int has_value :opt_flag 690 .tailcall self.'attr'('hll', value, has_value) 691.end 692 693 694=item loadlibs([lib1, lib2, ...]) 695 696Get/set the libraries to be loaded at startup. EXPERIMENTAL (not subject to 697deprecation policy, yet). 698 699=cut 700 701.sub 'loadlibs' :method 702 .param pmc libs :slurpy 703 .local int has_value 704 has_value = elements libs 705 .tailcall self.'attr'('loadlibs', libs, has_value) 706.end 707 708 709=item nsentry([nsentry]) 710 711Get/set the C<nsentry> for this block. 712 713=cut 714 715.sub 'nsentry' :method 716 .param pmc value :optional 717 .param int has_value :opt_flag 718 .tailcall self.'attr'('nsentry', value, has_value) 719.end 720 721 722=item symbol(name [, attr1 => val1, attr2 => val2, ...]) 723 724If called with named arguments, sets the symbol hash corresponding 725to C<name> in the current block. The HLL is free to select 726any symbol attributes desired, although the 'scope' attribute 727is typically used to assist with lexical scoping of PAST::Var 728nodes. 729 730If no named arguments are given, returns the current 731attribute hash for symbol C<name>. 732 733=cut 734 735.sub 'symbol' :method 736 .param string name 737 .param pmc attr :slurpy :named 738 .local pmc symtable 739 symtable = self['symtable'] 740 unless null symtable goto have_symtable 741 symtable = new 'Hash' 742 self['symtable'] = symtable 743 have_symtable: 744 .local pmc symbol 745 symbol = symtable[name] 746 if null symbol goto symbol_empty 747 unless attr goto attr_done 748 .local pmc it 749 it = iter attr 750 attr_loop: 751 unless it goto attr_done 752 $S0 = shift it 753 $P0 = attr[$S0] 754 symbol[$S0] = $P0 755 goto attr_loop 756 attr_done: 757 .return (symbol) 758 symbol_empty: 759 unless attr goto symbol_done 760 symtable[name] = attr 761 symbol_done: 762 .return (attr) 763.end 764 765 766=item symbol_defaults([attr1 => val1, attr2 => val2, ... ]) 767 768Set default attributes for non-existent symbols in the 769symbol hash (see C<symbol> above). If no named arguments 770are given, returns the default attribute hash itself. 771 772Currently we just use the '' entry of the symbol hash to 773store the default attributes, but it's probably not safe 774to rely on this behavior in the future. 775 776=cut 777 778.sub 'symbol_defaults' :method 779 .param pmc attr :slurpy :named 780 .tailcall self.'symbol'('', attr :flat :named) 781.end 782 783 784=item symtable([value]) 785 786Get/set the symbol table for the block. May be deprecated in 787favor of the C<symbol> method above. 788 789=cut 790 791.sub 'symtable' :method 792 .param pmc value :optional 793 .param int has_value :opt_flag 794 .tailcall self.'attr'('symtable', value, has_value) 795.end 796 797 798=item lexical([flag]) 799 800Get/set whether the block is lexically nested within 801the block that contains it. 802 803=cut 804 805.sub 'lexical' :method 806 .param pmc value :optional 807 .param int has_value :opt_flag 808 .tailcall self.'attr'('lexical', value, has_value, 1) 809.end 810 811 812=item compiler([name]) 813 814Indicate that the children nodes of this block are to be 815compiled using compiler C<name> instead of the standard 816PAST compiler. 817 818=cut 819 820.sub 'compiler' :method 821 .param pmc value :optional 822 .param int has_value :opt_flag 823 .tailcall self.'attr'('compiler', value, has_value) 824.end 825 826=item compiler_args() 827 828Specify named arguments to be passed to the compiler set 829through the compiler attribute. Not used if compiler is 830not set. 831 832=cut 833 834.sub 'compiler_args' :method 835 .param pmc value :named :slurpy 836 .local int have_value 837 have_value = elements value 838 .tailcall self.'attr'('compiler_args', value, have_value) 839.end 840 841=item subid([subid]) 842 843If C<subid> is provided, then sets the subid for this block. 844Returns the current subid for the block, generating a unique 845subid for the block if one does not already exist. 846 847=cut 848 849.sub 'subid' :method 850 .param pmc value :optional 851 .param int has_value :opt_flag 852 if has_value goto getset_value 853 $I0 = exists self['subid'] 854 if $I0 goto getset_value 855 value = self.'unique'() 856 .local pmc suffix 857 suffix = get_global '$!subid_suffix' 858 unless null suffix goto have_suffix 859 $N0 = time 860 $S0 = $N0 861 $S0 = concat '_', $S0 862 suffix = box $S0 863 set_global '$!subid_suffix', suffix 864 have_suffix: 865 value .= suffix 866 has_value = 1 867 getset_value: 868 .tailcall self.'attr'('subid', value, has_value) 869.end 870 871 872=item pirflags([pirflags]) 873 874Get/set any pirflags for this block. 875 876=cut 877 878.sub 'pirflags' :method 879 .param pmc value :optional 880 .param int has_value :opt_flag 881 .tailcall self.'attr'('pirflags', value, has_value) 882.end 883 884 885=item tempregs([tempregs]) 886 887Get/set whether this block is allowed to create a fresh 888bank of temporary registers. Default is disabled -- i.e., 889the block uses the same temporary register bank as its 890outer statement. 891 892=cut 893 894.sub 'tempregs' :method 895 .param pmc value :optional 896 .param int has_value :opt_flag 897 .tailcall self.'attr'('tempregs', value, has_value) 898.end 899 900 901.namespace [ 'PAST';'VarList' ] 902 903.sub 'bindvalue' :method 904 .param pmc value :optional 905 .param int has_value :opt_flag 906 .tailcall self.'attr'('bindvalue', value, has_value) 907.end 908 909 910=back 911 912=head1 AUTHOR 913 914Patrick Michaud <pmichaud@pobox.com> is the author and maintainer. 915Please send patches and suggestions to the Parrot porters or 916Perl 6 compilers mailing lists. 917 918=head1 HISTORY 919 9202006-11-20 Patrick Michaud added first draft of POD documentation. 9212007-11-21 Re-implementation with pdd26 compliance, compiler toolkit 922 923=head1 COPYRIGHT 924 925Copyright (C) 2006-2011, Parrot Foundation. 926 927=cut 928 929# Local Variables: 930# mode: pir 931# fill-column: 100 932# End: 933# vim: expandtab shiftwidth=4 ft=pir: 934