A Plan for Pugs

Autrijus Tang is a talented Perl hacker, a dedicated CPAN contributor, and a truly smart man. His announcement of starting an implementation of Perl 6 in Haskell on February 1, 2005 might have seemed like a joke from almost anyone else. A month later, his little experiment runs more code and has attracted a community larger than anyone could have predicted. Perl.com recently caught up with Autrijus on #Perl6 to discuss his new project: Pugs.

chromatic: I’ve followed your journal from the beginning, but it didn’t start from the start. Where did you come up with this crazy idea?

Autrijus: Ok. The story is that I hacked SVK for many months with clkao. SVK worked, except it is not very flexible. There is a VCS named darcs, which is much more flexible, but is specced using quantum physics language and written in a scary language called Haskell. So, I spent one month doing nothing but learning Haskell, so I could understand darcs. Which worked well; I convinced a crazy client (who paid me to develop Parse::AFP) that Perl 5 is doomed because it has no COW (which, surprisingly, it now has), and to fund me to develop an alternate library using Haskell.

(I mean “Perl 5 is doomed for that task”, not “Perl 5 is doomed in general”.)

chromatic: Copy-on-Write?

Autrijus: Yeah.

chromatic: So that’s a “sort-of has”.

Autrijus: Yeah. As in, sky suddenly worked on it and claims it mostly works. Haven’t checked the code, though.

chromatic: It’s been in the works for years. Or “doesn’t works” perhaps.

Autrijus: But I digress. Using Haskell to develop OpenAFP.hs led to programs that eat constant 2MB memory, scale linearly, and are generally 2OOM faster than my Perl library.

Oh, and the code size is 1⁄ 10 .

chromatic: Okay, so you picked up Haskell to look at darcs to borrow ideas from for svk, then you convinced a client to pay you to write in Haskell and you started to like it. What type of program was this? It sounds like it had a bit of parsing.

Autrijus: AFP is IBM’s PDF-like format, born 7 years before PDF. It’s unlike PDF in that it’s all binary, very bitpacked, and is generally intolerant of errors. There was no free library that parses or munges AFP.

chromatic: Darcs really impressed you then.

Autrijus: The algorithm did. The day-to-day slowness and fragility for anything beyond mid-sized projects did not. But darcs is improving. But yeah, I was impressed by the conciseness.

chromatic: Is that the implementation of darcs you consider slow or the use of Haskell?

Autrijus: The implementation. It basically caches no info and recalculates all unnecessary information. Can’t be fast that way.

chromatic: Hm, it seems like memoization is something you can add to a functional program for free, almost.

Autrijus: Yeah, and there are people working on that.

chromatic: But not you, which is good for us Perl people.

Autrijus: Not me. Sorry.

Anyway. So, I ordered a bunch of books online including TaPL and ATTaPL so I could learn more about mysterious things like Category Theory and Type Inference and Curry-Howard Correspondence.

chromatic: How far did you get?

Autrijus: I think I have a pretty solid idea of the basics now, thanks to my math-minded brother Bestian, but TaPL is a very information-rich book.

chromatic: Me, I’m happy just to recognize Haskell Curry’s name.

Autrijus: I read the first two chapters at a relaxed pace. By the end of second chapter it starts to implement languages for real and usually by that time, the profs using TaPL as textbook will tell the students to pick a toy language to implement.

chromatic: I haven’t seen you pop up much in Perl 6 land though. You seemed amazingly productive in the Perl 5 world. Where’d Perl 6 come in?

Autrijus: As an exercise. I started using Perl 6 as the exercise. I think that answers the first question.

Oh. p6 land.

chromatic: More of a playground than a full land, but we have a big pit full of colorful plastic balls.

Autrijus: Yeah, I was not in p6l, p6i or p6c. However, the weekly summary really helped. Well, because I keep hitting the limit of p5.

chromatic: It seems like an odd fit, putting a language with a good static type system to use with a language with a loose, mostly-optional type system though.

Autrijus: Most of more useful modules under my name, (including the ones Ingy and I inherited from Damian) were forced to be done in klugy ways because the p5 runtime is a mess.

chromatic: You should see Attributes::Scary. Total sympathy here.

Autrijus: Template::Extract uses (?{}) as a nondet engine; PAR comes with its own perlmain.c; let me not mention source filtering. All these techniques are unmaintainable unless with large dosage of caffeine.

chromatic: Yeah, I fixed some of the startup warnings in B::Generate a couple of weeks ago…

Autrijus: Cool. Yeah, B::Generate is abstracted klugery and may pave a way for Pugs to produce Perl 5 code.

chromatic: Parrot has the chance to make some of these things a lot nicer. I’m looking forward to that. Yet you took off down another road.

Autrijus: Actually, I think Pugs and Parrot will meet in the middle. Where Pugs AST meets Parrot AST and the compiler is written in Perl 6 that can then be run on Parrot.

chromatic: I thought Pugs would get rewritten in C for Parrot?

Autrijus: No, in Perl 6.

chromatic: Can GHC retarget a different AST then?

Autrijus: It can, but that’s not the easier plan.

