Blog Closed

This blog has moved to Github. This page will not be updated and is not open for comments. Please go to the new site for updated content.

Monday, March 29, 2010

Austin's Tickets.

Austin, of Kakapo and Close fame, has been creating new tickets avidly as he develops his various projects. I asked him to put together a prioritized list of his various tickets so I could focus my attentions fixing bugs that would benefit him the most. Without much delay, he complied. Here's a truncated list:
1 = blocking something;
2 = not blocking, but I strongly feel this is needed;
3 = nice to have;
4 = I'm not sure of the status.

ticket priority summary
1497 1 Expose 'meth_cache' attribute of class.pmc1492 1 Get_class namespace) confuses NSes that have same final name.
1473 1 Handle PMC type is broken
1520 1 P6metaclass cannot derive from already-`register`ed PMC type
1429 2 Add -L support to parrot-nqp
1515 2 Duplicate named args cause fatal error in subs
1133 2 MMD matching does not match 'scalar' with primitive types
1448 2 Modify `throw` opcode to pass through pre-configured resume continuation
1514 2 NQP-rx doesn't check storage mode for contextuals
1510 2 NQP-rx doesn't create PMC for string // expressions
1464 2 NQP-rx doesn't handle bare "return" from nested block correctly.
809 2 Opcode 'isa' does not accept RSA PMC for class
1431 2 Register assigned to .local string variable is mis-remembered
1430 3 Change trace offset numbers to hex format
799 3 Configure should explicitly check for symbolic link capability on Linux
1138 3 Create a 'vivify' opcode
1455 3 Exception 'birthtime' attribute not accessible
1446 3 Exception PMC 'clone' does not work
1088 3 Multidispatch 'concatenate_str' does not handle LHS undef
1109 3 MultiSub PMC does not support get_namespace method
1512 3 NQP-rx generates bad access code for non-twigiled attribute
1308 3 NQPrx does not vivify globals in all cases
1107 3 Opcode get_class has failed assertion with garbage input
1481 3 P6metaclass.register does not catch second registration of PMC Class
1437 3 pbc_dump: don't skip varargs words in -d mode
1438 3 pbc_dump: Indicate sub/method boundaries in -d mode
1065 3 PGE should emit inline PIR with Grammar namespace
741 3 PIR line numbers in backtraces are substantially wrong.
816 3 PMC 'Undef' does not support logical_not
1273 3 Provide a parrot 'backtrace' with assertion failures.
1442 3 Sub PMC should support getattribute
1513 3 Test::Builder formats TODO tests wrong/poorly
1439 3 pbc_dump: Mark branch targets in -d mode

I've crossed out the tickets I've already closed, and there are about a half-dozen more that I suspect will be closed within the next week. I'm trying to find the domain experts for some that I don't feel comfortable/competent to close myself.

I would like to see all of these get resolved not just for the benefit of Kakapo, but for the good of Parrot in general. 

Tuesday, March 23, 2010

Potential GSoC students

I've gotten several emails from prospective GSoC students in response to some of the blog posts I've written about potential project ideas. It looks like we're going to have interested applicants for several of the projects, including a few new ones that I hadn't even considered. These steps are especially important if you are new to the Parrot project and are applying for a GSoC position for the first time with us.

In each case, the advice I give the students is always basically the same:

  1. If you aren't a super C coder, or only have limited experience, pick up a copy of K&R. Read it cover-to-cover. "real world" code, like that found in Parrot, can differ significantly from the simplified, mickey-mouse code you experience in most introductory programming classes or the exercises in the back of a "Learn C in 24 hours" book. K&R isn't as in-depth as some tutorial books, but it's complete, concise, and serves as a great reference. Likewise, if your project is centered on Perl code but you aren't a great Perl coder, pick up a copy of the Camel book. Nothing beats having a good reference available as you work. If you don't know all the answers, you should know where to find all the answers.
  2. Get a copy of the Parrot source code, build it and run the tests. Start reading the code. You'll definitely want to skim over at least most of the src directory, and you will want to pay particular focus to the subsystems involved in your proposed project. If you're doing a GC project, read the code in src/gc. Strings? src/string. As you read code, make changes; especially changes to code formatting, readability, and documentation. Submit these changes as patches and be prepared for feedback. If you see problems but aren't able to fix them yourself, submit bug reports. It's hard to accept a GSoC project if we aren't familiar with the quality (or quantity) of your work.
  3. Get involved. Join the parrot-dev mailing list. This list isn't super-high traffic, so don't worry about getting your inbox flooded. Send a welcome message to the list to introduce yourself. If you're really interested to see what's going on at a deeper level, join the parrot-tickets list as well This list represents a live feed of events happening in our issue tracker. This will give you an idea of the kinds of problems users have and how we go about fixing them. One of the best things you can do is to join the #parrot chatroom on IRC. Introduce yourself to people there, follow the conversations, and get involved. Ask questions. It's hard to accept a GSoC project if we aren't familiar with you as a person, and if you aren't an active community member.
