
Planet Parrot is an aggregation of select Parrot related blogs. You won't find anything about birdseed or molting here. The list of contributors changes periodically. You might also like to visit Planet Perl or Planet Perl Six for more focus on their respective topics.
Planet Parrot provides its aggregated feeds in Atom, RSS 2.0, and RSS 1.0, and its blogroll in FOAF and OPML
There is life on other planets. A heck of a lot, considering the community of Planet sites forming. It's the Big Bang all over again!
This site is powered by Venus and maintained by Robert and Ask.

Planet Parrot is licensed under
a Creative
Commons Attribution-Noncommercial-Share Alike 3.0 United States
License. Individual blog posts and source feeds are the
property of their respective authors, and licensed
independently.
[This announcement was made last week on rakudo.org -- I'm reposting to use.perl.org so it will show up in the various Perl aggregators. --Pm]
On behalf of the Rakudo and Perl 6 development teams, I'm happy to announce the August 2010 release of "Rakudo Star", a useful and usable distribution of Perl 6. The tarball for the August 2010 release is available from http://github.com/rakudo/star/downloads.
Rakudo Star is aimed at "early adopters" of Perl 6. We know that it still has some bugs, it is far slower than it ought to be, and there are some advanced pieces of the Perl 6 language specification that aren't implemented yet. But Rakudo Perl 6 in its current form is also proving to be viable (and fun) for developing applications and exploring a great new language. These "Star" releases are intended to make Perl 6 more widely available to programmers, grow the Perl 6 codebase, and gain additional end-user feedback about the Perl 6 language and Rakudo's implementation of it.
In the Perl 6 world, we make a distinction between the language ("Perl 6") and specific implementations of the language such as "Rakudo Perl". The August 2010 Star release includes release #32 of the Rakudo Perl 6 compiler [1], version 2.7.0 of the Parrot Virtual Machine [2], and various modules, documentation, and other resources collected from the Perl 6 community.
This release of Rakudo Star adds the following features over the previous Star release:
* Nil is now undefined
* Many regex modifiers are now recognized on the outside of regexes
* Mathematic and range operations are now faster (they're still slow, but they're significantly faster than they were in the previous release)
* Initial implementations of .pack and .unpack
* MAIN can parse short arguments
* Removed a significant memory leak for loops and other repeated blocks
This release (temporarily?) omits the Config::INI module that was included in the 2010.07 release, as it no longer builds with the shipped version of Rakudo. We hope to see Config::INI return soon.
There are some key features of Perl 6 that Rakudo Star does not yet handle appropriately, although they will appear in upcoming releases. Thus, we do not consider Rakudo Star to be a "Perl 6.0.0" or "1.0" release. Some of the not-quite-there features include:
* nested package definitions
* binary objects, native types, pack and unpack
* typed arrays
* macros
* state variables
* threads and concurrency
* Unicode strings at levels other than codepoints
* pre and post constraints, and some other phasers
* interactive readline that understands Unicode
* backslash escapes in regex character classes
* non-blocking I/O
* most of Synopsis 9
* perl6doc or pod manipulation tools
In many places we've tried to make Rakudo smart enough to inform the programmer that a given feature isn't implemented, but there are many that we've missed. Bug reports about missing and broken features are welcomed.
See http://perl6.org/ for links to much more information about Perl 6, including documentation, example code, tutorials, reference materials, specification documents, and other supporting resources. An updated draft of a Perl 6 book is available as in the release tarball.
The development team thanks all of the contributors and sponsors for making Rakudo Star possible. If you would like to contribute, see http://rakudo.org/how-to-help, ask on the perl6-compiler@perl.org mailing list, or join us on IRC channel #perl6 on freenode.
Rakudo Star releases are created on a monthly cycle or as needed in response to important bug fixes or improvements. The next planned release of Rakudo Star will be on September 28, 2010.
The Google Summer of Code pencils-down date was last Monday. GSoC is now over, but I don't plan to stop working on my project.
The initial goals listed in my project proposal were:
INIT { pir::load_bytecode("pla_nqp.pbc"); }
my $A := NumMatrix2D.new();
$A.initialize_from_args(2, 2, 1, 2.0, "3", 4);
$A.transpose();
pir::say("A: " ~ $A);
my $B := ComplexMatrix2D.new();
$B.initialize_from_array(2, 2, [1, 2.0, "3+3i", "7+5i"]);
$B.conjugate();
pir::say("B: " ~ $B);
my $C := PMCMatrix2D.new();
$C.fill(4.4, 2, 2);
pir::say("C: " ~ $C);
my $D := $B.gemm(0.5, $A, $B, "1+2i", $C);
pir::say("D: " ~ $D);
t/sanity.t .............................................. ok
t/pmc/pmcmatrix2d.t ..................................... ok
t/pmc/nummatrix2d.t ..................................... ok
t/pmc/complexmatrix2d.t ................................. ok
t/methods/nummatrix2d/convert_to_complex_matrix.t ....... ok
t/methods/nummatrix2d/row_scale.t ....................... ok
t/methods/nummatrix2d/get_block.t ....................... ok
t/methods/nummatrix2d/mem_transpose.t ................... ok
t/methods/nummatrix2d/convert_to_number_matrix.t ........ ok
t/methods/nummatrix2d/initialize_from_args.t ............ ok
t/methods/nummatrix2d/row_swap.t ........................ ok
t/methods/nummatrix2d/iterate_function_inplace.t ........ ok
t/methods/nummatrix2d/fill.t ............................ ok
t/methods/nummatrix2d/initialize_from_array.t ........... ok
t/methods/nummatrix2d/iterate_function_external.t ....... ok
t/methods/nummatrix2d/transpose.t ....................... ok
t/methods/nummatrix2d/item_at.t ......................... ok
t/methods/nummatrix2d/gemm.t ............................ ok
t/methods/nummatrix2d/row_combine.t ..................... ok
t/methods/nummatrix2d/resize.t .......................... ok
t/methods/nummatrix2d/convert_to_pmc_matrix.t ........... ok
t/methods/nummatrix2d/set_block.t ....................... ok
t/methods/complexmatrix2d/convert_to_complex_matrix.t ... ok
t/methods/complexmatrix2d/row_scale.t ................... ok
t/methods/complexmatrix2d/get_block.t ................... ok
t/methods/complexmatrix2d/mem_transpose.t ............... ok
t/methods/complexmatrix2d/convert_to_number_matrix.t .... ok
t/methods/complexmatrix2d/initialize_from_args.t ........ ok
t/methods/complexmatrix2d/row_swap.t .................... ok
t/methods/complexmatrix2d/iterate_function_inplace.t .... ok
t/methods/complexmatrix2d/fill.t ........................ ok
t/methods/complexmatrix2d/initialize_from_array.t ....... ok
t/methods/complexmatrix2d/conjugate.t ................... ok
t/methods/complexmatrix2d/iterate_function_external.t ... ok
t/methods/complexmatrix2d/transpose.t ................... ok
t/methods/complexmatrix2d/item_at.t ..................... ok
t/methods/complexmatrix2d/gemm.t ........................ ok
t/methods/complexmatrix2d/row_combine.t ................. ok
t/methods/complexmatrix2d/resize.t ...................... ok
t/methods/complexmatrix2d/convert_to_pmc_matrix.t ....... ok
t/methods/complexmatrix2d/set_block.t ................... ok
t/methods/pmcmatrix2d/convert_to_complex_matrix.t ....... ok
t/methods/pmcmatrix2d/get_block.t ....................... ok
t/methods/pmcmatrix2d/mem_transpose.t ................... ok
t/methods/pmcmatrix2d/convert_to_number_matrix.t ........ ok
t/methods/pmcmatrix2d/initialize_from_args.t ............ ok
t/methods/pmcmatrix2d/iterate_function_inplace.t ........ ok
t/methods/pmcmatrix2d/fill.t ............................ ok
t/methods/pmcmatrix2d/initialize_from_array.t ........... ok
t/methods/pmcmatrix2d/iterate_function_external.t ....... ok
t/methods/pmcmatrix2d/transpose.t ....................... ok
t/methods/pmcmatrix2d/item_at.t ......................... ok
t/methods/pmcmatrix2d/resize.t .......................... ok
t/methods/pmcmatrix2d/convert_to_pmc_matrix.t ........... ok
t/methods/pmcmatrix2d/set_block.t ....................... ok
PASSED 356 tests in 55 files
I proposed a pretty ambitious Google Summer of Code project this year. Although I didn't manage to do everything I hoped, I did manage to get a useful subset of threading functionality working in the gsoc_threads branch. In this blog post I will describe what I have working and what more needs to be done.
Never worry about theory as long as the machinery does what it's supposed to do.
—Robert A. Heinlein
On behalf of the Parrot team, I'm proud to announce Parrot 2.7.0 "Australian King"
Parrot is a virtual machine aimed at running all dynamic languages.
Parrot 2.7.0 is available on Parrot's FTP site, or follow the download instructions. For those who would like to develop on Parrot, or help develop Parrot itself, we recommend using Subversion on our source code repository to get the latest and best Parrot code.
SHA digests for this release are:
INIT { pir::load_bytecode("pla.pbc"); }
That file loads the PLA binary library, stores a global reference to the library, and registers the type names with P6metaclass. That done, you can start writing more natural-looking programs in NQP. I updated the Gaussian Elimination example I wrote a few weeks ago to use this new bootstrap file (and some new methods I added), which means the example can now run without Kakapo or any other dependencies.method test_METHOD_iterate_function_inplace_TRANSPOSE() {
my $m := self.fancymatrix2x2();
$m.transpose();
my $n := self.matrix2x2(self.fancyvalue(0) * 2, self.fancyvalue(2) * 2,
self.fancyvalue(1) * 2, self.fancyvalue(3) * 2);
my $sub := -> $matrix, $value, $x, $y {
return ($value * 2);
};
$m.iterate_function_inplace($sub);
assert_equal($m, $n, "external iteration does not respect transpose");
}
my $sub := -> $matrix, $value, $x, $y {
return ($value * 2);
};
my $sub := sub ($matrix, $value, $x, $y) {
return ($value * 2);
};
Problem solved, and now more tests are legitimately passing.I’ve been spending the past few weeks cleaning up and finalising the interface used to instrument Parrot. So here’s a recap of the major changes:
An example of usage will be as follows:
# Instrument the ops.
$P0 = new ['Instrument']
$P1 = $P0.'instrument_op'()
$P1.'callback'('some_sub')
$P1.'inspect'('op_name')
$P0.'attach'($P1)
with similar usages for the other methods listed above. Instrument.pmc also takes over the function of actually calling the callbacks, a function previously handled by EventDispatcher. For this task, it has 3 methods:
whose functions are rather self explanatory.
.sub pre
# This is called before execution.
# ...
.param pmc data
.param pmc instrument
.param pmc probe
$P0 = get_global 'post'
.return($P0)
.end
.sub post
# This is called after execution.
# ...
.param pmc data
.param pmc instrument
.param pmc probe
.end
Along with this change, all callbacks are now passed 3 parameters, with data being a PMC that is an instance of InstrumentOp for op probes or a Hash for other kinds of probes, instrument being the Instrument instance itself and probe the instance that the callback associated with.
With all that done, I’m now focusing on documentation and dealing with the bugs I’ve uncovered in my code, some new, some old and some not yet known.
Now that I have the basic green threads (Task) API basically working, it's time to start mixing in OS threads. I plan to do that in two steps: First I'm going to use OS threads to solve the key issue with the green threads implementation - blocking IO. The result of this will be basically equivilent to CPython threads-with-GIL. The second step - real parallel thread execution - will have to wait for after GSoC pencils down.
I spent this last week working on Tree::Optimizer (and getting distracted by Rakudo *).
I've got the functionality described in my blog post last week mostly finished. The only thing remaining is making sure that recursive passes correctly handle nulls, which I'm about to work on.
The Google Summer of Code is almost over. Next Monday is the "suggested 'pencils down'" date. The following Monday is the "firm 'pencils down'" date. After that are final evaluations.
Here's my plan for the remainder of GSoC:
I reached the midterms mostly as scheduled, and NFG is pretty much feature complete now. There's still some stuff to do here and there, but the 'big ticket' items are done. So, I have been looking at what needs to be done before the gsoc_nfg branch can be merged back into trunk. And that means giving a hard look at all of the places where I've cut corners and see if they can be made better. It's mostly minor stuff, like leaving out a cast, or not paying attention to const mismatches in a few places. Most of it is just a matter of code cleanup. Until you see the extra pointer I added to string headers.
On behalf of the Rakudo and Perl 6 development teams, I'm happy to announce the July 2010 release of "Rakudo Star", a useful and usable distribution of Perl 6. The tarball for the July 2010 release is available from http://github.com/rakudo/star/downloads.
Rakudo Star is aimed at "early adopters" of Perl 6. We know that it still has some bugs, it is far slower than it ought to be, and there are some advanced pieces of the Perl 6 language specification that aren't implemented yet. But Rakudo Perl 6 in its current form is also proving to be viable (and fun) for developing applications and exploring a great new language. These "Star" releases are intended to make Perl 6 more widely available to programmers, grow the Perl 6 codebase, and gain additional end-user feedback about the Perl 6 language and Rakudo's implementation of it.
In the Perl 6 world, we make a distinction between the language ("Perl 6") and specific implementations of the language such as "Rakudo Perl". "Rakudo Star" is a distribution that includes release #31 of the Rakudo Perl 6 compiler [1], version 2.6.0 of the Parrot Virtual Machine [2], and various modules, documentation, and other resources collected from the Perl 6 community. We plan to make Rakudo Star releases on a monthly schedule, with occasional special releases in response to important bugfixes or changes.
Some of the many cool Perl 6 features that are available in this release of Rakudo Star:
There are some key features of Perl 6 that Rakudo Star does not yet handle appropriately, although they will appear in upcoming releases. Thus, we do not consider Rakudo Star to be a "Perl 6.0.0" or "1.0" release. Some of the not-quite-there features include:
In many places we've tried to make Rakudo smart enough to inform the programmer that a given feature isn't implemented, but there are many that we've missed. Bug reports about missing and broken features are welcomed.
See http://perl6.org/ for links to much more information about Perl 6, including documentation, example code, tutorials, reference materials, specification documents, and other supporting resources.
Rakudo Star also bundles a number of modules; a partial list of the modules provided by this release include:
These are not considered "core Perl 6 modules", and as module development for Perl 6 continues to mature, future releases of Rakudo Star will likely come bundled with a different set of modules. Deprecation policies for bundled modules will be created over time, and other Perl 6 distributions may choose different sets of modules or policies. More information about Perl 6 modules can be found at http://modules.perl6.org.
Rakudo Star also contains a draft of a Perl 6 book -- see "docs/UsingPerl6-draft.pdf" in the release tarball.
The development team thanks all of the contributors and sponsors for making Rakudo Star possible. If you would like to contribute, see http://rakudo.org/how-to-help, ask on the perl6-compiler@perl.org mailing list, or join us on IRC #perl6 on freenode.
Rakudo Star releases are created on a monthly cycle or as needed in response to important bug fixes or improvements. The next planned release of Rakudo Star will be on August 24, 2010.
Well, the past two weeks haven’t been very productive. Other than the usual addition of tests, I’m slightly stuck on how I’m approaching instrumenting methods and this post is meant to be a sounding board.
In Parrot, methods of a class can be defined in a few ways. First is by defining a sub in a namespace with the same name as the class and annotating the sub with :method. Second is through the use of the addmethod op. Lastly, it seems all PMCs are classes and PMCs can define methods in C. So at the very least, methods can be either Sub or NCI instances (or rather, invokables), and through the use of the addmethod op, an invokable can be a method to more than one class. So the past week I added support to instrument methods of a class, raising an event whenever any instances of the class invokes the method. What I did not foresee was that due to the ability to “share” methods, an event would also be raised for another class that did not instrument the “shared” method. And this unintended consequence is further exacerbated when the instances themselves are instrumented (I added the ability to instrument on a per-object basis too, although it seems like it’s not working too well now).
So a step back to reflect is in order. I would need to:
It sounds like a plan, albeit not very fleshed out. Time to find out if it works.
After a false start earlier this week, I've begun implementing something like LLVM's PassManager. It can be found in the pass-manager branch of my project's git repository.
Today, I'm going to talk about adding optimizations to compilers using my GSoC project without Tree::Optimizer and with it. Note that most of the features of Tree::Optimizer that I describe here are not yet implemented.
Now that I have green threads basically working with the API functionality I discussed in my last blog post, I've been working on coming up with tests/examples that clearly demonstrate both how green threads in Parrot work and that they work as advertised. With that goal in mind, this blog post is about a classic concurrent programming example: The Sieve of Eratosthenes.
What we call the beginning is often the end And to make an end is to make a beginning. The end is where we start from. —T. S. Eliot, Four Quartets
On behalf of the Parrot team, I'm happy to announce Parrot 2.6.0
"Red-rumped." Parrot (http://parrot.org/) is a virtual machine aimed
at running all dynamic languages.
Parrot 2.6.0 is available on Parrot's FTP site, or follow the
download instructions at http://parrot.org/download. For those who would like to
develop on Parrot, or help develop Parrot itself, we recommend using Subversion
This has been an uneventful week in my GSoC work.
Parrot's 2.6 release is Tuesday, and I've taken on the task of updating Squaak to modern NQP-rx prior to it. Because of that and my GSoC midterm evaluations, I haven't spent much time hacking on Tree::Pattern or on optimizations using it this week. I plan to finish working on Squaak tonight or tomorrow, commit my fixes to trunk, and finally get back to work on my GSoC project. I'm a little behind schedule now because of that, but I plan to work hard on optimization for the rest of GSoC.
Well, on use.perl.org, anyway. I'd like to thank those who run this place for doing so, as it's been the place I've blogged about my Perl 6 stuff for the last couple of years. However, I've found the user experience of WordPress a lot more enjoyable - it was great for the Perl 6 Advent Calendar - and figure I'll blog more if I more enjoy doing so.
So, from now you'll be able to read my Rakudo news and other Perl 6 related ramblings from my shiny new blog. For those reading through Planet Six, no action required - I'll arrange for my new blog to be aggregated there.
See you over there.
Now that I have pre-emptive task switching between green threads basically working, I need to figure out what the API to interact with them wants to look like. Additionally, I need to clean up this scheduler thing that I've mauled in order to make the API and terminology consistent.
Done this week:
.sub '' :anon :load :init
load_bytecode 'Instrument/InstrumentLib.pbc'
.end
.sub main :main
.param pmc args
$S0 = shift args
$P0 = new ['Instrument']
$P2 = get_hll_global ['Instrument';'Event'], 'Class'
$P1 = $P2.'new'()
$P1.'callback'('class_handler')
$P1.'inspect_class'('Sub')
$P1.'inspect_vtable'('invoke')
$P0.'attach'($P1)
$S0 = args[0]
$P0.'run'($S0, args)
.end
.sub class_handler
.param pmc data
$I0 = data['line']
$P0 = data['parameters']
$I1 = $P0
$P1 = $P0[1]
print 'Line: '
print $I0
print ' with '
print $I1
say ' parameters.'
print 'address: '
say $P1
.end
test-script.pir
.sub main :main
test()
say 'Done'
.end
.sub test
say 'Invoke!'
.end
Which yields the following output:
Line: 3 with 2 parameters. address: 0 Line: 25 with 2 parameters. address: 1006b0050 Invoke! Done
Along the way, I discovered a small bug in src/pmc/pointer.pmc, in line 162:
return Parrot_sprintf_c(INTERP, "%s", PARROT_POINTER(SELF)->pointer);
Subtle, innocuous looking code, until you realise that it’s supposed to print an address, not a string.
What did not get done was most of last week’s goals. I got sidetracked into refactoring and ended up not doing the goals. Furthermore, I found out that I need to take into account inheritance when instrumenting the vtable. As an example, EventHandler extends Sub, so when I instrument Sub’s vtable, the stub entries got imported into EventHandler, leading to fireworks that I least expected. Ah well, at least while figuring it out I discovered how to use XCode’s debugger on parrot. So long command line gdb! And good riddance.
Goals this week will be to complete last week’s goals, since this week, week 8 is supposed to be code review, and most of that got covered last week.
My main goals this week have been getting a tail-call elimination optimization to work in NQP-rx and moving my GSoC project to an external repository to make it easier for other projects to use it. Both of these goals have been successful. You can find the tail-call elimination optimization here. My GSoC project can now be found on github or installed via Plumage with ./plumage install tree-optimizations.
Done the past week:
.sub '' :anon :init :load
load_bytecode 'Instrument/InstrumentLib.pbc'
.end
.sub 'main' :main
.param pmc args
$S0 = shift args
# Create an Instrument::Event::GC object.
$P0 = get_hll_global ['Instrument';'Event'], 'GC'
$P1 = $P0.'new'()
$P1.'callback'('do_gc_mark_callback')
$P1.'inspect'('do_gc_mark')
$P2 = new ['Instrument']
$P2.'attach'($P1)
$S0 = args[0]
$P2.'run'($S0, args)
.end
.sub 'do_gc_mark_callback'
.param pmc data
$I0 = data['line']
$S0 = data['file']
$S1 = data['type']
print '('
print $S1
print ') at line '
print $I0
print ' in file '
say $S0
.end
gc_sample.pir:
.sub main :main
meh()
sweep 1
collect
say "End main"
.end
.sub meh
$P0 = new ['Hash']
$I0 = 0
LOOP:
$P0 = new ['String']
inc $I0
unless $I0 > 1 goto LOOP
sweep 1
collect
say "End"
.end
Running the command: “./parrot gc_do_mark_sweep.pir gc_sample.pir” will yield the following output:
(do_gc_mark) at line 19 in file gc_sample.pir End (do_gc_mark) at line 4 in file gc_sample.pir End main
So refactoring and changing the internals of EventDispatcher came as a natural consequence of that. For what I wanted to do, I found that splitting the event type into 3 parts, namely Category, Group and Specific would do nicely for all cases that I could think of. To give an example, ‘GC::allocate::allocate_pmc_header’. If I’m only interested in the specific event, I can just register a handler for ‘GC::allocate::allocate_pmc_header’. If I’m only interested in events in the ‘allocate’ group, I can register a handler for ‘GC::allocate’. Similarly, for all GC events, I can register a handler for ‘GC’.
Thinking ahead for what I want to do in week 7, this dovetails nicely with Classes. As an example, ‘Class::ResizablePMCArray::push’, ‘Vtable::ResizablePMCArray::push_pmc’. On hindsight, maybe refactoring it again to handle more levels would be better, as looking above for the Vtable example, adding 1 more level would allow catching of push_* vtable entries as a group, ie. ‘Vtable::ResizablePMCArray::push::push_pmc’.
vtable_push_pmc.pir
.sub '' :anon :load :init
load_bytecode 'Instrument/InstrumentLib.pbc'
.end
.sub main :main
.param pmc args
$S0 = shift args
$P0 = new ['Instrument']
$P1 = new ['InstrumentVtable'], $P0
$P2 = $P0['eventdispatcher']
# Register a handler
$P3 = get_global 'class_handler'
$P2.'register'('Class', $P3)
# Instrument push_pmc of class ResizablePMCArray
$P1.'attach_to_class'('ResizablePMCArray')
$P1.'insert_vtable_hook'('push_pmc')
$S0 = args[0]
$P0.'run'($S0, args)
.end
.sub class_handler
.param pmc data
$I0 = data['line']
print 'Line: '
say $I0
.end
vtable_test.pir
.sub main :main
$I0 = 0
LOOP:
if $I0 > 5 goto DONE
$P0 = new ['ResizablePMCArray']
$P1 = box $I0
push $P0, $P1
inc $I0
goto LOOP
DONE:
say 'Done'
.end
Running the command: “./parrot vtable_push_pmc.pir vtable_test.pir” yields the following output:
Line: -1 Line: 8 Line: 8 Line: 8 Line: 8 Line: 10 Line: 10 Line: 10 Line: 10 Line: 10 Line: 10 Done
Since I have not implemented the appropriate Instrument::Event class for Vtable events, the code in ‘vtable_push_pmc.pir’ is rather lower-level than I would have preferred. But it will do for now.
With that, this week I would like to:
Last week, I generalized PAST::Pattern to Tree::Pattern. This week, I put that to use.
The Perl 6 design team met by phone on 30 June 2010. Allison, Patrick, and chromatic attended.
Allison:
Patrick:
Allison:
Patrick:
List and Iterator types for the #30 releaseAssociative and Positional rolesNil; it's defined, not undefined$! $*ARGFILES c:
I've spent my Parrot time for the last week working on something I call Alarms. Alarms are like Timers, except instead of specifying a delay the user specifies when they want the Alarm to fire. This is a pretty simple concept. If the Scheduler did what I wanted, I'd be done long ago.
It has been a very exciting few weeks in the Perl 6 world with regard to database access. mberends++ just wrote a nice blog post about how Perl 6 support for DBI is ramping up with work on MiniDBI (formerly FakeDBI). Multiple developers recently made great progress on PostgreSQL drivers and have been improving the Parrot interface to libpq, Pg.pir .
I have also been dutifully hacking on PL/Perl6, which embeds Rakudo Perl 6 into your PostgreSQL datbase via PL/Parrot, and just recently merged the plperl6 branch, which adds the first basic support for PL/Perl 6. Here is how it currently works:
To tell PL/Parrot that you would also like PL/Perl6, you set the environment variable PERL6PBC to the full path of perl6.pbc like so:
export PERL6PBC=/Users/leto/git/rakudo/parrot_install/lib/2.5.0-devel/languages/perl6/perl6.pbc
A PBC file is Parrot bytecode, and the perl6.pbc file basically bundles all of Rakudo Perl 6 into a single file. You can play around with the Rakudo Perl 6 REPL by running:
$ parrot $PERL6PBC
which is pretty much the exact same thing as running the perl6 binary in your $PATH.
When you compile PL/Parrot with the $PERL6PBC environment variable set, it automatically creates a separate Parrot interpreter with the perl6.pbc bytecode loaded, so that Perl 6 code can be executed.
To run PL/Parrot tests, you type "make test". You can also do this the PostgreSQL way with "make installcheck", which will run the tests and verify that the output matches a certain, known output. "make tests" just generates the TAP output.
Currently PL/Perl 6 tests are not run by default, they have their own Makefile target: test_plperl6 This is what the output of "make test_plperl6" looks like currently, on commit 44a985f123 of the perl6_args branch.
We run a total of 9 tests, 6 of which correctly run Perl 6 code and pass. You will notice that all the failing tests are relating to passing arguments into Rakudo from PostgreSQL, which is what I am currently trying to get to work. Currently I am passing a Parrot ResizablePMCArray of the arguments to a Rakudo function and executing it, but the function can't seem to see it. My guess is that Rakudo wants native datatypes and not Parrot datatypes. If you know how to create Rakudo datatypes from PIR, please let me know :) I promise you will -Ofun.
What does PL/Perl 6 look like? Here is a nice example of a PL/Perl6 function which calculates the sum of all Fibonacci numbers <= 100:
CREATE FUNCTION test_fibonacci_plperl6(integer) RETURNS int LANGUAGE plperl6 AS $$
[+] (1, 1, *+* ... 100)
$$;
If you are interested in hacking on PL/Perl 6, PL/Parrot or anything related, come join us in #plparrot on freenode, join the mailing list and fork us on github !
Due to unforseen personal circumstances, I did not manage to do much this week. However, I did manage to finish instrumenting the GC subsystem. So, here’s a short recap:
Each stub does the following,
Furthermore, in addition to inspecting each individual GC_Subsystem entry, I have also grouped the entries into the following categories: allocate, reallocate, free, administration. This grouping is based on what each function is supposed to do, using the Mark and Sweep GC as the basis. The leftover functions are grouped under administration.
What is not done yet however is the interface for these events, which I’m currently in the midst of. My current problem is getting the EventDispatcher to recognise and dispatch to catchall event handlers, such as Instrument::Event::GC::*. This is needed as for example, wanting to only instrument the PMC related entries of the GC_Subsystem. What I have currently doesn’t allow this. So a rework is in order.
This week I’ll be continuing on the following tasks:
After taking some time off GSoC work to pay the parrot Upgrade Tax that plumage had accumulated in the months since 2.3 shipped, and watching the World Cup this hasn't been an awfully productive week, code-wise. However, there's been quite a bit of work and planing done anyway.
This took longer than I expected, but the draft of the Modern Perl book is available for review. I'm especially interested in hearing from people who don't consider themselves expert Perl 5 programmers. The goal of the book is to explain how Perl 5 works (and how to write Perl 5 effectively) to help novices become adepts.
Earlier this summer, when I was considering what sort of interface would be best for the PAST pattern matching and transformation I've been building, Bacek suggested an XPath-like syntax. XPath is, nominally, a language for pattern matching on XML, but it is applicable to any tree-like data structure where each node may have both attributes and children. It's a general-purpose tree-matching language.
The Perl 6 design team met by phone on 16 June 2010. Larry, Allison, Patrick, Will, and chromatic attended.
Larry:
TOP (again), and explained how parsing is initiated and how it actually works...) now picks a monotonic function when using single characters as endpointsprotos as well as onlyssub() declarationAllison:
Patrick:
Associative and Positional rolesc:
The Perl 6 design team met by phone on 09 June 2010. Larry, Allison, Patrick, and chromatic attended.
Larry:
gather/take gimme5's limitations.<_from> and .<_pos> hash lookups to using .from and .pos accessorsEXPR out of STD to make it generally available to any grammar wanting operator precedence$< detection have a longer token to avoid confusion with match variablesinfix_circumfix_meta_operator >>R~<< correctly, or at least dwimmilyprintf formats like "%{$count}s" /m and /s with the opposite semanticstermish now localizes $*MULTINESS in its scope so that inner declarations aren't accidentally multifiedpackage Foo; as a Perl 5 constructAllison:
Patrick:
exit opcode** quantifier in regexes to understand surrounding whitespacec:
If we track HEAD the we'll run on 2.6 when it's released. We branch on the release day and do whatever 'release engineering' we need to do on the branch and tag a release when we're done.
In my work on Timers, I've concluded that the scheduler really is the right place for scheduling things (who would have guessed?). How the scheduler *should* work is described in pdd25. How the scheduler actually works is a bit different, and how I want the scheduler to work to implement green threads is a bit different from that...
The Perl 6 design team met by phone on 02 June 2010. Larry, Allison, Patrick, Will, and chromatic attended.
Larry:
viv instead of gimme5 Blobs to simply be immutable Bufs, with similar generic characteristicsblob typesBEGIN and use, since those can't wait for end of file$*GOAL variable only as informative, never as a "stopper"<stopper> rule for $*GOAL if necessary$*GOAL viv work besides thatAllison:
Will:
Allison:
getstderr and related opcodesWill:
Patrick:
c:
Progress this week was not bad. To recap, here’s what I got done this week:
Additionally, in the process of fleshing out the InstrumentOp dynpmc, I also removed a todo item with regards to the special ops which have variable arguments (set_args_pc, get_results_pc, get_params_pc, set_returns_pc), which up until then, were simply ignored.
With reference to the previous post, I did not manage to complete the following two tasks:
I hope to be able to complete these two tasks by Thursday (June 24th).
For this week, I would like to complete the following:
The Perl 6 design team met by phone on 26 May 2010. Larry, Allison, Patrick, Will, and chromatic attended.
Larry:
:() syntax is now always signaturefoofix:[...] as the general op form instead of foofix:(...) :nth and :x :nth() now only ever takes a monotonically increasing list!= and ne if could terminate one statement and start another\s etc and reject \u etc:() on name extension as a signature always, never as a categoricalAllison:
Will:
Patrick:
eval c:
As many of you know, last summer we announced that we would be releasing a "usable release of Rakudo Perl 6" to be called "Rakudo Star" in the second quarter of 2010. We later refined our target release date to be April 2010.
Until March of this year we were well on track to meet the April 2010 release date, but then I had an family medical emergency that took me away from Perl 6 development. As a result of my situation, the Rakudo and Perl 6 team met online in early March and decided that an April release date would be unrealistic, and we instead focused our efforts on trying to make a June release for Rakudo Star, to keep with our original "second quarter 2010" goal.
Ultimately it ended up being twelve weeks before I was able to return to active Perl 6 development (i.e., late May). During my absence the others on the Rakudo and Perl 6 team made incredible progress on Rakudo Perl 6; I think their progress shows that a truly capable (and growing) team of developers has coalesced around Rakudo Perl. Thanks to their efforts, as of late May the compiler had nearly everything we identified as critical for Rakudo Star in the ROADMAP, with only a few key features blocking on my personal participation. We therefore felt we still had a good likelihood of meeting the June 2010 target, and continued to work with that goal in mind.
As part of planning this week's Parrot and Rakudo releases, we all met online to solidify our plans for the Rakudo Star release. After much discussion, we decided that although we could likely make some sort of Rakudo Star release in June, there was too much risk that releasing in June would fall well short of our vision of what we want Rakudo Star to be.
Therefore, we've decided to to let the release date slip one more month and release Rakudo Star not later than July 29, 2010. We are firmly committed to the July 29 date; whatever we have available then, that's what we release. I know that another delay will be frustrating to many (it is very frustrating to me), and that some will undoubtedly cite this delay as yet more "evidence" that there will never be a release of Perl 6. But given the circumstances, I think we feel that we promote Perl 6 better by moving the release date by a month than we would by releasing something less than our vision.
For those who might claim that we should "release early", we are still continuing to make regular monthly compiler releases. The most recent release (#30, "Kiev") comes with a lot of improvements over previous releases, and I truly expect the next release (#31, "Atlanta") to continue the trend. As always, we continue to invite people to try out the compiler releases and to visit the Perl 6 website to see what Perl 6 is already doing today.
Finally, on a personal note, my wife and I sincerely appreciate the ongoing support, prayers, and understanding we have received from the Perl community (and especially the Rakudo and Perl 6 teams) during these difficult times. While my wife is still not "out of the woods" yet, things are far better now than they were in the Spring, and we continue to work towards and pray for her full recovery.
More details about the Rakudo Star release will be forthcoming over the next couple of weeks.
Pm
typedef struct _array {
int length;
int *values;
} array;
void push( array *ary, int x) {
array->length++;
realloc(array->values, newlen * sizeof(int));
array->values[array->length - 1] = x;
}
This isn't nearly as contrived an example as it may seem initially, though I purposefully made the code a little bit naive. It's worth noting here that the idea of a structure which contains both an array and the integer length of that array is very common. It's how Parrot implements it's STRING type and several of its array PMC types as well. In fact, the push_int VTABLE method for the ResizableIntegerArray PMC probably looks extremely similar to this example code.foo = i++;This seems pretty simple, but in fact it is not. This line of code requires several assembly language instructions, especially when we are talking about a non-optimized build:
Mutex *m;The power in this code is that the AQUIRE_MUTEX() function will attempt to gain ownership of the mutex, and will wait indefinitely for the mutex to become available if some other thread already owns it. ACQUIRE_MUTEX is like waving your arms in the air, shouting "I'm open" until the current ball carrier passes the ball to you. Until you get the ball, you just have to stand with your arms in the air until you get it. Because of that behavior, no two threads can enter the same critical section, assuming of course that the programmer (you) has properly protected that critical section with the mutex. Keep in mind that there is no intrinsic property of the critical section itself that prevents multiple threads from running it simultaneously and corrupting data. The exclusion comes from the proper and pervasive use of locks like our mutex to keep the critical section safe. Here's another example:
AQUIRE_MUTEX(m);
// critical section code
RELEASE_MUTEX(m);
Mutex m;In this example we can see that we aren't properly using the mutex everywhere, so we can't guarantee that we won't get corrupt data. Multiple threads could just as easily enter the push function simultaneously as could attempt to enter the pop function. If you don't use mutexes everywhere, it's almost as good as not using them anywhere. This is a convention that the coder must decide upon beforehand and follow diligently.
int pop(array* a) {
ACQUIRE_MUTEX(m);
int item = a->values[a->length - 1];
a->length--;
RELEASE_MUTEX(m);
return item;
}
void push(array* a, int item) {
a->values[a-length] = item;
a->length++;
}
$P0 = syncronize $P1We can create some kind of wrapper PMC type whose vtables enter a lock, call the vtable of the synchronized PMC, and then release the lock. In this example, if everybody used $P0 when they wanted to modify $P1, all operations would be safe. The onus would be on the programmer to explicitly mark the PMC as synchronized, of course, and many programmers will probably forget to do that.
propagate thread, objThis would pause the specified thread, update the object contents, and then unpause the thread. This would be very similar to the message passing that languages like Erlang use (not exactly the same, because Erlang wouldn't pause the recipient for this, but you get the idea).
In my previous post, I described in tutorial form how to implement a very simple constant folding optimization for Integer addition. In this very brief post, I describe in greater detail how that optimization works.
The Perl 6 design team met by phone on 19 May 2010. Larry, Will, and chromatic attended. Patrick added his notes later.
Larry:
~~ topicalizes, and removes smartmatch table fossils that automatically fall out from that:a and :aa changed to :m and :mm :samecase and :samemark mm// to ms// to avoid confusion with new :m ignoremark option??!! constructs of various sortsCORE.setting now has protos of all the operators so they can be recognized as subs tooStr $toto' to intuit missing declaratorWill:
c:
Patrick:
The Perl 6 design team met by phone on 12 May 2010. Larry, Allison, Patrick, and Will attended.
Larry:
@foo[] into regex1__3 minmax function to CORE.settingcircumfix:«X Y» as grammar derivation >> insidefoofix:("\x[face]") and foofix:("\c[YOUR CHARACTER HERE]") without actually evaluatingyaml out of gimme5, since viv is not likely to go that route.Patrick:
Allison:
Will:
The next step in green threads is to make them preemptive: after one thread has run for a while, it needs to be stopped so a waiting thread can have a turn. Parrot has a mechanism for doing things after a set time called Timers which would be perfect for this. Unfortunately, they don't really work.
Since my last post I haven't spent as much time as I'd like coding, since getting a win32 development environment setup was a bigger time sink than I expected, but I've still managed to stay pretty close to the schedule. The main feature for the next week, once I'm done with the charset-level stuff will be Iterators, which will finally enable NFG 'literals' in PIR source, for which I have added, failing, tests the past week.
The NCI updates using the libffi are coming along. I ran into a bit of an annoyance when I found out that there are places internally where signatures are not specified for some functions, but luckily it was easy to remedy once I had figured out the problem. All of those cases used the same signature ("vJP"), it was only hard to find the right place to add that.
On Friday I flew from rainy Sweden to scorching hot Kiev to attend a combined Perl Mova + YAPC::Russia. The passport queue wasn't overly long, and I'd happily managed to be hand luggage only, so I wasn't too long in the airport. I planned to take the "official" bus, but before it appeared I heard a lady shouting about a mashrutka going to the center, so I took that instead. Understanding basic Russian - well, it coulda been Ukrainian too - sure comes in helpful. I was dropped by a metro station, leaving the 15 euro-cent (yes, really) metro ride a few stops to where I was staying - a hotel right on the main Independence Square. I was a little bemused as I checked in to be spoken to in a mixture of Russian and Ukrainian, by the same person in the same conversation.
My plane had been slightly late, so I was also slightly late joining the pre-workshop dinner. After I'd filled up on a tasty dish of borsch, we wandered on to a pub that offered no less than 22 different beers. I was...happy. :-) Some beer later, it was time for a little stroll, which terminated in a Japanese restaurant, where I had my first encounter with wasabi vodka. All in all, a very fun start to my visit here.
I was worried I'd sleep badly in my room since it was a little hot, but I actually slept really quite well and was nicely refreshed for the hack meet. There were a lot of people there hacking on all kinds of different projects. Some folks were interested in contributing to Rakudo, and so we gathered around on a table and I helped each of them find and get started on a task. It went extremely well - everyone in attendance contributed Rakudo patches or code that allowed us to close an RT ticket right there on the day, or that will after I apply patches. Of note, people who were new to Rakudo hacking:
I think it goes without saying that this is really quite impressive, especially given they had to share one Rakudo core hacker between them for guidance. In fact, I even had time to cook up a few patches myself amongst guiding others! It was great fun to hack alongside such pepole. I handed three spectest repo commit bits out that day, and I think they were all used. It's experiences like the one at this hack meet that make me really glad that we're writing most of Rakudo in Perl 6 or a restricted dialect of it - all of the above tasks required (apart from a one line change in one of them) no PIR or C knowledge at all. Some of those at the hackmeet said they may find time for a bit more Rakudo hacking in the future, which would be really great. :-) After the hack meet, there was more nice food - including a Chicken Kiev - and some lovely beer at prices I've become rather unacustomed to in Sweden.
Day two was talks day. I had one 40 minute talk on Perl 6 signatures which went well. I received some great questions, and I hope I answered them all to people's satisfaction. Later on, I gave a lightning talk about Rakudo * and what it would contain, and showed off a simple little example site that used Rakudo Perl 6, including the modules JSON::Tiny by moritz++ and FakeDBI by mberends++ along with Blizkost (sorear++ for that) to get at the Perl 5 CGI module (though I'll refactor it to use Web.pm in the near future - I just wanted an excuse to show off Blizkost). The evening was, of course, more food and beer, and a lot of fun.
The final day of the workshop was a bit different - a river cruise! It was very relaxing, and gave me yet another way to enjoy this beautiful city. Certainly good for unwinding after a workshop. Most people left either after that or were flying home today; I on the other hand used "no direct flight on a Tuesday" as an excuse to get another day to potter around Kiev, and today I've enjoyed doing exactly that, gently strolling between my favorite sights and stopping in the odd open air cafe in a park to keep myself refreshed in the somewhat stuffy weather. Soon it'll be time to take my last dinner here, an evening stroll and maybe find some outdoor place to sit and nurse a final beer before it's time to get some sleep before my flight home tomorrow.
Beautiful Kiev. It gets harder to leave each time I come. :-)
On behalf of the Parrot team, I'm proud to announce Parrot 2.5.0
"Cheops". Parrot
is a virtual machine aimed at running all dynamic languages.
Parrot 2.5.0 is available on Parrot's FTP
site, or follow the download
instructions. For those who would like to develop on Parrot, or help
develop Parrot itself, we recommend using
Subversion on our
source code repository to get the latest and best Parrot code.
Parrot 2.5.0 News:
The process of loading a dynop library is seemingly straightforward. Simply using the “.loadlib” directive or the “loadlib” opcode in PIR will result in the library being loaded and integrated into the interpreter environment. That is, until you have more than 1 interpreter in play, or, the bytecode that you load has different opcode numberings that what is currently reflected in the interpreter.
Parrot’s solution to the former is to simply disallow loading dynop libraries when there is more than one interpreter in play. There exists a certain assumption on how interpreters are created, in that, there is only one main interpreter, and additional interpreters are spawned as ParrotThreads (at least that is how I understand the code). Creating interpreters in the model above will yield the expected behaviour, in that everything works normally when the main interpreter will preload everything that is needed by the threads, thus obviating the need to load of dynop libraries in the threads. However, if one creates an additional interpreter outside this model, it breaks the assumption and one can load dynops in the second interpreter. The main reason for this is that only the first interpreter is registered in the “interpreter_array”, while the second is not. Since the code to detect if there is more than 1 interpreter depends on the “interpreter_array” and the associated “n_interpreters” count, the second interpreter is non-existent in the point of view of the core.
With regards to dynops, in the process of updating the core op tables, there is a high possibility that pointers to the various op tables change to point to new locations in memory. With 1 interpreter, everything is fine, as the op table references of that interpreter is updated accordingly. Adding a second interpreter to the mix will result in a segmentation fault when the second interpreter tries to access the outdated references to the op tables. There has to be a way to detect or notify any changes to the op tables to all interpreters currently existing.
Trying to change the code in the core to achieve this is an exercise of frustration. After trying out a few things, namely forcibly registering all interpreters by modifying Parrot_cx_init_scheduler and broadcasting messages in dynop_register by using Parrot_cx_broadcast_message and trying to make sense of the failures I’m getting (mostly assertion failures), I discovered a few things. First, I discovered that there are no GC runs after a thread is created (if I understand correctly, see src/pmc/threadinterpreter.pmc). Apparently its not really stop the world, more like stop the GC and I don’t see anywhere where the GC is reenabled. Second, there is no simple way to halt a thread and know that it is halted. I can broadcast messages to all interpreters for all I want, but unless I know for sure that all interpreters have stop, it is dangerous to go ahead with updating the op tables. One way I wanted to try out was to use pt_thread_wait and pt_thread_signal, but that got blocked as I can’t get those symbols exported (putting them in thread.h doesn’t help, marking them as PARROT_EXPORT also doesn’t help). Since that didn’t work, I’m stopping this experiment as it has taken way too much time and its not part of my objectives.
All that effort is not wasted though. Now that I understand more of how the internals work, I could do my own DIY dynlib detection. In the same vein, I found the reason for a segmentation fault that I encountered when I try to run “tracer.nqp” against “examples/pir/io.pir”. I worked around that by simply making the child interpreter’s vtables point to the parent’s instead. Digging into the internals these past week, I think I figured out why. So apparently, NQP loads the OS dynpmc. “examples/pir/io.pir” also loads in the OS dynpmc. So at this point, there are two different entries in two different vtables with different base_type numbers. For normal dynpmcs, this is fine as each interpreter will only look at their own vtable entries. However, the OS dynpmc is a singleton. Thus, when NQP loads it, an instance is created and stored. When io.pir loads it again, the stored instance is then saved in the MRO (method resolution order) list of io.pir’s copy of the OS vtable entry. So, io.pir’s OS vtable entry’s index is around 85, but the one in its MRO list is about 101, and this difference leads to a segfault when trying to invoke a method of OS.
Back on track, I do my dynlib detection in the Instrument dynpmc itself, in the form of the function detect_loadlib. Since I discovered that each interpreter stores a hash of the dynlibs it has loaded in the iglobals hash, detecting newly loaded dynlibs is simply comparing an old list of loaded dynlibs with the current list. So, now the Instruments dynpmc can detect all dynlibs loaded through “.loadlib” directives and “loadlib” opcodes, and creates the task/event “Instrument::Event::Internal::loadlib” which can then be handled in PIR. With that in place, I can now proceed to go on and implement more events to raise.
Currently, I have three events, which are Instrument::Event::Internal::loadlib, Instrument::Event::Class::instantiate, Instrument::Event::Class::callmethod. An example script to use these events is shown below (in NQP):
Q:PIR {
load_bytecode 'Instrument/InstrumentLib.pbc'
};
sub loadlib_cb ($task) {
my $data := Q:PIR {
find_lex $P0, '$task'
%r = getattribute $P0, 'data'
};
say('Library loaded: ' ~ $data[0]);
};
sub class_cb ($task) {
my $data := Q:PIR {
find_lex $P0, '$task'
%r = getattribute $P0, 'data'
};
say('Class instantiated: ' ~ $data[0]);
};
my $args := pir::getinterp__p()[2];
$args.shift();
my $loadlib_evt := Instrument::Event::Internal::loadlib.new();
$loadlib_evt.set_callback(loadlib_cb);
my $class_evt := Instrument::Event::Class::instantiate.new();
$class_evt.set_callback(class_cb);
my $instr := Q:PIR { %r = new ['Instrument'] };
$instr.attach($loadlib_evt);
$instr.attach($class_evt);
$instr.run($args[0], $args);
Running this against “./examples/pir/io.pir” yields:
Library loaded: io_ops test4 test5 test1 test2 test3 Library loaded: os Class instantiated: OS
Well, it’s not much but its a start. Not too mention I’ve fixed most of my crashes already.
4th Weeks Tasks:
Parrot Abstract Syntax Trees(PASTs) are one of the forms code being compiled in a PCT-based compiler takes before being evaluated or compiled to bytecode. With PAST::Pattern, you can find all the sub-trees of a PAST that match a certain pattern and transform them. This can be used to perform optimizations at the PAST level.
Wherein I dash your hopes of spending the weekend hacking on making your favorite HLL compiler generate better code only to give you hope at the end that it will not be long at all before you can:
I noticed yesterday that I forgot to post a blog post last week. I'll try to make up for that with double the blog post goodness this week(expect a second post Thursday or Friday).
During my meeting with cotto on Tuesday (my time), he suggested looking into replacing entries within the op_func_table on the instrumented interpreter (CHILD). So the past few days, I’ve been working on it. The initial plan was to create a copy of that table, replacing ops that have hooks attached with a stub function that will fire the hooks before executing the op itself. The operation itself went swimmingly, until the monster known as “dynops” popped up to say “OHAI!”.
Before I go into the problems I face with dynops my initial approach, I have to say that cotto was right in that this approach will have better performance characteristics that what I was doing earlier, which was to store the hooks in a ResizablePMCArray which holds the hooks in a Hash. That was a bit of a cop-out on my part, as that was the path of least resistance in terms of adding new and removing hooks. Doing it in that manner simplifies the code for adding and removing hooks, at a cost of going through more levels of VTABLEs. With that, I’ve changed the data structure to hold the probes. It is now an array of linked lists, with a 1-1 mapping between each linked list and op. With this major change, running the example code [0] against examples/pir/mandel.pir yields approximately 5% performance increase (user 16.077s vs user 17.001s previously).
Back on topic, so the plan is to create a copy of the op_func_table, instrument it and change CHILD’s to refer to it instead of the core op_func_table. This was rather easy. Then, dynops dropped by.
With dynops in the equation, it did not turn out easy. Problem is, if the instrumented table is not switched back to the core table, the core table will end up pointing to the instrumented table instead at the end of dynops_register (see src/runcore/main.c). Also, how is the supervising interpreter (PARENT) supposed to know when new dynops are loaded in the CHILD? The PARENT has to know when the core op_func_table is changed, so that it can update its own references accordingly. Currently, dynops_register gets around this problem by prohibiting loading dynops when there is more than 1 interpreter in play.
So, hold on. “more than 1 interpreter in play”. But there are two interpreters, PARENT and CHILD! Apparently, creating interpreters through Parrot_new will only register the first interpreter in the list of interpreters held by core. Thus,
Parrot_Interp PARENT = Parrot_new(NULL);
Parrot_Interp CHILD = Parrot_new(PARENT);
PARENT will be registered, as traced through Parrot_new -> Parrot_cx_init_scheduler -> pt_add_to_interpreters (I might have missed some steps in between).
However, CHILD is not, as in Parrot_cx_init_scheduler (see src/scheduler.c), since CHILD has a parent interpreter, pt_add_to_interpreters (see src/thread.c) is not called. So, as far as core is concerned, there is only 1 interpreter in play, and that interpreter is PARENT. Thus that is why the check “n_interpreters > 1″ in dynop_register fails, and how I inadvertently was able to run 2 interpreters and have dynops loading, although it segfaults later on when PARENT tries to access its outdated tables. If CHILD is manually registered by calling pt_add_to_intepreters, then that is a no go, as then both PARENT and CHILD cannot load any dynop libraries. Given that CHILD has to be able to load dynop libraries, I’m at an impasse.
To recap, this is the problem at this juncture, if CHILD loads a dynop library, the instrumented table must be swapped out and replaced with the core table. After loading is complete, the instrumented table is then updated and swapped back in. After all that, PARENT must be notified of this loading so that it itself can update its own table references.
In my previous post, I mentioned making use of the events system to detect when CHILD is going to execute a “loadlib” op and to raise an event that PARENT can handle and do the necessary stuff. But that won’t work for “.loadlib” directives (see [1]), as that is not an op. So scratch that idea for now (although, I think it is a good idea for normal “loadlib” ops). Digging into the events system, I noticed that it already does some of what I was doing, in that, to check for events, a copy of the core op_func_table is made (see include/parrot/interpreter.h , interp->evc_func_table), and all entries in that table points to the “check_events__” op. This table is also helpfully taken care of in dynop_register, in that it helpfully extends it whenever new dynops are added.
Then I realised something, I’m going to create a copy of the op_func_table, and replace each entry with a stub function. This table will then be used for op lookup and execution by the runcore. And I control CHILD’s runcore. Why don’t I move the call to the stub function in the runcore itself. So that’s where I’m at now, square one + a bit.
To get around the problem brought about by dynops temporarily, I simply add a check in the runcore to update PARENT’s op tables whenever it does not match CHILD’s op tables. I did some thinking on this, maybe make dynop loading a STOP THE WORLD event, just like GC. This I think can be done in dynops_register, broadcasting to all to halt and when all is halted, proceed to load the dynop library before broadcasting again to do the necessary updates before resuming itself. This I will revisit again later, seeing that I’m running out of time for this week’s tasks, which is, to recap, bug hunting and squashing of tracer.nqp, implementing the event notifications library and tests.
So bug hunting. Apparently I did something and now I can obtain and print out the STRING KEY constants. But the segfault with example/pir/io.pir remains when I try to trace it using tracer.nqp. Running it under a debugger shows that it segfaults when trying to access INTERP->vtables[SELF->vtable->base_type]->_namespace (in src/pmc/default.pmc line 549). Before this line, control is in find_method_direct_1 (in src/oo.c line 1051), where the variable _class is being queried for its namespace. Only problem is, the base_type of _class is 101, which is not a valid number given that at that point in time, there is only about 87 pmc types.
Running simple-tracer.pir [0] on it has no problems, of which I can only suspect that a GC run happened and the object got cleaned up, so bad data was being read. This would make sense given tracer.nqp is written in NQP and it does lots of string concatenations, so that should cause the GC to run more frequently. Now, if there’s a tool that I can use to confirm this… Oh wait, I’m supposed to be making those tools.. GAH!
[0] Simple-tracer.pir (Edited 13/06/2010)
.sub '' :load :init :anon
load_bytecode 'Instrument/Instrument.pbc'
load_bytecode 'Instrument/Probe.pbc'
.end
.sub 'main' :main
.param pmc args
$P0 = shift args
.local pmc pr, in, probe_class
probe_class = get_hll_global ['Instrument'], 'Probe'
pr = new probe_class
pr.'make_catchall'()
pr.'set_callback'('cb')
in = new ['Instrument']
in.'attach'(pr)
$S0 = args[0]
in.'run'($S0, args)
.end
.sub 'cb'
.param int pc
.param pmc op
.param pmc instr
print 'Op: '
$I0 = op[0]
say $I0
.end
Parrot has Continuations. In fact, Parrot is *based* on Continuations: rather than having a call stack and stack frames, each sub call has a return continuation - a pointer back to the call frame and bytecode position to return to after the sub completes.
As the Scheme and Ruby users keep telling us, continuations are pretty neat stuff. In fact they're so neat that they give us light weight cooperative threads "for free".
"N̈" (Or "n̈" if you don't like caps) is a grapheme from several minor extended Latin alphabets. It occurs in the orthographies of the Jacaltec Mayan dialect, Cape Verdean Creole, and in the rockumentary "This is Spın̈al Tap". Today I want to talk about the injustices this symbol has faced in the past and how, starting today, parrot can right them.
Last week marked the start of the GSoC coding period. Prototyping during the bonding period helped me in creating an initial version of my framework and currently, I’m focusing on creating an interface to inspect each opcode that is being executed. This interface is the class Instrument::Probe [0]. Initially, this class was written in PIR. It quickly became rather untenable, with labels and jumps all over the place. My mentor, cotto, suggested implementing it in NQP instead, and that suggestion has proven to be a godsend. The code is cleaner, and it’s easier to follow, not to mention adding new features to it.
As of now, the class Instrument::Probe allows the creation of probes that inspect the opcodes being executed. Each probe has its associated callback and a list of opcodes that it is inspecting. Whenever the runcore encounters any of these opcodes, it will call the associated callback. This system is rather flexible in that probes can be enabled or disabled dynamically, and multiple callbacks can be associated with a single opcode. With that in mind, each probe also has an associated finalize callback which is called only at the end of execution and only if the probe is enabled at that point.
With that in mind, I’ve implemented a simple tracer example (examples/library/tracer.nqp [1]) that tries to mimic the output of the tracing runcore. It mostly works alright and is rather slow, which is a given seeing how much work it is doing per op, both at the PIR (or rather NQP) and the runcore levels. Not to mention its tendency to segfault every now and then, which I’m still in the process of tracking down. One current segfault happens when running it against examples/pir/io.pir, and it doesn’t happen when a simpler tracer that only prints the op number is used. Further testing shows that it seems to happen on the opcodes “get_results” and “set_results”, although I’m not quite certain why, probably because I’m accessing something the wrong way. Bug squashing is not a fun activity.
For this week, I’m working on to solve a few problems in addition to tracking down the segfaults above. First of which are dynops. This past week has seen major changes to the op libraries within parrot, due to “ops_massacre”. These changes made me think about dynops and how it will affect my project. Currently, the runtime library does op lookups using the OpLib and OpCode pmcs, and this lookup is done before the code is loaded/compiled. Due to this, the opcodes contained in the dynop libraries will be non-existent from the point of view of the library . One way i’m thinking of to solve this is to defer registering hooks for dynops, trying whenever new dynlibs are loaded. This can be done with a simple probe that looks for the opcode “loadlib” and raises an event when that opcode is encountered (I’m assuming “.loadlib” and “loadlib” works the same way). Which brings me to the question of is there an event system I can use? Simple tests and some digging (t/pmc/scheduler.t and PDD-24) showed me how to use Parrot’s event system and I think I can utilise this to implement the above and to serve as the basis for the other events such as PMC creation and GC mark cycle, barring any unforeseen issues.
To recap, I spent most of this week learning just enough NQP to reimplement the runtime library in NQP and chasing down bugs uncovered by the simple tracer example. This coming week will be spent on squashing the segfaults the tracer produces and make it faster and implementing events and a runtime library to abstract it away. And I should start on the tests too.
[0] https://svn.parrot.org/parrot/branches/gsoc_instrument/runtime/parrot/library/Instrument/Probe.nqp
[1] https://svn.parrot.org/parrot/branches/gsoc_instrument/examples/library/tracer.nqp
We're coming up on the annual Parrot Foundation member's meeting. Which includes the nomination and election of the next Parrot Foundation board of directors. And being so, the foundation is inviting everyone eligible for membership to apply. To be eligible for becoming a member of the Parrot Foundation you must:
Coding for GSoC officially began this Monday, but I decided to get a head start and started working on PAST::Walker Thursday. PAST::Walker is the foundation for the rest of what I will be doing regarding PAST Optimization, and the foundation is largely laid. There have been a few complications, and a few decisions remain to be made(and implemented) before I can say that PAST::Walker and PAST::Transformer are finished, but implementing PAST::Walker has gone smoothly and quickly for the most part.
One of the features of NFG I've mentioned before is that it solves our problems with variable width characters without taking additional storage space over UCS-4, on top of which it's defined. The artifact that allows us to pull off that trick is called the 'grapheme table' and today, I'll try to explain how it works.
(This post is to show my thinking on my GSoC project. Sorry in advance if it's not especially coherent or interesting out of context.)
Over the past week I've been examining the Parrot code to figure out how hybrid threads are going to fit in. First, if I'm going to make Parrot do stuff concurrently, I have to figure out what Parrot is actually doing at all.
However to be honest, its scary that over the last 10 years so much was done and discarded and is being rewritten. I agree with the "throw away the first" reasoning but that is something I would expect in a 2-3 year project not a 10 year old project.This really is two questions rolled into one:
Could you comment on the risk associated with for a HLL project that starts to build on Parrot with an ETA of say 1 year? Can it be said with a reasonably level of certainity that whatever sub-projects (JIT, treads etc.) are added to Parrot now, they will take an evolutionary approach rather than being scrapped and rewritten?
My intent is not to put down Parrot as I really want to use it but I want to voice my fears and hope to understand the parrot-dev perspective on making Parrot a stable (for some definition of stable) platform to build on.
"So there me was beating boulder into powder because me couldn't eat it, and magic ball land in lap. Naturally me think, "All right, free egg." because me stupid and me caveman. So me spent about three days humping and bust open with thigh bone so me could eat it good. Then magic ball shoot Oog with beam, and next thing me know me go out and invent wheel out of dinosaur brain. Magic dino wheel rolls for three short distance until me eat it. The point is, me get smarter. Soon me walk upright, me feather back dirty, matted hair into wings for style, and me stop to use bathroom as opposed to me just doing it as me walk. " -- Oog, Aqua Teen Hunger Force
- Core
+ Various long-standing bugs in IMCC were fixed
+ STRINGs are now immutable.
+ use STRINGNULL instead of NULL when working with strings
+ Fixed storage of methods in the NameSpace PMC
+ Added :nsentry flag to force method to be stored in the NameSpace
+ Added StringBuilder and PackfileDebug PMCs
+ Added experimental opcodes find_codepoint and unroll
- Compilers
+ Fixed reporting of line numbers in IMCC
+ Removed deprecated NQP compiler, replaced with new NQP-RX
+ Removed NCIGen compiler
- Deprecations
+ Tools to distribute on CPAN were removed
+ Deprecated dynpmcs have been removed to external repositories
+ Removed RetContinuation PMC
+ Removed CGoto, CGP, and Switch runcores
- Tests
+ Many tests for the extend/embed interface were added
+ done_testing() is now implemented in Test::More
- Tools
+ The fakexecutable tapir is renamed parrot-prove
+ Performance fixes to the pbc_to_exe tool
+ Fix data_json to work outside of trunk
+ The dynpmc GzipHandle (zlib wrapper) was added
+ The library Archive/Tar.pir was added.
+ The library Archive/Zip.pir was added.
+ The libraries LWP.pir, HTTP/Message.pir & URI.pir were added.
- Miscellaneous
+ Six Parrot-related projects accepted to GSoC
+ Improve use of const and other compiler hints
My Google Summer of Code (2010) objectives are to integrate libffi into the NCI framework and to build a new Stack Frame builder that takes advantage of the llvm.
After laying down the foundations of what NFG does in previous blog posts I've started implementing, as part of my work in this Summer of Code, a new Unicode encoding for parrot, UCS-4. In this post I'll try to explain what it is and how it makes NFG easier to achieve.
In Parrot, opcodes are currently implemented as a standalone piece of code that is invoked whenever its corresponding opcode number is encountered in the bytecode. Each opcode is described internally through the use of an op_info_t struct, which, taking from <parrot/op.h> is the following:
typedef struct op_info_t {
const char *name;
const char *full_name;
const char *func_name;
unsigned short jump;
short op_count;
arg_type_t types[PARROT_MAX_ARGS];
arg_dir_t dirs[PARROT_MAX_ARGS];
char labels[PARROT_MAX_ARGS];
} op_info_t;
These descriptions are stored as an array, with the index of each entry being the opcode’s own opcode number. This array is pointed to by a field within the interpreter struct, the field being “op_info_table”. This is just for the descriptions of the opcodes. In Parrot, currently each opcode is defined in a C-ish language that gets parsed into C source code, with each opcode constituting a function that satisfies the following function prototype:
typedef opcode_t *(*op_func_t)(opcode_t *, PARROT_INTERP);
Similar to the opcode descriptions, these opcode function pointers are stored as an array, with the opcode’s number being the index to the position of the opcode’s function pointer. This table is pointed to by the field “op_func_table” within the interpreter’s struct.
So what happens during execution? A pointer, which is the program counter (PC), is passed to the runcore’s runops function. This runops function is the one that looks up the function pointer for the current op pointed to by the PC and calls that function for execution.
The code for an opcode will do a number of things. First, it will grab the current context of the interpreter. The current context consists of a number of items, but chief and most important is that the current context holds the current values of the registers (Parrot being a register-based VM). With this context, it will then grab the required values from certain registers and after performing the required logic, will write values to a certain register. After that, it will advance the PC by a certain number, which generally is (PC + 1 + NO_OF_PARAMS)).
So how would you know which registers the parameters are in? The PC actually points to somewhere within the bytecode. Generally, the PC will point to the start of an opcode. If an opcode has no parameters, advancing the PC by 1 will get us to the next opcode to execute. However, if the opcode has parameters, advancing the PC by 1 will get us the register or INTVAL constant for the first parameter. Similarly, advancing by 2 will yield the register or INTVAL constant for the second parameter.
This is all well and good except for the fact that Parrot allows the loading of dynamic op libs, which extends the capabilities of the VM by providing additional ops, similar to how MMX/SSE/SSE2/etc extends the capabilities of an x86 processor. Parrot also shares the two tables “op_info_table” and “op_func_table” between interpreters, which does make sense, as having duplicates of these tables can be expensive memorywise, given that Parrot already has more than 1000 core opcodes.
Handling these two issues won’t be trivial. With regards to dynamic op libs, there needs to be a way to detect when the library being loaded is a dynop library. One way is to trap loadlib opcodes and then peek to check if the op tables change. It would also be good to investigate if we can duplicate any shared tables such that the interpreter running the instruments has its own private tables that will be untouched by any changes to the tables of other interpreters.
JimmyZ: trunk with old nqp-rx real:8m5.546s user:7m37.561s sys:0m10.281s
JimmyZ: trunk with new nqp-rx real:7m48.292s user:7m11.795s sys:0m10.585s
JimmyZ: codestring with new nqp-rx real:6m58.873s user:6m22.732s sys:0m6.356s
The Perl 6 design team met by phone on 05 May 2010. Larry, Allison, Patrick, Will, and chromatic attended.
Larry:
p5=> description because it's not supported in coreself:sort construct because self isn't a real syntactic category. pattern, so cursor_fate never called its alternative, oops.looks_like_cclass method to Cursor to detect most accidental uses of P5 ranges:tr language to :cc language since character classes share it# that would otherwise be a comment\# in character classes instead of misparsing as unspace- in a regex, we now presume we're in an old-school character class and fail with a sorry instead of a panic to give the character class code a shot at it~ syntax for regex brackets to set $*GOAL correctlysorry messages more correctlysorry no longer uses panic in a supposition, but dies directly to throw the exception to the suppose's try block$x[0] isn't taken as a character class; still needs speccingPatrick:
Larry:
Patrick:
Larry:
@ would be illegalPatrick:
Larry:
@ alternations are a big deal one way or another$ than what it really isPatrick:
Larry:
::T from role signaturesPatrick:
Allison:
Will:
Patrick:
* discussion of the StringBuilder PMC *
c:
Having an instrumentation framework opens the doors to having many different tools that can help to diagnose problems within a piece of code. One main example of this is Valgrind. Valgrind provides an interface for making many different tools that help to diagnose and identify certain specific problems, ranging from memory leaks to multithreaded data races between threads. Furthermore, the framework is also used to provide profiling tools, such as Callgrind and Cachegrind, to determine useful information such as call graphs and execution times of functions. As such, given a good framework to work with, a whole new world of performance and error analysis tools is opened up.
In the case of Parrot, which aims to be the virtual machine for many different kinds of languages, having such a framework can assist in creating debugging tools that cater to each languages’ idiosyncrasies or be general enough to apply to all. With proper hooks in place, such a framework can also provide the ability to inspect on the inner workings of the virtual machine itself, introspection that is more in depth that what is currently offered in the various PMCs offered by Parrot.
Thus, over the summer I will be working on creating such a framework for Parrot. In general terms, I would be looking to create an interface for various user-generated tools to hook into a Parrot program. Such tools can be written in PIR, and are run in a separate interpreter from the code to instrument against. There will be three layers that I hope to be able to provide an interface for instrumenting, which are the opcode layer, PMC layer and the GC layer. Explanations for these three layers are given below:
I intend to implement the interfaces in the order shown above and as each layer gets implemented, create tools that serve specific purposes such as call graphing, I/O monitoring and more. Tentatively, the API for the tools should look like the following:
$P0 = new ['Instrument']
$P0.’attach’(‘ops’, ‘catchall’, ’sub_callback)
$P0.’finalize’(‘finalize_sub’)
$P0.’run’(args)
In the example shown above, the ‘:main’ subroutine of the tool will perform the required initialization, creating an Instrument instance that it then registers callbacks into before executing the code to instrument against.
During this Community Bonding period, I will be prototyping the instrumenting framework as a PMC and will be looking at ways on how to insert hooks into the various PMCs and the GC subsystem in a safe manner. I would be posting more information on the project based on my prototyping efforts here and at the following blog, http://parrot.mangkok.com, and would welcome any feedback regarding this project on #parrot or through email at khairulsyamil@gmail.com.
The Perl 6 design team met by phone on 28 April 2010. Larry, Allison, Jerry, Will, and chromatic attended.
Larry:
Allison:
Will:
c:
The Perl 6 design team met by phone on 21 April 2010. Larry, Allison, Patrick, Will, Jerry, and chromatic attended.
Larry:
now to return the current instantrand and self, it does not parse as a function, since it never takes argumentsnow term and several other time-related namesAllison:
Will:
Jerry:
Patrick:
List implementation, especially laziness and contextc:
More Perl 6 Anti-FUD here:
http://www.perlmonks.org/?node_id=836533
http://www.perlmonks.org/?node_id=836564
and thoughts on the name "Perl 6"
http://www.perlmonks.org/?node_id=836626
Pm
An Anonymous Monk on perlmonks.org recently started a discussion on "The current state of Perl 6" in which he (she? they?) offers his views on various aspects of Perl 6 development. Personally, I find nearly all of Anonymous Monk's comments in the thread to be so devoid of logic and so far removed from reality/facts that it's hard to imagine providing an adequate reply to them.
Beyond that, I have other priorities in my life right now. Uppermost is that my family is going through a very difficult period at present -- I need to take care of them first. Rakudo and Perl 6 come in at a somewhat distant second to that. Responding to garbage being spouted by anonymous person(s) probably ought to not even be anywhere on my radar.
But at least one post in the thread bugs me sufficiently that I'd like to respond, even if it's an inadequate response. And I don't want my response buried in a thread somewhere, so it gets its own post.
Anonymous Monk writes:
Oh I'll tell you how you do that [write a grammar engine capable of supporting Perl 6]. It's very simple. You get people skilled for this exact task ! Those skills are acquired in universities(preferably good ones) where professors teach courses like "Formal Languages and Automata" or "Compiler theory". If you have a bunch of people who are open-source contributors but don't have the knowledge or haven't studied the right things ... [t]hey don't know it in theory and they're trying to put it in practice! (emphasis in original)
Who does Anonymous Monk think is working on Perl 6? Personally, I have a Ph.D. in Computer Science and taught university language courses for nearly 14 years. Damian Conway certainly also has a fairly strong university background (Monash University) and understands the theory and practice of language and compiler design. Jonathan Worthington has a degree from the University of Cambridge, where he specialized in compiler construction and formal languages. Larry Wall has a degree in Natural and Artificial Languages with two years of graduate work in Linguistics at U.C. Berkeley. Many of our other key contributors also have degrees and backgrounds in language theory and practice. I'd be willing to compare the academic credentials of this group against any other dynamic language team Anonymous Monk might care to postulate.
If you can't get real compiler people to use Perl6 and help with it, the average open-source rookie won't be able to deal with this.
Somehow I have trouble classifying Larry, Damian, Allison, etc. as being "not real compiler people". And they along with many other Perl 6 contributors have a lot of experience in nurturing open source developers and projects. If you feel Larry et al. are indeed unqualified to be working in the field of programming language design and implementation, you probably don't want to be using Perl at all, much less Perl 6.
People like Anonymous Monk spew lots of opinions about how long they think Perl 6 development should take, and then speculate on the reasons why it has taken longer than they estimate it should be taking. The speculations that crop up most often are things like "the people involved are clueless about language design/implementation" (see above), "the design process itself is flawed", "they're building on an inadequate toolset like Parrot", etc. For such people it's easy to toss out random thoughts about "the problems with Perl 6" without bothering to look at the obvious evidence to the contrary, as Anonymous Monk does above. Indeed, I'm often amused when people suggest that we should be doing things that we're already doing .
Returning to the topic of developing a grammar engine, which Anonymous Monk claims above as "very simple" and just needing "people skilled for this exact task", it's interesting to contrast his opinions with the actual development of the Perl 6 standard grammar (STD.pm6). I think STD.pm6 is also indicative of the challenges confronting all Perl 6 implementors. Consider:
I think one could consider this to be an almost perfect situation for developing a new language implementation -- an experienced language designer/implementor working without significant external restrictions on top of an advanced programming platform like Perl 5. Yet it's been three years since Larry started working on this implementation of the standard grammar and parser, and while STD.pm6 is very powerful, it's also certainly not "finished", and has been through a number of significant refactors in its development. This says to me that the amount of time and effort involved is more likely due to the sheer audacity and ambition of what Perl 6 seeks to accomplish.
(Some will undoubtedly look at the above and knee-jerk respond with something like "If it's taken three years just to create the parser, then finishing a compiler will take far longer still and therefore Perl 6 will never see the light of day." This argument ignores the fact that other pieces are being implemented in parallel with Larry's work, that software development is not a strictly sequential process, and the obvious fact that there are already "working" Perl 6 implementations available.)
Anyone who thinks that Perl 6 is fundamentally based on traditional compiler construction techniques taught in universities frankly has no clue as to what a fundamental paradigm shift Perl 6 represents to language design and implementation. It's this fundamental change that ultimately gives Perl 6 its power, but it's also why Perl 6 development is not a trivial exercise that can be done by a few dedicated undergraduates. As TimToady on #perl6 says, "We already have lots of those kinds of languages."
Personally, I'm impressed and honored to be associated with the people who are working on Rakudo and Perl 6. I understand that people are frustrated (and even feel burned by) the long wait for something as cool as Perl 6; I share the frustration and like to think that I'm doing something constructive about it. But I also find the vast majority of suggestions, comments, and conclusions coming from Perl 6's anonymous detractors to be (1) things we've already done or are doing, (2) ungrounded in reality, (3) in direct contradiction to reasonably observable facts, or (4) attempts to discredit a product they have little interest in ever using themselves. And far too many of the comments, like the ones I've highlighted in this post, are so easily refuted with just a little bit of fact digging and common sense, it's often hard to believe anyone can be seriously making them in the first place. Yet there they are.
Returning to my original theme, I think my response here is inadequate because it leaves so many other of Anonymous Monk's claims in the thread unrefuted. I could undoubtedly spend many more hours analyzing and responding to the many fallacies and untruths in the thread, but frankly I don't believe that's the best use of my time. People such as Moritz Lenz, chromatic, Michael Schwern, and others are also writing extremely well-reasoned posts refuting the garbage, for which I'm grateful, but it's far easier for Anonymous Monk and his like to spin garbage than it is for a small number of us to clean up after it. And it does need to be cleaned up, otherwise it festers and results in even more public garbage that someone has to clean up.
I hope that this post will at least encourage more people in the Perl community to critically examine the things they hear and read regarding Perl 6, especially when coming from sources with no apparent standing or reputation within the community. And maybe a few more people will even assist in publicly refuting the garbage ("many hands make light work"), so that the sloppy thinking, analysis, and dialogue that people like Anonymous Monk post doesn't spread to infect all of Perl.
Pm
P.S.: Some may reasonably conclude from what I've written above that Perl 6 is somehow "aiming too high", that our goals should be scaled back to make something ready "right now". I have two responses to this: (1) we are making things ready 'right now', just grab any of the available packages and start working and reporting bugs, and (2) there are already 'scaled back' versions of Perl 6 appearing and being used, such as NQP or even the components that execute the standard grammar. Some of these other projects, like NQP, are being used for "real" programs and applications today; they're not simply theoretical exercises or research projects.
Others often claim that all this effort on Perl 6 would be better spent on improving Perl 5. In my experience, those of us working on Perl 6 have absolutely no qualms with seeing Perl 5 improve and continue to grow -- we welcome it. Indeed, many of the features appearing in Perl 5 today come directly from ideas and things first attempted in Perl 6, and we're genuinely happy to see that. But just because Perl 6 developers also like Perl 5 doesn't mean that doing Perl 5 core development is interesting to us, or that (in my case at least) we'd even be qualified to do Perl 5 core changes. We aren't commodity programmers that are interested in simply being unplugged from one project and into some other project that others think is more worthwhile. Personally, I'd prefer to see people who are really into Perl 5 improvements continue to work to make them happen, and that the surrounding ecosystem continue to evolve to enable that to happen more easily for more people. Indeed, this is my wish for all open-source projects, even the ones I don't find interesting or otherwise disagree with.
The Perl 6 design team met by phone on 14 April 2010. Larry, Allison, Patrick, Will, and chromatic attended.
Larry:
.pm files to .pm6 to avoid confusionNYTProf Cursor.pmc now prefers .pm6 over .pm in any particular directory when searching for Perl 6 codeParse failed" vs "Check failed"True or False \V*\v for consistency\N*\v Couldn't find final ..." messages now use that capability to point to both ends of the error<<op>> ("Texas hypers") better even if op contains angles~<< that produced a misleading quotewords errornote' functionnote to print STDERR Allison:
:nsentry flagPatrick:
c:
Will:
Recently I moved to Sweden to join startup company Edument. They are, happily, very open to and supportive of my involvement in the Perl 6 project, and are organizing and sponsoring me to give a talk on Perl - both 5 and 6 for the Dataföreningen in Malmö on Tuesday 27th April. I believe this is only open to those who are members of the user group; if you are, feel free to come along though.
|
When you need perl, think perl.org
|
|