chromatic: It’s easy for me. I don’t plan to do it.

Autrijus: The easier plan is simply for Pugs to have a Compile.hs that emits Parrot AST. Which, I’m happy to discover yesterday, is painless to write. (Ingy and I did a KwidAST->HtmlAST compiler in an hour, together with parser and AST.)

chromatic: Kwid and HTML, the markup languages?

Autrijus: Yeah.

Ok. So back to p6. P5’s limit is apparent and not easily fixable

chromatic: It sounds like you wanted something more, and soon.

Autrijus: Parrot is fine except every time I build it, it fails.

chromatic: Try running Linux PPC sometime.

Autrijus: Freebsd may not be a good platform for Parrot, I gathered. Or my CVS luck is really bad. But I’m talking about several months ago.

chromatic: 4.x or 5.x?

Autrijus: 5.x.

chromatic: Ahh, perhaps it was ICU.

Autrijus: Two out of three times is. I think.

chromatic: I guess it’s too late to interest you in a Ponie then.

Autrijus: I was very interested in Ponie. I volunteered to Sky about doing svn and src org and stuff, but svn was not kind for Ponie.

obra:Well, that was before svn 1.0

Autrijus: Right. Now it all works just fine, except libsvn_wc, but we have svk now, and I learned that Sky has been addicted to svk.

But anyway. And the beginning stage of Ponie is XS hackery which is by far not my forte. I’ve read Lathos’ book, so I can do XS hackery when forced to but not on a volunteer basis. Oh no.

chromatic: That’s a special kind of pain. It’s like doing magic tricks, blindfolded, when you have to say, “Watch me push and pop a rabbit out of this stack. By the way, don’t make a reference to him yet….”

Autrijus: So, on February 1, when I had too much caffeine and couldn’t sleep, I didn’t imagine that Pugs would be anything near a complete implementation of Perl 6. I was just interested in modeling junctions but things quickly went out of control. And some other nifty things like subroutine signatures.

chromatic: There’s a fuzzy connection in the back of my head about Haskell’s inferencing and pattern matching being somewhat similar.

Autrijus: Sure. Haskell has very robust inferencing, pattern matching, and sexy types. Which I’m trying to inflict on luqui to improve Perl 6’s design.

chromatic: As long as they do the right thing with regard to roles, go ahead.

Autrijus: They do. :)

chromatic: This was an academic exercise though?

Autrijus: Yeah. It stayed as an academic exercise I think for two days.

chromatic: “Hey, this Perl 6 idea is interesting. I wonder how it works in practice? I bet I could do it in Haskell!”

Autrijus: Yup. Using it as nothing more than a toy language to experiment with, iitially targeting a reduced set of Perl 6 that is purely functional. But by day three, I found that doing this is much easier than I thought.

chromatic: Did you say “highly reduced”?

Autrijus: Yeah. Term is “featherweight”.

chromatic: What makes it easier?

Autrijus: Parsec and ContT. Parsec is like Perl 6 rules.

chromatic: Parsec’s the most popular Haskell parsing library, right?

Autrijus: Well, Parsec and Happy. Happy is more traditional; you write in a yacc-like grammar thing and it generates a parser in Haskell for you. Parsec is pure Haskell. You just write Haskell code that defines a parser. The term is “parser combinator”.

chromatic: Haskell is its own mini-language there.

Autrijus: It’s a popular approach, yes. When you see “blah combinator library”, think “blah mini-language”.

chromatic: I looked at the parser. It’s surprisingly short.

Autrijus: And yet quite complete. Very maintainable, too.

chromatic: Now I’ve also read the Perl 5 parser, in the sense that I picked out language constructs that I recognized by name. Is it a combination parser/lexer, or how does that work? That’s the tricky bit of Perl 5, in that lexing depends on the tokens seen and lots of context.

Autrijus: Yup. It does lexing and parsing in one pass, with infinite lookahead and backtracking. Each lexeme can define a new parser that works on the next lexeme.

chromatic: Does that limit what it can do? Is that why it’s purely functional Perl 6 so far?

Autrijus: The purely functional Perl 6 plan stops at day 3. We are now fully IO. Started with say() , and mutable variables, and return() , and &?CALLER_CONTINUATION . So there’s nothing functional about the Perl 6 that Pugs targets now :).

chromatic: Does Haskell support continuations and all of those funky things?

Autrijus: Yes. And you can pick and match the funky things you want for a scope of your code. “In this lexical scope I want continuations”; dynamic scope, really. “In that scope I want a logger.” “In that scope I want a pad.”

chromatic: Performance penalty?

Autrijus: Each comes with its own penalty, but is generally small. GHC, again, compiles to very fast C code.

chromatic: Can you instrument scopes at runtime too?

Autrijus: Sure. &?CALLER::SUB works. And $OUTER::var .

chromatic: Are you compiling it to native code now? I remember that being a suggestion a few days ago.

Autrijus: Pugs itself is compiled to native code; it is still evaluating Perl 6 AST, though.

chromatic: It’s like Perl 5 in that sense then.