So here are my three recommendations in a nutshell: Beef up your skills, Get familiar with the project, and get involved in the community. Do these things, along with submitting a good proposal, and your chances of getting accepted go way up. Good luck!

Thursday, March 18, 2010

Parrot is In GSoC!!

I just heard on IRC that The Perl Foundation and (through collaborative agreement) The Parrot Foundation have been accepted as mentoring organizations in this year's Google Summer of Code.

I've posted a few project ideas on my blog. I'll probably post more in the coming days. There are other ideas floating around as well, and you are always welcome to propose your own.

Interested students should definitely get in touch with myself or other Parrot community members AS SOON AS POSSIBLE!!!!

Seriously, the more applicants we have, the more cool projects we can end up with and the better the summer will be. If you or somebody you know is an able coder, especially if you have experience using Parrot or hacking on it, please apply.

Lean and Mean Parrot.

I got a comment from old-time Parrot contributor Melvin the other day in response to my criticisms of the PDD23 Exceptions system. He had a few things to say that really echo points that I've been trying to make in the past few months. I would like to reprint his comment here, in full (with some minor copyedits), and address it directly.

If IMCC needs to look into the op lib during lexical analysis, there is probably a design flaw. The opcode should probably only be checked during the parse / semantic check phase. If you want to tweak that much more performance out of IMCC you'd probably be better autogenerating the short op-list into imcc.l before calling lex so the token list is built directly into the scanner. As to your die vs. exit, I agree. This is where there is too much Perl influence in the VM. Things like 'die' semantics are better implemented in high level. Give the VM a simple opcode for termination, let all other things (printing messages, etc.) be implemented on top of the core op. I was arguing this in 2001/2002. If I had it my way, the core ops would be lean, and all the PMC grunge would have been implemented on top of those lean ops, not in the wacky .pmc/VTABLE mechanism that exists now. 99% of the Parrot lib would be written in a single, consistent HLL, and the JIT would be manageable. Right now, even as an original Parrot developer, I cannot wade in. Parrot requires a mix of Perl, PIR, C and custom build macros. PMCs are not Objects and Objects are not PMCs. There are still multiple cores for the fun of it. etc. etc. If Parrot is to ever really be done, seriously, someone needs to take a scalpel to about 50% of the "sacred" parts of the codebase and cut the amount of busy work and maintenance that has to be done, and remove some of the "multiple options" for accomplishing the same thing. Examples of projects that succeeded much faster than us are Mono. They built a canonical compiler (C#) and then proceeded in implementing the platform using the C# compiler. I was arguing that this would have been Cola at the time, and was my intent when I wrote PIR and the simple Cola compiler. But 8 years later, there is no JIT and Parrot is looking at using projects that started well after itself. I cringe when I look at all the hand-written .pir files in the distro. This was not the intent of PIR. Anyway, good luck. Don't take my comments the wrong way, hopefully they'll spark some debate. I'll check in in 2012. :)

I don't know how actively Melvin has been following IRC discussion, the mailing list, or this blog. I assume that he hasn't been following too closely, and we really can't expect a person to be following discussion for a project he's not really involved in actively. One of the big points we've been pushing for in recent months is Lorito, the lean set of low-level ops that we are going to use to rewrite large swaths of the codebase. In fact, seeing Melvin discuss this very idea is encouraging and validating: If other people come to the same conclusions that we come to internally, that means they are at least common ideas and maybe even good ones.

Lorito gives us the opportunity to move the abstraction layer down, and reduce context switches that occur by moving from one side of the line to the other. You don't have to look far in the PCC system, for instance, to see the machinations we have to go through to manage method calls from C. There are complicated structures of function pointers to access parameters from variadic argument lists. There are all sorts of complicated serialization paths to marshal arguments into the CallContext PMC, make the call, and then marshal the arguments back out of it again.

