Tuesday, November 17, 2009

Paying taxes

A long time ago - 3 or 4 months, when I started this project - I tried to update my version of Parrot every few days. I'd get some code working, then the next day I'd svn update in the Parrot dir, rebuild, and carry on. But a couple of things happened, and I realized that that was a stupid idea. Once you give out commit privs, it's next to impossible to enforce any kind of discipline without chasing volunteers off your project, so Parrot is stuck with the occasional commit-without-testing.

So I decided that me updating without any kind of knowledge about stability was a stupid thing to do, and I started just updating after the monthly releases. This is a bad idea, too, because the release process seems to involve a "code freeze" for a little bit just before the release, and then everybody slams in whatever branch they've been holding off on merging for the last week. So I'm basing my stuff on the tagged release, rather than trunk, which is as it should be.

A few times, there have been failures even then, because the code didn't work, or a bug was introduced, or whatever. I've evolved a procedure for that, too -- I move the old Parrot workspace out of the way until I'm sure the new one is good, and I don't waste any time waiting for fixes. This means sometimes I go two months with no updates, but that's not such a bad thing.

At any rate, every month or so I "pay the upgrade tax." That is, I invest an hour or more in getting and building and rebuilding, and oh, yeah, I forgot I need to run dos2unix, and re-rebuilding Parrot. My buddy Jesse is now convinced that I've generated a meme, since other folks on #parrot keep telling me about paying the tax.

Today is tax day, and there's this new version of NQP, called NQP-rx. (That's the last sentence in this post that I'll be able to write without having to go back and remove profanity.)

Friday, November 13, 2009

No Close! Kakapo!

I've been silent for a while, and that's pretty bad.

The reason is that I've been busy not working on Close at all. Instead, I stopped to turn a bunch of the code I had already written into a general-purpose library, called Kakapo.

Kakapo is a runtime library for NQP, that helps developers (like me!) do useful stuff without having to drop into PIR every couple of lines. Since this is code that has been extracted from Slam, obviously Slam will be using it. I hope that other coders find it useful, too.

Monday, October 19, 2009

rtype not set

I just got this diagnostic from NQP, and boy, is that not a helpful error message. Of course, since it's in PAST->POST compilation, there's no line number or token output.

FWIW, the problem was that I was doing this:
self.declarator := '' ~ $name;
when, as anyone can plainly see, I should have been doing this:
self.declarator('' ~ $name);
because .declarator is a method, not an attribute. D'oh.

I've seen this error once before, and I didn't remember what caused it. I hope that next time I'll remember it, or that The All-Knowing Oz will be able to remind me.

Friday, October 16, 2009

Parrot Multi-Subs and Inheritance

One of the things I've added to Slam (the Close compiler) is support for declaring multi-subs. In another language, these would be called "overloaded methods" or "overloaded functions," but in Close, it's all about the underlying hardware, and that means MultiSubs.

Before I write too much, let me make this clear: Parrot is not the same as Perl6, or Python, or whatever your favorite language is. And so, the way Parrot (and Close) handle things like object dispatch -- the "Object Meta-model," as it is called -- is different from the way other languages handle these things. This is one of those times where the difference matters. (And specifically, the stuff I write below about inheritance isn't true for Perl6. You have been warned.)

Friday, October 2, 2009

Top versus Bottom

Last time, I posted on multiple inheritance, and on "class"-ifying the Slam code in general. Sadly, that is a "rat-hole" that I've gone down, and other than "still working on it" there hasn't been much to post. :-(

So I thought I'd dig out this little gem of a topic that I've had sitting in reserve: the difference between top-down and bottom-up parsing, and what it means to you.

Sunday, September 27, 2009

Multiple Inheritance

As an update to my previous post on subclassing PAST::Node classes, I ran into another problem. It turns out that the PAST -> POST compiler knows about, and depends on the differences between, the different Node subclasses.

For example, there are multi-methods that match on the types of their parameters, so that a PAST::Block gets processed by a different method than a PAST::Var. You get the idea.

So my original idea, of deriving a set of roughly parallel Block, Var, Val classes from a new root that was a child of PAST::Node won't work. Because while a Slam::Block may be a Slam::Node, which may be a PAST::Node, it turns out that it also has to be a PAST::Block for the other stuff to work.

Subclassing PAST::Node in NQP

One of the problems with NQP is that it's not quite perl6. And that means if you do much development, you eventually run up against a corner of the language where the sidewalk just ends.

The support for objects is an example of this. There's no problem with defining methods, or defining a class name. There's no problem with creating a new instance of the class. But that's where it stops being easy. Because the syntax for extending another class is missing.

One thing I'd like to do is subclass the PAST::Node class(es) in my own code, so I can use method invocations to call functions in a different namespace. This would change code like:
close::Compiler::Type::merge_specifiers($node1, $node2)

into something like:
$node1.merge($node2);

which would make my fingers happy, if nothing else.

Saturday, September 26, 2009

The Whitespace Hack

Every culture has certain rites of passage that they expect members to pass through before they are fully accepted. In some places, they're pretty extreme -- taking knives to your naughty bits, and the like. Fortunately, the Parrot community is a little more laid back than that. There are two rites of passage for new members to participate in. The second one, which I haven't done yet, is to code a new garbage collector. Apparently, when you've coded a new GC, you get to do
svn commit -m "Today, I am a Parrot."
and you're totally in. I haven't reached that far, but I'm here to tell you that the first rite of Parrot-hood is pretty easy: filling out a ticket on http://trac.parrot.org.

Friday, September 25, 2009

Recursive Compiling

Years ago, back when GCC was still on version 1.x, I went looking through the code. I don't remember why, but I was looking for a way to "just make a function." I had some notion that down in the bowels of the code there would be a function called "create_function" or some such, and I could pass it a return type and a name and who-knows-what-else, and it would return a function object. Or maybe it would automatically emit the function object. I don't remember what I was thinking at the time, I just remember being frustrated by the nest of snakes I uncovered, each function requiring a huge initialized data structure as input, making a small update to the tree, and returning.

The other day I was working on Close, and I needed to create a function for the namespace init code. And I thought, "what I need is a function that will just create this one thing for me." Deja vu!

Tuesday, September 22, 2009

Output ordering and Initializers

Output ordering

Today I got Close to emit functions in the same sequence they occur in the input file. That was easy.

What wasn't easy was automatically creating a namespace init function to handle initialized declarators.

If you compile code that looks like this:
int x = 10;
There's no function involved. Clearly, this is a global variable 'x', and its initial value is 10. But Parrot does not use the same model that *nix uses, of loading a file that contains a partial memory image. Since there's no data segment, any and all initialization have to be done by code.

Referencing symbols in another namespace

Today, I got this code to DWIW:
#include <std/io>
#include <std/test>

namespace test {
    namespace hll: close :: test :: nested {
        namespace deeply {
            void goodbye() {
                say("Adios, amigo.");
            }
        }
    }


Howdy

Everyone else is doing it, so why can't we?

In this case, I'll be blogging about Close - a programming language on and for the Parrot VM.