Autrijus: Yes, it’s exactly like Perl 5. Have you read PA01?

chromatic: I have.

Autrijus: Cool. So yeah, it’s like Perl 5 now. The difference is B::* is trivial to write in Pugs

chromatic: Except maintainable.

Autrijus: And yeah, there’s the maintainable bit. Pugs is <4k lines of code. I think porting Pugs to Perl 6 will take about the same number of lines, too.

chromatic: You already have one module, too.

Autrijus: Yup. And it’s your favorite module.

chromatic: I’ve started a few attempts to write Test::Builder in Parrot, but I’m missing a few pieces. How far along are classes and objects in Pugs?

Autrijus: They don’t exist. 6.2.x will do that, though. But the short term task is to get all the todo_() cleaned. which will give us an interpreter that really agrees with all synopses. At least in the places we have implementation of, that is.

chromatic: I see in the dailies that you are producing boatloads of runnable Perl 6 tests.

Autrijus: Yup, thanks to #Perl6. I seldom write tests now :) The helpful committers do that for me.

chromatic: How do you know your code works then?

Autrijus: I just look at newest todo_ and start working on it.

chromatic: Oh, they write tests for those before you implement them?

Autrijus: Yup. It’s all test-first.

chromatic: Okay, I’ll let you continue then.

Autrijus: Ha. So yeah, the cooperation has been wonderful. Camelfolks write tests and libraries, and lambdafolks makes those tests pass. If a camelfolk wants a particular test to pass sooner, then that person can learn from lambdafolk :). Things are easy to fix, and because of the coverage there’s little chance of breaking things. If lambdafolks want to implement new things that may or may not agree with synopses or p5 norm, then they learn from camelfolks.

chromatic: Have you started giving Haskell tutorials? I know Larry and Patrick have started to pick up some of it. I’m pretty sure Luke and Damian have already explored it (or something from the same family tree).

Autrijus: I think I’ve read a paper from Damian that says he taught Haskell in monash. It’s before the monadic revolution though.

chromatic: If not Haskell, certainly something from the ML family.

Autrijus: Right. So, I’ve been pointing people to YAHT and #Haskell.

chromatic: It sounds like you’re attracting people from both sides of the fence then.

Autrijus: It indeed is. I get svn/svk patches and darcs patches.

chromatic: Is there a lot of overlapping interest? Where does it come from?

Autrijus: Well, ever since the monadic revolution of ‘98 Haskell people have started to do real world apps.

chromatic: Now that they can do IO, for example.

Autrijus: Yeah. It’s been only 7 years ago. And recently Haskell world has its native version control system; a Perl-review like magazine, cpan/makemaker-like infrastructure, etc. So it’s growing fast.

chromatic: There’s still a lot of attraction there for real world applications, of which Pugs is one?

Autrijus: Pugs is a practical project in that working on it has a chance of solving real problems, and is very fun to boot. And although p5 got no respect, in general p6 is very slick. So the mental barrier is lower for lambdafolks to join, I think.

chromatic: The lambdafolks like what they see in Perl 6?

Autrijus: Yup. I quoted Abigail on #Haskell a while ago.

chromatic: I saw something earlier about access to libraries and such. Do you have a plan for the XS-alternative?

Autrijus: Yeah, Ingy is working on it ext/Kwid/ eventually inline Haskell code. And with luck, inline other kinds of code as well through Haskelldirect (the Haskell equiv of Inline).

chromatic: Is this within Pugs or Perl 6 atop Pugs?

Autrijus: It’s within Pugs. The Parrot side had not been well-discussed.

chromatic: Yeah, the Parrot AST needs more documentation.

You’re devoting a lot of time to it. Obra mentioned that you’ve cleared most of your paying projects out of the way for the time being. What’s the eventual end?

Autrijus: And whither then? I cannot say :). As you mentioned, I’ve diverted most of my paying projects away so I should have at least 6 months for Pugs.

chromatic: How about in the next month?

Autrijus: This month should see robust semantics for basic operations, the beginning of classes and objects, and many real modules hooks to Haskell-side libraries.

chromatic: I’ll do T::B then.

Autrijus: Oh and Pugs hands out committer bit liberally so if you want to do T::B, I’ll make you a committer :). You can start now actually. Just write imaginary Perl 6 code, and we’ll figure out how to make it run. Most of the examples/* started that way.

chromatic: Ah, I’ll take a look.

Autrijus: Oh. Right. I was quoting Abigail.

“Programming in Perl 5 is like exploring a large medieval castle, surrounded by a dark, mysterious forest, with something new and unexpected around each corner. There are dragons to be conquered, maidens to be rescued, and holy grails to be quested for. Lots of fun.”

“Perl 6 looks like a Louis-XVI castle and garden to me. Straight, symmetric, and bright. There are wigs to be powdered, minuets to be danced, all quite boring.”.

I, for one, am happy for Perl to move from the dark age to the age of enlightenment. I think many camelfolks and lambdafolks share the same sentiment :).

chromatic is the author of Modern Perl. In his spare time, he has been working on helping novices understand stocks and investing.