If we didn't have to worry about making calls from C, or if we at least didn't have to worry about making them regularly, we could avoid all this nonsense and delete several hundred lines of code, and the code we had left would be faster.

Another fact that comes up regularly is that the VTABLE interface is lousy. We've optimized for VTABLE access even though it's an extremely limited interface. There are simultaneously too many functions in the list, too few to support certain PMC types, and not nearly enough flexibility to support the kinds of interoperation mechanisms that we need. Ask this: How many mathematics-related VTABLEs exist? Now ask how many of them are even remotely useful outside the handful of numerical PMC types? Why does every single PMC type need to carry around pointers to all these functions that never get used? Why don't VTABLEs support proper MMD? Why don't all VTABLEs do any kind of MMD, even if it's wrong? Why do we have so much trouble inheriting VTABLEs between core PMC types and user-defined objects?

If we re-write the whole PMC system in Lorito, we can improve VTABLE dispatch semantics, maybe unify VTABLEs and METHODs, and expand the list of VTABLEs to hold any operations that we need. If we make the distinction that a VTABLE is like a method but only has a fixed number of positional arguments and can only be called from Lorito code, we could use a separate streamlined dispatch path that would be far faster than VTABLE overrides in PIR are now, only marginally slower than C-level VTABLES are, with the flexibility to plug into Parrot's MMD system for proper dispatch, and significantly more powerful and flexible than what we currently have. Plus, using hashes and named lookups, types could define a Sub of any arbitrary name to be a VTABLE, look up by any name we want to use with any arity we need for that operation, and we would only need one "VTABLE not found" handler to fall back to if a suitable one hasn't been found.

