Day 1 and Day 2/3 got me (mostly) prepared to begin the actual coding for the Parrot Plumage prototype. There were just two things left to figure out: how to access command-line arguments, and how to initialize complex data structures.
The first problem turned out to be relatively simple to solve with a couple more additions to the glue library to initialize
@ARGS
and $PROGRAM_NAME
from the IGLOBALS_ARGV_LIST
field of the Parrot interpreter globals.
The second problem (initializing complex data structures) required a couple silly hacks, but I got a decent workaround in the end. Allow me to explain ....
NQP natively can index into hashes, arrays, and complex arrangements of same with relative ease. Want to access an entry in a hash of arrays of hashes, with some fixed keys and some varying keys? No problem. Something like this will do:
$age := %pets{$type}[$num];
The problem is, there's no short and simple way to
initialize the %pets
hash. NQP doesn't have syntax for hash or array literals, which makes it rather painful to instantiate complex structures. Oh, I suppose you could write a whole bunch of these:
%pets[0] := 5; %pets [1] := 6; %pets [0] := 4; ...
but as you can imagine that gets old rather quickly -- and doing the initialization in raw PIR would be even more painful. Luckily, during my previous hack day I'd brought the JSON parser up to current standards, so I used it for a little trick. I defined the data structure I wanted as a JSON string, parsed it into a real data structure using the
data_json
language that now ships with Parrot, and then ran a fixup routine on the few bits that didn't translate easily.
That last bit might require a little explanation. I could only create data structures this way containing data types the JSON language knows how to represent: numbers, strings, arrays, hashes, booleans, etc. However, there's no way to represent a code reference, and one of the applications I had in mind was a function table for mapping user commands, such as
version
and install
to the subroutines that would implement them.
My solution was to replace the code references with the names of the subroutines I wanted in the JSON text, and then after parsing the JSON run a peculiar bit of inline PIR to replace the names with the real code references. The fixup function in question looks like this:
sub fixup_commands ($commands) { Q:PIR{ $P0 = find_lex '$commands' $P1 = iter $P0 fixup_loop: unless $P1 goto fixup_loop_end $S0 = shift $P1 $P2 = $P1[$S0] $S1 = $P2['action'] $P3 = get_hll_global $S1 $P2['action'] = $P3 goto fixup_loop fixup_loop_end: }; return $commands; }
The short explanation is that the loop in the above PIR block iterates over each entry in the $commands
hash, and for each action
key replaces the matching string value (the subroutine name) with the subroutine itself, looked up using the get_hll_global
op. And it works!
These problems out of the way, I could finally start writing a prototype of the plumage
command line tool. Time eventually ran out on my hacking day, but I managed to implement basic versions of
usage
, version
, and
info
commands, and a command parser and dispatcher that could be charitably described as "beyond minimalist".
While the first two commands just provide info about plumage
itself, the last one is the first command that actually provides real functionality. In particular, info
simply loads the metadata for a given project and prints the details for the user.
In order to have some metadata to display with my brand new info
command, I took a shot at filling in the fields from the
Metadata Proposal manually for a single project. In this case, I chose
Blizkost because it's useful, cool, and non-trivial without being insane.
Unsurprisingly, I came across a couple underspecified bits in the metadata proposal, but things mostly seemed to make sense. The result is a tad wordy, but it is after all intended to be generated mostly automatically.
That done, I found myself out of time for this hack day, but things are looking up for implementing an ultra-simple version of the install
command next time. Until then, I invite you to
browse the repository
or just come by #parrot on irc.parrot.org and ping me (japhb
). See you there!