CPANdeps can now highlight non-perl dependencies 2008-05-12 13:51 drhyde
If there's any other things I should look for, please use the "report bugs" link on the website.
If there's any other things I should look for, please use the "report bugs" link on the website.
It also makes a very good example of how useful closures can be. Here's just one example.
The Z80 is an 8 bit processor, with several 8 bit registers. But it also has some 16 bit "reigster pairs", which are made up of two 8 bit registers that can be treated as a single larger register. For example, the 8 bit register B and C can be combined to make a 16 bit register BC. Any operation that changes B or C also changes BC, and vice versa. Now, to implement them, I could have lots of hairy logic so that any instruction that operates on BC actually operates on both B and C. But that would lead to lots of duplication of code, for all the register pairs, and for all the instructions that operate on 'em.
I already have a
So now, I can create a 16 bit register pair like this
my $BC = CPU::Emulator::Z80::Register16->new(
get => sub {
return 256 * $self->register('B')->get() +
$self->register('C')->get()
},
set => sub {
my $value = shift;
$self->register('B')->set($value >>8);
$self->register('C')->set($value & 0xFF);
}
);
and then as far as implementing the actual Z80 instructions goes, I can just get() and set() sixteen bit registers with a single method call, instead of doing all the multiplication, shifting, bitmasking and so on every time. Note that I use a variable $self inside the two anonymous subroutines without declaring it with my. This isn't a bug. That is the $self in the code that creates the anonysubs. It has nothing to do with whatever
$self might be inside a Register16 class's get() or set() method.
But there are actually several register-pairs, so I went one step further. Instead of repeating that chunk of code several times, once for each pair, I did this:
$AF = _derive_register16($self, qw(A F));
$BC = _derive_register16($self, qw(B C));
$DE = _derive_register16($self, qw(D E));
sub _derive_register16 {
my($self, $high, $low) = @_;
return CPU::Emulator::Z80::Register16->new(
get => sub {
return 256 * $self->register($high)->get() +
$self->register($low)->get()
},
set => sub {
my $value = shift;
$self->register($high)->set($value >>8);
$self->register($low)->set($value & 0xFF);
},
);
}
In this case, I pass $self and the names of two 8 bit registers to
the _derive_register16 function. That function then creates and returns a Register16 now "closing over" 3 variables.
Closures rock. By combining objects and closures I have ended up writing a lot less code. And by reducing the amount of duplication in my code, when I inevitably find a bug, I'll have just one place to fix it, instead of having to remember all the hundred places where I twiddle register pairs. If you ever find yourself writing the same code over and over again just with minimally different data, this is a useful technique.
You can see what I'm up to on this project by looking at the CVS repository.
"It's still in something of a state of flux so not ready for real-world use yet, but we're at the stage where we need lots of people to beat it to hell and back. Please try to run the tests on as many platforms as possible, with as many perls as possible, and in particular using perls built with as many compilers and linkers as possible. Send the results - both successes and failures - to me by email along with the output from perl -V (that's a capital V).
We're particularly interested in results from people whose perl was built with something other than gcc or Microsoft C, as we don't have easy access to the proprietary Sun/SGI/DEC etc compilers or Borland C.
The more alert of you will have noticed that there is a bootstrapping problem in using this from within a Makefile.PL - relax, it will come with a script to bundle itself in an inc/ directory.
Following on from Devel::CheckOS I have been working with David Golden on Devel::CheckLib. It's similar to Devel::CheckOS, in that it will let module authors specify dependencies which aren't just other perl modules - if they need, eg, libjpeg, then they can use this module in Makefile.PL / Build.PL to make it a pre-req, and if it's missing then the CPAN testers will SHUT THE HELL UP ABOUT IT and not annoy the author.
It's still in something of a state of flux so not ready for real-world use yet, but we're at the stage where we need lots of people to beat it to hell and back. Please try to run the tests on as many platforms as possible, with as many perls as possible, and in particular using perls built with as many compilers and linkers as possible. Send the results - both successes and failures - to me by email along with the output from perl -V (that's a capital V).
We're particularly interested in results from people whose perl was built with something other than gcc or Microsoft C, as we don't have easy access to the proprietary Sun/SGI/DEC etc compilers or Borland C.
The more alert of you will have noticed that there is a bootstrapping problem in using this from within a Makefile.PL - relax, it will come with a script to bundle itself in an inc/ directory.
Devel::CheckOS provides functions which return true or false depending on whether there's a match. Devel::AssertOS dies when you try to use it if there's no match.
The intention is that authors will use these modules whenever they write platform-specific code so that it will die with an appropriate message, which will be picked up by CPAN testers, and make them SHUT THE HELL UP when they try to do stupid things like test Solaris::Foo on Linux or VMS::Bar on Windows.
Last night I released Devel::CheckOS and Devel::AssertOS. They are a wrapper around $^O with some extra functionality. For example, where you can check $^O's value to see if you're running on a Linux system, you can use these modules to check for OS 'families' as well, such as whether you're running on a Unix system.
Devel::CheckOS provides functions which return true or false depending on whether there's a match. Devel::AssertOS dies when you try to use it if there's no match.
The intention is that authors will use these modules whenever they write platform-specific code so that it will die with an appropriate message, which will be picked up by CPAN testers, and make them SHUT THE HELL UP when they try to do stupid things like test Solaris::Foo on Linux or VMS::Bar on Windows.
I expect it to be useful for authors trying to decide what to depend on (you don't want to depend on stuff that itself has fragile dependencies) and also for people trying to figger out why the hell some random module won't install.
To see half the CPAN, try pointing it at Angerwhale.
After a discussion on the perl-qa list, and being blessed with a few hours free time, I wrote a shiny thing, which, given a module name on the CPAN, will find all its dependencies, and their dependencies yea even unto the Nth generation, and display a nice shiny report on their CPAN-testers results.
I expect it to be useful for authors trying to decide what to depend on (you don't want to depend on stuff that itself has fragile dependencies) and also for people trying to figger out why the hell some random module won't install.
To see half the CPAN, try pointing it at Angerwhale.
update: it now calculates the likelihood of a trouble-free install, and has been made much faster by having a local copy of the CPAN testers database and moving to mod_perl