Runcores that don't build on every platform and are not well-tested by default should disappear. Sure, there is some benefit to having them as an academic exercise. Sure, it's cool to say we have an obscure and complicated dispatch mechanism with fun properties. But the reality is this: We're not using them. When we create a fakecutable binary for HLL projects like Rakudo, it generally hard-codes in the name of the runcore to use. So if our primary users can't select their own runcore, and if the primary way to use Parrot should be through HLLs (because I'll be damned if we want people in general to be writing PIR directly forever), then having multiple runcores is a huge waste.

Slow core? It does do bounds checking, but those bounds checks have never been seen to fail in my tenure as a Parrot coder. Drop it.

Computed-Goto and Predereferenced-Computed-Goto cores? Not all compilers even support these, and they require much more than their fair share of support code to operate at all.

Switch core? It's available everywhere and it's pretty speedy, but performance decreases pretty dramatically when used with dynops.

There has been some effort to make runcores pluggable using libraries, so a migration effort to move some of the uncommon ones out of core would be beneficial. I don't think we need them in core, but if other people would like to maintain them elsewhere, I won't complain about it at all.

Let's get one thing straight: including unused or rarely-used code in your program is not free. There are costs associated with having that code in memory. There are costs associated with the branches and decisions that choose to avoid it. There are costs associated in loading and dynamically linking exported symbols. There are costs associated with compiling all this code These things may not be super-expensive, but they are not free. And keeping code that has no practical benefit for developers or end users without a good reason to have it is not good practice.

Unnecessary opcodes need to disappear as well. We have well over 1300 opcodes now, probably closer to 1400 at this point. All of these add overhead in terms of memory footprint and lookup effort. It's a huge waste, and I suspect that if we did some actual profiling work we would find only about 200 of them were used with any regularity and about half would be almost completely unused except for one or two calls in obscure tests in the Parrot repo. If PGE and NQP don't use particular ops, and if there is no compelling need to keep them for particular HLLs, or if those HLLs can reasonably turn them into dynops, they should be removed.

Adding more ops is not a case of "it's a small added convenience with no downside". There are very real downsides.

Having too many core PMCs is a problem too. Parrot currently has 86 core PMC types by my count. I think we can drop this number to 60 without having to make any cuts that are too painful. If we wanted to be aggressive I think we could go even lower, but we do hit a point where we need to start weighing proportionally-smaller performance gains against the lost utility of removing PMC types that we're dependent on. In any case, I think we can definitely stand to move the following PMC types into dynpmc libraries or even delete them entirely: AddrRegistry, BigInt, BigNum, Boolean, Capture, CPointer, File, 9 of the array types, Key (to be replaced with an array type), Opcode, OpLib, OrderedHash, Pointer, Scalar, and Timer. This would bring us down to 63 PMC types, and several of these that I've listed are already either deprecated or are listed as experimental.

We as a community have definitely been moving in this direction. Allison especially has been helping to spread a "less is more" philosophy to the design of Parrot and I do appreciate that effort on her part. Making a switch over to Lorito, and then using Lorito to implement Ops, PMCs, and a few other core systems would be a major benefit. chromatic has been a major pusher for the Lorito effort as well, and having somebody of his stature behind the effort lends major credence to it. The effort to slim down the number of ops and PMCs doesn't have as much momentum but there is real evidence that we could be moving in that direction in the near future. I welcome all these changes and hope to see them come to fruition.

Wednesday, March 10, 2010

GSoC Idea: GMP Bindings

This conversation happened yesterday on IRC, with some off-topic things edited out:

darbelo: That reminds me. I hate our bignums and want them to die...
whiteknight: darbelo: I agree with the bignums thing 100%. I want bignums out of the repo and moved to their own project
whiteknight: There's no sense keeping them when I suspect a majority of users can't use them because they don't have GMP installed
darbelo: Actually, I wouldn't mind them being in the core if they weren't dependant on a lib I don't have.
darbelo: I actually had started to write a stand-alone BigInteger PMC after last year's SoC.
whiteknight: that would make an awesome project too.
whiteknight: I think we should have lots of projects like that, and for developers to be able to pick which solution they want
whiteknight: as we are now, it's easier to force BigInt to pretend to do what we need instead of just using the best solution, which might be DecNumber or something else
darbelo: Maybe, but GMP is much, much more than just bignums. It's a pretty big library.
darbelo: Our PMCs don't even start to scratch the surface of what GMP can do.
whiteknight: darbelo: so moving those PMCs out to a separate library and adding wrappers for other functionality might be nice
darbelo: I would consider a GMP binding much more valuble to parrot than our current use of the lib, yes.
bubaflub: last year i worked a bit with GMP library and suggested to dukeleto we work on a GMP binding for parrot
bubaflub: last year with GSOC and perl 5
darbelo: bubaflub: That would be nice to have.
bubaflub: though we used an existing perl 5 binding (Math::GMPz)
whiteknight: yes, that would be a wonderful project
bubaflub: but we could nab the test suite and what not
whiteknight: exactly. We have the two PMC types, and we could write wrappers for the rest of the library and get all sorts of additional power
bubaflub: i think access to the GMP library in general would be nice; the stuff i worked on last year was setting some foundational stuff for cryptography libraries

Parrot has two PMC types that wrap GMP: BigInt nd BigNum. I think, and apparently a few people agree, that these two types have no business being in the core Parrot repository and should be moved to another project. The immediate benefit to this would be that the bindings for GMP could be improved and expanded independently, instead of only providing what little functionality Parrot actually makes direct use of.

A good GSoC project for this year would be to move (or fork) the current BigInt and BigNum PMC types to a new project and use them as the cornerstone for writing a more comprehensive interface for the GMP library.This could include other PMC types, NCI function wrappers, PMC methods, ops, and other things to allow access to the power of the GMP library. Adding custom Integer-like and Float-like PMCs that autopromote to their Big- counterparts would be nice too.

For more info about this project, you could probably get in touch with myself, darbelo, or bubaflub.

Tuesday, March 9, 2010

Weekend Hackathon

This weekend we were supposed to have a hackathon to get the new PCC branch up and running. The purpose of this branch is, as I have discussed before, to rearrange the call sequence so return values are processed after the function invocation instead of before. In the grand scheme of things, especially in comparison to the previous PCC refactors, this ends up being a minor change characterized mostly by massive code deletions instead of needing to write huge new functions or rewrite tons of existing functions. A few bugs stymied completion of the branch, but I have high hopes that the remaining bugs will get worked out soon. This branch was worked on primarily by allison, though I lent an eye as time permitted and chromatic lent some major debugging support as well.

Very few people ended up working on the PCC branch, even though that was the "official" target of the hackathon. A large amount of effort instead went to work on other branches. I'm certainly not complaining about the division of effort. In fact, I want to celebrate it. I'm extremely happy to see other worthwhile projects getting extra manhours devoted to them. It's very good to get people working on Parrot in any capacity, and as I mentioned above the PCC work was not a huge project that would have required a dozen developers focusing on it anyway.

cotto and bacek focused their considerable talents on the ops_pct branch, which aims to replace the Perl5-based ops parser with a bootstrapped version written with PCT. Im not sure about the exact status of that branch, but there was a huge flurry of commits and I have to believe things are progressing rapidly.

plobsing started a new branch to tackle ticket #1015. Using some of the new mechanisms he's developed to find and prevent cycles in the freeze/thaw code, he decided to try and fix the problems with cycles in deep clones as well. I don't know the current status, but last I saw his work was going well.

Coke has started a new branch to continue the makefile cleanups, this time focusing on the recursive makefile for the dynops. He seems to be running into some bugs this morning, but hopefully nothing that cannot be quickly overcome.

Overall I would label the hackathon a great success. A lot of people came out to IRC to follow progress and work on various projects, and it is all much-appreciated.

GSoC: Parrot in Summer 2010

Jonathan Leto sent out a great email to the list today about Parrot's involvement in GSoC this year. Parrot will be combining together with the Perl foundation again and entering as a single organization. I very much like this arrangement, under the blind assumption that we do better together in terms of student allotment than we do apart. I have no reason to doubt that.

Mentors: If you want to sign up to be a potential mentor, you can do it on the Perl foundation wiki.

Project Ideas: If you have any project ideas (I know I do!), list them on the Perl foundation wiki. If you tell me about the ideas as well, I'll feature them in a blog post and hopefully drum up some interest among prospective students.

Tuesday, March 2, 2010

Difference between PMCs and Objects

There has been lots of talk and activity lately that has to deal with Parrot Objects. My rant about exceptions in Parrot has incited Tene to begin a flurry of development on that system, and Austin's Kakapo project has been regularly pushing the boundaries of what kinds of operations are and should be possible (and finding lots of bugs along the way!). Other people have been bringing up the topic as well, and lots of people are asking lots of questions about the implementation. I'm going to use this post to explain a bit about how Objects and PMCs work in Parrot, and maybe later I'll devote a post or two to ideas for fixing this system.

PMCs are basically objects, though extremely simple, flexible, and low-level. PMCs are interacted with, primarily, through the VTABLE interface. VTABLEs in Parrot are long lists of C function pointers that implement various behaviors. Calling the in-place addition VTABLE, add_i, is done like this in C:

VTABLE_add_i(interp, pmc, 5);

...Which translates to this:

pmc->vtable->add_i(interp, pmc, 5);

By pointing to a per-type VTABLE structure, PMCs with the same type can access a common list of function behaviors without overlapping or needing to do expensive switch/cases over a list of direct function calls. Likewise, determining the type of a PMC means finding the type of the VTABLE it points to:

pmc->vtable->base_type; // type number
pmc->vtable->whoami; // type name (Parrot STRING)
pmc->vtable->class; // Class or PMCProxy PMC for the type

Also, if we have the type number, we can look up the particular VTABLE in an array:

VTABLE * tbl = interp->vtable[index];

In a sense, that's all there is to a PMC. All interactions with a PMC happen through this interface of about 185 function pointers. A PMC, by itself, doesn't have things that we would normally associate with "objects" in higher-level systems: Attributes and Methods. Sure, PMCs do have a way to associate a C structure, and therefore maintain a list of what we call "attributes", but those aren't directly accessible from PIR without adding some kind of lookup routine to find them and maybe wrap them into one of the Parrot register types (INTVAL, FLOATVAL, STRING, PMC). PMCs also appear to have methods, but this really isn't the case when you look at it closely.

As I describe in a previous post, the long way to invoke a method on a PMC is like this:

$P0 = new ['Foo']
$P1 = find_method $P0, "bar"
callmethodcc $P0, $P1

The find_method opcode is a thin wrapper around the VTABLE_find_method interface function. If I translate this to an extremely condensed and wildly inaccurate pseudo-C listing, we get:

PMC * p0 = Parrot_pmc_new(interp, type_Foo);
PMC * p1 = VTABLE_find_method(interp, p0, "bar");
setup_method_call(interp, p0);
VTABLE_invoke(interp, p1);

This is obviously an extremely inaccurate listing, but should do well to illustrate my point. The method is actually a separate PMC type. It can be either a Sub (a .sub written in PIR) or an NCI (a wrapper type around a C function call). To make the call we set up the argument list (the invocant, $P0, is treated sort of like an argument but is kept distinct) and then invoke the method.

Before they are invoked, methods are stored inside either a Class or PMCProxy PMC associated with that type. When we call VTABLE_find_method(interp, p0, "bar"), we go through this machination:

PMC * class = pmc->vtable->class;
PMC * methods = class->data->methods;
PMC * method = VTABLE_get_pmc_keyed_str(interp, methods, "bar");

What we think of as an "object" and a "class" is actually a small collection of interoperating PMCs. The PMC itself contains a long list of VTABLEs and a small amount of data stored in a C structure, which cannot be directly accessed from PIR code. The PMCProxy PMC (like Class, which I will describe later, but designed to work with PMC types written in C) contains a hash of methods and a variety of other data. Methods themselves are their own PMCs, complete with their own type data. To really blow your mind consider that, as a PMC, you can call a method on a method, or even a method on a method on a method.

In short, a PMC is sort of like the building block that is used to create objects and a type system, though the PMCs themselves are not what we normally think of as "objects". The only way to interact with a PMC is through VTABLEs, not attributes or methods. Luckily, VTABLEs exist that allow us to query the object for related attributes and methods, though the PMC itself may not necessarily respond to these requests.

Using PMCs, Parrot does provide a proper Object system through the use of two special PMC types: Object and Class. Class, as can be guessed, is a "metaobject" that defines type information for objects of a single type. The Class uses a series of PMCs internally to manage things like method PMCs and attributes. The Object PMC is the basic building block of a class instance object. It provides a series of default vtables that allow it to interact with Class the way we expect (to find methods that are stored in the class reliably, for instance) and to provide a set of attributes that are available for access from PIR. PMCs are the almost formless building blocks, Object is a very specific PMC type that provides behaviors that we expect from an OO type system.

Now that we've covered basic definitions, what are the big operational differences between the two systems? Here's a short list:

  1. Object types are defined by Class PMCs. PMCs are defined by PMCProxy PMCs
  2. Class PMCs are created whenever we do a "newclass" or "subclass" operation from PIR. PMCProxy PMCs are created lazily, only when we actually need to introspect a built-in PMC type.
  3. Objects must be created from a Class, which means the Class PMC must exist before any Objects of that type can be created. PMCs can be created by themselves and generally don't require instantiation from another PMC.
  4. Objects have very regimented behavior: You can (and should) expect certain things when you access a named attribute or named Method. In a PMC these behaviors may be overridden to do different and unexpected things. Specifically, it can be very difficult to get access to named attributes on a PMC unless they are explicitly made visible from PIR (which can be a lot of work, and not a lot of PMC types do it completely)
  5. Inheritance between PMCs happens at the C level, so C-level attribute structures are merged together and made visible from C code. Inheritance between objects happens at the PIR level, method and attribute lists are combined and made visible as expected when accessed from PIR code. Inheritance from a PMC to an object is almost always broken, if you expect the attributes and methods from the PMC to magically become visible as attributes and methods on the Object. I've never seen inheritance from an Object to a PMC subclass, but I suspect it is broken even worse.
  6. The VTABLEs in the Object PMC all provide an option to use a PIR-based override routine to implement the behavior. To do this, every VTABLE function in the Object PMC searches the associated Class for a similarly named VTABLE Sub PMC and, if one is found, calls that. PMC types almost never search for an override in the Proxy, and if you define one it will never be called (unless you specifically implement the logic to search for and execute it). On a related note the VTABLEs of an Object, because they are stored as PMCs in a Hash in the Class, can be modified at runtime. The VTABLEs of a PMC cannot be (well, I guess you could change the pointer to call a different function if your C-foo is strong, but I would prepare for fire and brimstone. Also, I won't fix any "bugs" that arise from this misguided behavior). I estimate at least 10% of reported bugs or feature requests in Parrot come from the "this sucks worse than I would expect" behavior of subclassing Objects from PMCs. If you can get away with it, it is almost always better to delegate to a built-in type instead of inheriting from it directly. But, I can talk more about problems and workaround solutions like this in another post.
So there you have a guide to the differences between Objects and PMCs. PMCs are the low-level building blocks of an object system, and Objects are combinations of several PMCs and a large number of default VTABLEs to implement an expected set of OO behaviors. In a sense, Objects are PMCs, but in another sense they really aren't.

Monday, March 1, 2010


A few days ago I mentioned an interesting new project called NQ-NQP, an implementation of the NQP language with a flex/bison frontend and an LLVM code generating backend. I've heard tonight that he's started blogging about it. Anybody who is interested in NQP or LLVM stuff might do well to give it a read.