1. cp EmitRuleP5Ratchet into EmitRuleP6Rathet and prefix all subs with "use v5" 2. Use v6.pm to convert EmitRuleP6Ratchet into EmitRuleP5Ratchet 3. Port EmitRuleP6Ratchet by hand to MiniPerl 6 (without using P6 Rules or advanced OO stuff) ---- Here We Declare Grammar Engine is Bootstrapped ---- 4. Design AST for MP6 by taking Pugs.Exp and kill nodes, or take v6/AST and add nodes. 5. Write v6/Emit(MiniPerl6->Perl5) and redo step 3 to make an optimized PCR/EmitRuleP5Ratchet 6. Rewrite v6/Grammar/Expression.pm to port Yapp-dependent parts into a new precedence parser written in MP6 that utilizes <%foo> style tokens 7. Finalize Perl 6 AST by taking MP6 AST and expanding on it. 8. Convert all of v6/Grammar/* to MiniPerl6 and emitted to optimized Perl 5 code ---- Here We Declare Perl 6 Parser is Bootstrapped ---- 9. Port MO to MiniPerl6 10. Port Sub::Multi to MiniPerl6 11. Port builtin Value and Container classes to MiniPerl6 ---- Here We Declare Perl 6 Runtime is Bootstrapped ---- NB: The VM is responsible to provide coroutines, threads, sockets, etc etc; if it's missing in the VM, it's _not_ our job to emulate them by drastically change the emitting strategy to e.g. CPS. All Value/Container classes do is to bridge the native VM API with Perl 6 class/method API. sub foo (Int $x) {...} ################## use v6-alpha; my $x = (1,2,3); sub foo (@x) {...} foo($x); use v5; my $x = SomeInternalFunctionToMakeLockedArrayRef([1,2,3]); sub foo { my ($at_x) = @_; ... } foo($x); ################## # The Difference between MP6 and P6 is thus: - Only allow one feed of positional arguments - Allow interpolated positional arguments (|@x) - In Signature, disallow "is slurpy", "is optional", "is named" (*@bad) ($bad?) (:$bad) - But we do allow Hash and Array and Tree unpacking: sub foo ([$a, $b, $c, Tree $top ($left, $right)], {:$x, :$y}) { ... } foo([1, 2, 3], { x => 1, y => 2 }, Tree({ left => 1, right => 2}); # This compiles to: sub foo { my perl6::Tree $top; my ($a, $b, $c, $x, $y, $left, $right); ($a, $b, $c, $top) = @{$_[0]}; ($x, $y) = @{$_[1]}{'x', 'y'}; ($left, $right) = @{$_[0][3]}{'left', right'); ... } foo([1, 2, 3], { x => 1, y => 2 }); - As a consequence, object constructor calls must be written in conercion form: Foo({x => 1, y => 2}); # NOT Foo.new - Only allow item context - No laziness; all List are Seq - No subtyping (inheritance) or role mixins - No first-class Capture and Signature objects, which means no \$x nor :(foo) - No assignment, only bindings, but don't panic: $x := $x + 1; # name = IntOp(named(Int)) # $x = $x + 1 The reason is we have to eliminate one of them to avoid dealing with: $x := $y; $x = 123; Because assignment always involve box(unbox()), so emitting binding to Perl 5 is much more straightforward as $x is always just a Int in ($x := $x + 1), never SomePossiblyTiedScalarContainerType that needs to have special FETCH magic associated with it. Also it's inevitable with eliminating list context, because: ($x, $y, $z) := (1, 2); # compile-time error ($x, $y, $z) = (1, 2); # list-context-undef-fill that we don't want to deal with because infix:<=> almost always imply slurpiness with LHS is not a simple scalar, eliminating it is consistent with eliminating list context. - Allow Type annotations. Preserve them Perl 5 emitted code using simple Typed vars: # MiniPerl6 my Int $x; my perl5:CGI $x; # Compiled Perl 5 my perl6::Int $x; my CGI $x; However, the compiler adds no extra assertions so types never slows programs down in MiniPerl6 land. - Closures, but no coroutines nor continuations - Declarators: my/state/has/constant. We don't have "our", and we don't have $Q::Var - Hypotheticals: temp - Fatal is always in effect; "fail" fails immediately - Closed grammatical categories and precedence levels - No macros; no BEGIN blocks! - No multis (for now; may revisit) # Not Imported In MiniPerl6 macro statement_control: {...}