Initial commit: HPR Knowledge Base MCP Server
- MCP server with stdio transport for local use - Search episodes, transcripts, hosts, and series - 4,511 episodes with metadata and transcripts - Data loader with in-memory JSON storage 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
687
hpr_transcripts/hpr0321.txt
Normal file
687
hpr_transcripts/hpr0321.txt
Normal file
@@ -0,0 +1,687 @@
|
||||
Episode: 321
|
||||
Title: HPR0321: Parrot
|
||||
Source: https://hub.hackerpublicradio.org/ccdn.php?filename=/eps/hpr0321/hpr0321.mp3
|
||||
Transcribed: 2025-10-07 16:19:54
|
||||
|
||||
---
|
||||
|
||||
music
|
||||
The Utah Open Source Foundation brings the Utah Logs home.
|
||||
Feel free to listen live at stream.utos.org or catch the audio afterward at podcast.utos.org.
|
||||
The bandwidth is provided by Center 7.
|
||||
The following presentation, Parrot, was given on March 11, 2009 by Stephen Weeks at the
|
||||
Provo Linux user group.
|
||||
Visit their site at plug.org.
|
||||
Wow.
|
||||
Wow.
|
||||
Happy.
|
||||
Hello.
|
||||
Let's see if this works again.
|
||||
My ex-server wouldn't wake up.
|
||||
What?
|
||||
I'm not sure.
|
||||
No.
|
||||
I'm not sure if it works.
|
||||
I don't know.
|
||||
I'm not sure.
|
||||
I'm not sure.
|
||||
I'm not sure.
|
||||
I'm not sure.
|
||||
Oh, I'm not sure.
|
||||
I'm not sure.
|
||||
I'm not sure.
|
||||
I'm not sure.
|
||||
I'm not sure.
|
||||
I'm not sure.
|
||||
I'm not sure.
|
||||
I'm not sure.
|
||||
I'm not sure if it works.
|
||||
Maybe we could, kittens or adults?
|
||||
Or could we wake up?
|
||||
And I was trying to log in again.
|
||||
It was working before.
|
||||
I'm here from Guru Lab's Parrot is really cool, so excited about Parrot.
|
||||
Parrot is a, it's a virtual machine for dynamic languages and video settings.
|
||||
And it's also a set of compiler tools on top of that, let me see, let's click here and
|
||||
just say, no, don't be disabled, shut up.
|
||||
Yes, this is how I teach all the time.
|
||||
I shout profanities at my laptop, that's, whoa, am I, that will have to be good enough.
|
||||
Now my display right here is very, very tiny, doesn't show as much as up there does, it's
|
||||
interesting.
|
||||
But I don't have an ATI card, I have zero ATI cards.
|
||||
I'll just look up there, how the work.
|
||||
Clint doesn't have to be nice.
|
||||
Anyway, right, I was saying things, sorry, a bit flustered, I'm also a bit sick, so if
|
||||
I fall on the ground coughing, just leave me for a minute, I'm sure I'll be fine.
|
||||
So Parrot, like I was saying, Parrot is a virtual machine for dynamic languages and it's also
|
||||
a set of compiler tools for building your own compiler for Parrot.
|
||||
One of the main goals of Parrot is to be able to allow all these different languages to
|
||||
interoperate with each other.
|
||||
You write your Ruby script, we're getting there, right now, at this very moment, most of
|
||||
that doesn't work because most of the languages library is, well, we're getting ready for
|
||||
our release in six days, six days will be the Parrot 1.0 release, which is good.
|
||||
How many people here know anything about Parrot, read about it, looked at it, okay.
|
||||
So the main thing I'm going to present on here is I wrote a little scheme compiler in
|
||||
Parrot and we're going to run through how to build the compiler and implement scheme.
|
||||
I had this prepared in advance and I apparently deleted it, I'm not sure, it wasn't on my
|
||||
laptop as of midnight last night.
|
||||
So I wrote it again in about three hours today, so that's good.
|
||||
These penguins here, the goal for these penguins is if you wanted a penguin, you have to
|
||||
ask me a question during my presentation.
|
||||
Your question is going to be if you can have a penguin, isn't it?
|
||||
That's a meaningful question, too.
|
||||
So any questions before I get started here?
|
||||
It might be one on IRC.
|
||||
It might be, I should, I could try to pay a tanking IRC.
|
||||
Yeah, that's good.
|
||||
Apparently he raised his hand but he doesn't ask the question so we'll wait.
|
||||
That's good.
|
||||
All right, so let's talk about Parrot.
|
||||
All right, so the very first thing I did to try to build this compiler is around this.
|
||||
There's this little tool of make language shell and go ahead and just run a Parrot slash
|
||||
live slash one to bell, tools, dev, that's not right, I don't care, anyway, get it, check
|
||||
it out, one.
|
||||
Here we are, creates this little directory for you, it's got the very basics implemented.
|
||||
It's with little test, which all this language is, is just say statement.
|
||||
It's the word say, followed by some text and a semicolon.
|
||||
So we can compile this, see if it works, then I'll show you a little bit about what we
|
||||
have here.
|
||||
All right, so if I run a Parrot on this steam.pbc, that's for Parrot bytecode, that's the
|
||||
compiled bytecode repeating myself here, run it on, it's yours or say, so it apparently
|
||||
works.
|
||||
All right, so let's walk through the different stages of this compiler, the very first stage
|
||||
is going to be the parsing, so we need a grammar here, so let's source, parser, grammar.pg
|
||||
or program, these are purl six rules, kind of like regular expressions, and so it's
|
||||
got comments here in pod, which is purls, markup, purls, commenting stuff, so you're going
|
||||
to find a grammar, it inherits from the PCT grammar, PCT is the Parrot compiler tools.
|
||||
All right, so we start off with a rule, it's kind of like a regular expression, there are
|
||||
two things here, rules and tokens.
|
||||
The difference is that in rules, white space is significant, any section of white space
|
||||
is replaced with a call to the WS rule, and so it's white space in your rule here represents
|
||||
white space in what you're trying to parse, right, which it'll work out, doesn't matter
|
||||
that much, we'll see it in a minute, anyway, so we want to parse inside of angle brackets
|
||||
is calling a named other rule, right, so it calls the statement rule, which if we look
|
||||
down here, that's the liberal text, say, followed by an expression, find later on, followed
|
||||
by a comma, another expression, any other, most of you familiar with regular expressions
|
||||
to some degree, vaguely kind of shut up.
|
||||
If anything I'm talking about just makes no sense to you at all, just throw something
|
||||
at me, or shout angrily, or let me know somehow, or, no, not at me, it's no things at
|
||||
pause, so, but care, anyway, calls the expressions, goes on like that, pretty straightforward, it's
|
||||
a pretty simple syntax, I'm not going to get into it too much with this, we'll talk about
|
||||
the scheme syntax, which I'm going to show you in just a minute, let's just go ahead
|
||||
and move to that, whenever moving along too quickly, or, I'll just trust you guys to
|
||||
harass me appropriately, anyway, the changes that I made here, right, a statement, which
|
||||
this top rule that's where it comes in, it starts parsing here, so any number of statements
|
||||
is a valid program, and after that it's either, the end of the string, so the dollar sign
|
||||
means is the end, or it panics, or they syntax error, so just bail out, so first we start
|
||||
with an open parenthesis, it's going to be a symbol, which I define all the way down
|
||||
here as just the built-in little thing identifier, which is, you know, ASCII, I'm sorry, a word
|
||||
character, letters, numbers, alpha numerics, that's what I was going for, some number of
|
||||
those, and I'm giving it the name, CMD for a command that you're running on scheme, right,
|
||||
the scheme syntax, hopefully all familiar with this, ASXpressions, so that'll be something
|
||||
like, you know, print, hello, right, something like that, it's going to be your scheme, vaguely,
|
||||
I don't actually delete no scheme, so this is based on little tutorials and grammar
|
||||
references and such, and then some number of other terms, which I'm going to find down
|
||||
here, become down a term, this leading a bar that's an OR, usually you'd see that in
|
||||
some kind of grouping, there's no grouping, so this just means either it's a value, or
|
||||
it's a symbol, right, so match those value, we come up here, that's this rule, right, that's
|
||||
either an integer, which is defined right here, or a quotation, right, which is defined
|
||||
here using some built and stuff, that just means either an apostrophe or the double quotes,
|
||||
and then everything leading up to the trailing double product, so I am skipping over kind of
|
||||
a lot, if you want me to stop and go into anything that I skip over, again, let me know,
|
||||
right, and then it has to be a close, now this special little curly brace star,
|
||||
close curly brace, what this means is, this is a use when we're actually trying to
|
||||
transform our parse tree farther down, but let's get into that in just a minute, so first
|
||||
let's see if this works, right, let's see if this parses some basic stuff, all right, so
|
||||
let's recompile it, oh go away, I don't want that right now, that's my take typing
|
||||
breaks thing, so my hands don't hurt, let's run parrot on steam.pbc, whoops, and let's
|
||||
say dash dash target equals parse, so let's see what happens, what it spits out when we
|
||||
give it a little expression, right, so let's say say hello, oh, and that's worked earlier,
|
||||
aha, did work earlier today, what's, what, since when, it's interesting, oh, oh this is going
|
||||
to be nice, let's see if it works anyway, what does work, so there's that, but no dump, oh,
|
||||
I guess it does work now, yeah, don't worry about it, I don't care, anyway, this is our parse
|
||||
tree, right, and so it takes the entire, except from that regular, from those rules, and it says,
|
||||
well here's the entire parse, was this text right here, say hello, well that contains one
|
||||
statement, which is, this right here, say hello, that contained a CMG, you remember earlier,
|
||||
I assigned that name right, see here, CMD equals, and call the symbol rule, so CMD contains an
|
||||
identifier, which was, say, there's also one term here, which, well that was a repetition, right,
|
||||
it's got that star, so that's inside of an array, of size one, which contained a value,
|
||||
which was a quote, which was a string literal, which was, hello, is this parse tree pretty
|
||||
clear for everyone, right, this is just the, well, not repeating myself again, right, so yes,
|
||||
how many people have written parses? I don't know, oh, I don't know, oh you were asking them,
|
||||
not me, you're clever man, I haven't implemented any sort of compiler, well, a little bit for other
|
||||
stuff, I like this a lot better than some of the other options for parsers, so anyway, the next
|
||||
step is to take that, I just set up a bunch of aliases right here, all that is, is steamed
|
||||
as just hard equals parse, saves me on type, right, so we want to compile this down, the next
|
||||
step is an abstract syntax tree, so we're going to see, can everyone read this font size
|
||||
comfortably? All right, so what we want is just an abstract representation of the sort of
|
||||
things we want to do, right, this is going to be very high level view of our program, it's going
|
||||
to be things like run a command with these arguments, right, so the next layer down, let me show you
|
||||
what that looks like, this is a past block, past tense for parrot abstract syntax tree, there's a bunch of
|
||||
classes in that namespace, right, we've got blocks, we've got operations, variables, values,
|
||||
right, so we're saying that this is a block, is our entire program, and that's a declaration of
|
||||
the par, we'll get into that in a minute, this is an operation, the type of operation is call, so a
|
||||
function call, and this has two sub nodes, right, all of these nodes, all of these past nodes have two
|
||||
parts, they have named parameters, you can see in here, so it's kind of like a Python dictionary or
|
||||
purl hash, and there's also positional items, so this is kind of like a, both the hash and an array
|
||||
together, or a dictionary and an array together, so the two items in here are a past var, right, so a new
|
||||
variable, whose name, the name of the variable is say, and its scope is package scope, kind of like
|
||||
global scope, I don't look in the namespace, and the past value is hello, so call the save function,
|
||||
which is in our global namespace on the text hello, is that pretty, pretty clear, any question
|
||||
now what this is doing, all right, so the way we get the, the way we get there is the compiler is
|
||||
actually calling, every time it gets to one of these little curly brace, star, close, curly brace,
|
||||
it calls a function often in other namespace, and it passes it this entire match, and then that
|
||||
other function constructs those objects, right, so in this top rule, what it does is it says, oh well,
|
||||
this is my entire program, so I'm going to make a block, I'm going to shove every item in there
|
||||
as a statement in that block, right, as an operation, and so we see that's exactly what it is right here,
|
||||
method top, it accepts this dollar sign slash, now this file here is written in a subset of
|
||||
purl six, called not quite purl, it's a very restricted purl six, and so it doesn't support a lot
|
||||
of the, a lot of the fancy things, just the basic syntax, for example it doesn't have assignment,
|
||||
it only has binding, just kind of like a, by reference instead of by value, so we see right here,
|
||||
it's accepting this dollar slash, that's the match object, and so that that's, everything
|
||||
goes in there, when we said target equals parse, and it printed that out, that's the object that
|
||||
this thing gets, so what we're going to do here is we're going to create and bind this variable,
|
||||
the difference between assignment and binding isn't that much that you really need to care about,
|
||||
it just means it doesn't get a new copy, it's just they're all pointing to the same data structure,
|
||||
going to create a new pass block, so passblock.new, this colon and the word followed by parentheses,
|
||||
that's purl six is a named argument passing, so we're going to create a block with block type
|
||||
declaration, and this node thing here, that's for introspection, right, where it said,
|
||||
right here, where it can tell what was going on here, right, this pass over is created from,
|
||||
or this, some other stuff, yeah, not actually important, that's just extra stuff, anyway,
|
||||
so we're going to iterate over, right, remember the statements, we're in array, right, it's,
|
||||
our statements are in array, right, because of any number of them, so we iterate over them,
|
||||
for each statement, you're going to push into it, right, because this block has a list of
|
||||
statements, and a list of things it's going to do, now again we have some special syntax,
|
||||
right, this is not quite purl, it's used here, it's mostly just special idioms, right,
|
||||
this dollar sign parentheses means that this, if you haven't worked with purl, the dollar sign
|
||||
underscore, that's the current topic, right, so for each time goes through this for loop,
|
||||
it's, this dollar sign underscore is set to each item in there, don't bother with the name,
|
||||
because we're not doing much special with it, so this dollar sign parentheses means get the syntax
|
||||
tree representation of each of these objects, right, so, so go ahead and compile the syntax tree
|
||||
for each one of those statements, and then give it back to me, and push it inside of this block,
|
||||
right, so if I had multiple of those, right, I can go ahead and do that,
|
||||
you know, say one, say two, we have two past ops, right, two operations in term,
|
||||
pretty straightforward, and these are children at the block, so we've gone through this a little bit more,
|
||||
we won't go through the whole thing unless someone asks me to, there's, well we'll get to it eventually,
|
||||
right, so it's going to call the rule for those statements, right, so that's method statement,
|
||||
again it accepts a match object, this says I want to create a new past op, right, an operation,
|
||||
right, like a function call or a method call or something like that, on, again we see this dollar sign
|
||||
so get the syntax tree of this, right, of this CMD thing, which is a symbol, and so we can chase that
|
||||
down, come down here and see that for symbols, right now I'm doing, say make a new past variable,
|
||||
whose name is, whatever was in the ident, part of the match, and whose scope is packet, so a
|
||||
globally scope variable, right, and I'll show you in a little bit where that save function is defined,
|
||||
it's not just magic, we'll get to it, all right, so inside the statement,
|
||||
new past op, that past type call, so call that function, and for each one of those terms,
|
||||
I remember term again was any number of these, push those into the op, okay, pretty straightforward,
|
||||
and then the make command means set this as the syntax tree representation for this node,
|
||||
it's kind of like return, it's slightly different for some reasons we're not going to get into,
|
||||
but you can think of it as just returning it back into one of these calls here, right, that's what
|
||||
that is, so any questions about how this is working, how this compiles that, that parse tree
|
||||
down into a syntax tree, all right, so now parrot takes that abstract syntax tree,
|
||||
next step it goes to is it compiles it down into a, well, couple steps, it compiles it down
|
||||
into peer essentially, which is the parrot intermediate representation, that's essentially a
|
||||
parrot's version of assembly, right, so I say say hello, it says dot sub create a new subroutine
|
||||
with some garbage out here that we don't care about, so what we're going to do is we're going to
|
||||
look in the global namespace, fetch it into a register, my parrot is a register based virtual
|
||||
machine, not a stack based virtual machine like many others, who has done any kind of assembly
|
||||
stuff, all right, so look up with this string say, and then we're going to save the result of
|
||||
calling this function with the value hello, and then we're going to return it, so that's all it
|
||||
does, right, pretty straightforward, any questions so far about how this works, all right, no questions,
|
||||
oh, I guess I'll keep my penguins to myself, all right, so let's start implementing a little bit
|
||||
more, this is a little not exciting, so let's check out next step, right, some basic math operations,
|
||||
nested expressions, so let's see what we changed in here, first thing we changed, we're defining
|
||||
more of these, right, in this built-ins directory, the make file compiles, you know, concatenates them
|
||||
all together and then includes them in the bytecode, so let's take a look at these, all right,
|
||||
the one we already have was that say function, the source built-ins say dot peer, this is just dot sub say,
|
||||
we want to accept one parameter, which just slurps up, right, it accepts as many parameters,
|
||||
sorry, as many arguments as we pass to it, it solves them inside of an array here called args,
|
||||
yeah, that's a modifier to this, right, it says, yeah, that basically says for the calling
|
||||
conventions, however many arguments are passed, just shove along into an array and put them inside
|
||||
of this variable here, this is written in peer, it's a parrots assembly language,
|
||||
so it's not, I mean, it looks kind of a little bit like, it's very high level for an assembly
|
||||
language, so we create a new, we sign a name, parrot has four different kinds of registers,
|
||||
right, there has four different kinds of registers and you see what the dollar sign out in front
|
||||
for reasons we don't get into, but then it's a capital letter and a number, or four different
|
||||
kinds of registers, there's PMs, well there's integers, right, so a whole number, there's
|
||||
num registers, which are a float, right, there's string registers which contain some amount of text,
|
||||
there's PMC registers, sensor parrot magic cookie, which basically means an object, right,
|
||||
some sort of high level object, it could be an array, it could be a socket, it could be, you know,
|
||||
some custom user class that you've made, it could be anything else, right,
|
||||
and so this is just giving a name to a PMC register called it, it create a new object of the iterator
|
||||
class, pass these args, and then just loop over it, keep pulling something out, printing it,
|
||||
and then looping back, print a new line, and then we're done, so you define this little built-in,
|
||||
once you get most of your language up a bit higher, you can start, you know, of course,
|
||||
defining your libraries in terms of, you know, actually writing them in their own code, the
|
||||
parrot's purl six implementation, for example, has a decent amount that's written in purl six itself,
|
||||
I think, I think their PHP implementation might be doing a little bit of that, I'm not sure,
|
||||
or a few others, anyway, we also added this math.purify, I'll just define some little basics,
|
||||
so we create a subroutine called plus, which will add two values, we create a subroutine called minus,
|
||||
which will subtract them, star from multiply, slash for divide.
|
||||
These are actually op-codes already.
|
||||
Yeah, that's what I'm saying, so you have to define those in a subroutine.
|
||||
Right, this is a very high-level assembly language, which is kind of fun,
|
||||
and what else do we do in here?
|
||||
So we add those, and change the grammar a little bit around, I made it so that a term could
|
||||
also be a statement, right, which you remember statement is a full-ass expression,
|
||||
and I also changed the symbol rule to instead of just be alpha numeric to be any character other
|
||||
than white space and parentheses, so that I can actually call the plus function and things like that.
|
||||
All right, so if I compile this, I can then run it, and we'll say say plus one two.
|
||||
Okay, pretty straightforward. Also, with each of these, I've been updating the tests,
|
||||
right, so I now have that this is the tap format, what is it, the test anything protocol,
|
||||
choose a law in the purl world, just print out the number of tests, and then okay one, okay two,
|
||||
okay three, okay four, right, so if I make tests, it runs, T slash zero zero sanity, okay,
|
||||
all tests successful. How do I actually just run steam on the file, it prints everything out?
|
||||
Let's work on okay so far. Yeah.
|
||||
Do you have to do like pause convention, excuse me, the drag?
|
||||
In steam? Yes. Parrot actually has, and this is one reason that I kind of was a little unsure
|
||||
about using steam for this, but actually has an additional way that you can use its parsing engine
|
||||
to do bottom up parsing instead, so you actually just define a table of operators, right?
|
||||
You define, well here, here I've got my infix plus, and I've got my prefix, you know minus to
|
||||
do negatives, and they're all, you know, the infix plus is higher precedents or lower precedents,
|
||||
and the infix multiply, and then you just define all those rules, and then you say can be a token
|
||||
here, and we'll go through and just parse out, you know, all that infix math and all of that,
|
||||
so there is some really nice stuff for that. If we have time at the end, we can go into that too,
|
||||
as well, if someone wants. Someone asked a question, he gets a penguin.
|
||||
All right, so what comes next? I don't even remember what order I did these in.
|
||||
Up until now, I think I got about here by 1am this morning, four should come next.
|
||||
Yes, yes, I got through to this part by 138, so implementation of the special form if,
|
||||
right, which is just, you know, if, and then you have some condition, right,
|
||||
if 1 is less than 2, then do this, otherwise do that. This is what it looks like in scheme.
|
||||
Pretty straightforward, so let's actually take a look at what we changed here.
|
||||
All right, so I added some comparison functions, let's take a look at those.
|
||||
All right, I did sub equals. If they, if these two are equal, then jump to the true label,
|
||||
which is down here, and return one. Otherwise, just fall through and return zero.
|
||||
Same thing for less than greater than, less than or equal, greater than or equal.
|
||||
You see, I'm just using these built-in parrot ops, which are, again, it's a very high-level language,
|
||||
or assembly language. And we also did, right, there we go. I'll just pull it up.
|
||||
Instead of the, whoops, instead of the diff, and what we have here is I changed the statement rule
|
||||
to first check for one of the special forms, which have their own special parsing rules.
|
||||
For example, instead of just like a function call, you don't want to evaluate both branches first
|
||||
to pass the argument in. That would be bad if you evaluate both branches of the conditional.
|
||||
So we check them both and only evaluate the one that's appropriate.
|
||||
If it doesn't match any of those, then we call the simple rule, which is just what it was before.
|
||||
So the special right down here, well, that's just the if rule. Now, one thing that you'll
|
||||
see right here in a few places, this hash equals, then a word, that's when something could match
|
||||
in a variety of different ways. And you want the parser engine to actually tell you which it was.
|
||||
So the way that's actually implemented is down here in the statement rule,
|
||||
and now except a second parameter here, which is a key. And that's which one of those
|
||||
things actually matched, right? So what I do is I take, you know, just return the syntax tree for
|
||||
the key named sub match of dollar slash, which is the match. So just actually return by far,
|
||||
it's just the same thing that's in here. So it just tells you it matched simple instead of
|
||||
special or special instead of simple, to simplify your rules there. Fun losing you that's not
|
||||
too important. We'll see it again a few times. So it comes out here, tries to match if,
|
||||
for if that's the literal text, if, and then one term, another term and a third term. So I'm
|
||||
just naming them condition, if it's true, if it's false. And then we call this, right? If you're
|
||||
just doing matching, right, if you're just trying to do, you know, the equivalent of regular
|
||||
expression, you don't need to do anything special with it, you don't need this special curly thing,
|
||||
right? So let me show you what, if, implements. So you have method if, that makes a new past operation,
|
||||
it creates a new one. The three arguments are the condition, if it's true, and if it's false.
|
||||
And then the past type, I saw earlier, right down here for a simple, so that's just a past type of
|
||||
call, it's a function call. This past type is if, for doing conditionals, right? The
|
||||
paracompilot will provide a lot of default implementations that make a lot of sense. We can
|
||||
actually take a look at the documentation, docs, d, pdd, 26, st. It's also in some more reasonable
|
||||
path, but that's the one I actually remember. So we look for past op, that can be past type of
|
||||
copy, bind, or if the first, second, and third children represent the condition, the then,
|
||||
and the else parts of a conditional expression. First, child's evaluated, if it's true, then the
|
||||
second's evaluated, if it's false, and the third's evaluated. Pretty straightforward.
|
||||
So we can actually see that, that's what the syntax tree looks like. We compile it,
|
||||
we see if it works, we say, say, if, one is less than zero,
|
||||
hello, hello, or goodbye. But if one is greater than zero, we say, hello, okay. Let's do a
|
||||
dash dash target equals past, and we see it did actually make a past op of if, that's a child
|
||||
of past type call, so call the save function on this past op. If you want to look at the
|
||||
period generates, that's just target equals peer, if less than one zero, hello, or goodbye.
|
||||
We see it get global that, if this jump to this value down here, and then go on and run these,
|
||||
otherwise, make a goodbye, and then jump down to the end where it returns it. So that's what it
|
||||
will generate for each one of these. It's pretty straightforward, completely losing you, and
|
||||
because it was more typing. And I can do the same thing here.
|
||||
Right. So in this case, the first get global say, then to the end down here, it calls this function,
|
||||
which are retrieved up here, and it calls this function on which ever value it did here,
|
||||
so I decided to set it to this or set it to that, and call the function on it.
|
||||
So any questions so far about this? Pretty clear? All right. So the rest is just
|
||||
implementing more of the special forms. So just adding more to our scheme compiler.
|
||||
I think next is five? Whoa, I apparently can count. No, that's the same one. Oh wait, no, that was
|
||||
previous. We'll skip that one for now. Okay, we define works, that's actually setting new variables.
|
||||
Oh, oh way. Ah, right. And so we first make a grammar change, right? Here in our special rule,
|
||||
say it could also be a define. And what that looks like is inside of the parentheses, right? Because
|
||||
remember, special is called from something that says parentheses. So inside it, ask expression,
|
||||
it starts with the literal text, define. And then I added some stuff here for error checking,
|
||||
and I pulled it out later, so it doesn't matter much. But basically it's just define, and then
|
||||
a variable you want to create, and what you want to set it to. Pretty straight forward, right?
|
||||
And that in scheme is just define a as one. So let me show you what the grammar rule for that
|
||||
looks like. It just says my variable, going to bind it to the syntax tree for variable, right,
|
||||
for that match. And then I also set this is decal. That says, this is a declaration. I'm creating a
|
||||
new variable here, right? It's not something that already exists, so don't try to fetch it,
|
||||
just create a new one. And my value, that's that. So now we make a past op, the past type bind,
|
||||
right? So actually do an assignment to this value, assign to the variable, the value.
|
||||
Pretty straight forward. So we can try this, right? There are make, define, message.
|
||||
Thank you, Clint.
|
||||
Hello world. Say the message. It works. Fantastic, right?
|
||||
Oh, I made some tests for if and for define, we run make test, we see they all pass.
|
||||
See the if test pass prints out, define test prints out.
|
||||
Pretty straightforward. If you want to actually look at the syntax tree for that,
|
||||
right? You say steam dash dash target equals syntax tree, define a as one.
|
||||
So you see it just calls bind a newly declared variable named a, that's in package scope,
|
||||
but it got that from that symbol rule, right? Which creates a new variable nodes here.
|
||||
And then it turns a new integer, right? Any questions about this? We okay with this?
|
||||
Want me to look at anything more and more depth? Want to sit there quietly? Your face is staring
|
||||
ominously. Okay. What's that? Oh, sure. Oh, below the assembly level.
|
||||
Para compiles it down to what's called a PVC file, which is para byte code. So just compiles
|
||||
it down to the actual binary representation of the op codes. And such.
|
||||
So we can actually print it out like that. Well, we can actually do this,
|
||||
that's that's a way.
|
||||
I don't bother with it. Yeah, you can actually compile down your individual programs
|
||||
down to a PVC. And so you don't need to strip your source with it or anything like that.
|
||||
You can just run the PVC directly, right? I wonder to do something like that.
|
||||
Well, that's just target equals peer. I'll put you defined there. And there's a little bit that
|
||||
I'll need to change in here because I'm not generating it properly. Load byte code,
|
||||
steam.pbc. You're on parodon it directly. That'll print it out. We'll write out to define.pbc.
|
||||
So now we run parodon.byte code.
|
||||
And actually dump it out and see here's the header, which tells me the word size,
|
||||
all of that stuff. And down here's the actual op codes. All right.
|
||||
Here's the constants table, which is for the literal text and such.
|
||||
And so that is that is that is that about what you were asking about?
|
||||
All right. So let's see what I implemented next. I don't even remember.
|
||||
That was it. So that was now. 7th can count.
|
||||
Let. Let is for doing lexically sculpt variables, right? So set these variables for just this block
|
||||
and then they're gone. So it's kind of like many other languages you do with the curly braces
|
||||
or something like that or indentation and Python, that kind of thing.
|
||||
So let's actually show you what it's like. Again, it's pretty simple,
|
||||
but I do need to do things a bit differently, right? Now that we've got lexically sculpt variables,
|
||||
we need a way to actually track what's going on with them, right? See, you know, we need to maintain
|
||||
a symbol table to say these variables have been defined here, but later on they're not defined.
|
||||
So what we do is we're going to have this global variable of this at sign. Again,
|
||||
this is purl six. The at sign means it's an array, a list. The question mark means it's a global
|
||||
variable, right? So we're saying here's our package global variable called block and all capital
|
||||
letters to show that it's weird. What we're going to do in here is as we go through and create new
|
||||
blocks, they're nested inside each other, which is what let does, we're going to actually, you know,
|
||||
make a new block object and save it inside of this array, right? We're just going to, you know,
|
||||
shove it on the front, then every time we need to look at the current block, we'll just look at
|
||||
the start of this array. We can just walk the whole thing there, right? Right, exactly, exactly.
|
||||
And we also made a parsing change here, right? We're going to actually call this two times at the
|
||||
very beginning, right, which is first we need to set up this stack, make our block for the entire
|
||||
thing, and then again at the end, right? It was going to be called two times. So we see up here,
|
||||
if the key equals begin, then we want to set us that are variable here to a new past block,
|
||||
and we want to unshift it, it's purlish for, you know, shove it on the front, kind of like push,
|
||||
but on the front instead of the end. So unshift this block on there. At the end, we want to actually
|
||||
grab it off of the front. So we want to shift it off, like pop, but from the front,
|
||||
then iterate over the statements and push them onto it, and then return it, right?
|
||||
That's our change down here. Define, I actually had
|
||||
do it lexically in the current block instead of globals now. So when we pull the variable out,
|
||||
we set the scope on it to lexical. We also, right, first I grab my block out of
|
||||
that block sub zero. So the very first one on the stack, right? So the very most recent,
|
||||
and we call the symbol function on it, which is just a way to set some data in there, right? So we
|
||||
keep this symbol table around, which I'm all in storing it here is the name of the variable,
|
||||
and this is lexically sculpt, right? So later on, when we actually mentioned a symbol,
|
||||
we can actually go back and walk up the stack and see, well, is it defined lexically anywhere?
|
||||
If not, it must be a global variable, right? So try that instead. So we'll see that in a bit
|
||||
down here. So the way we define let, the grammar for that is right here. What the grammar actually
|
||||
looks like is let, the insider parentheses, we have a list of things inside parentheses. So we say
|
||||
a is equal to one, and b is equal to two, and c is equal to three. Then over here, we can do,
|
||||
you know, whatever you want, right? Say a, say b, right? That's what a let statement looks like.
|
||||
So it's kind of like, you know, just defining a block in some of the little, little bit different.
|
||||
Ah, I can't, yeah. So down here, what we do, oh, we also have the grammar for it.
|
||||
I didn't show it. So we say we first have an open parentheses, and then any number,
|
||||
well, at least one, the plus is like the star, but at least one instead of at least zero,
|
||||
of open parentheses, a symbol, excuse me, a symbol, which we save under the name var and a term,
|
||||
which we save under the name val, a closed parentheses, at which point, once we've parsed that much,
|
||||
go ahead and call it, right? So we create our block first and, you know, save things inside the
|
||||
symbol table. So the one we're out parsing the other statements, it has access to them. Then we
|
||||
parse any number of statements, and then we're done, right? Call it again.
|
||||
So the way we do this, right, we again use this, this global set of, you know, blocks at our little
|
||||
symbol table. So if the key is begin, and we create a new past block, block type of media,
|
||||
which means go ahead and run this right now, right? We're not defining some code, right? We're
|
||||
not defining a function or something. This is just inline stuff to actually do, and we're going to
|
||||
create a list of statements, which is like a block, but it doesn't make a new scope, right? So
|
||||
just a list of statements to hold stuff in. And then for each one of the variables, we defined,
|
||||
again, that's going to be a list, we want to save it inside, and we can actually look at the
|
||||
parse tree as we're doing this. Oh, I already did make it. All right, so we say let a1 and b2,
|
||||
then say a. Oh, that's bigger than I. Want it to be go get bigger. Yeah, there we go.
|
||||
So we have our special form. It's let. It has two variables, which are a and b, because they both
|
||||
get saved into that name. So it becomes an array. And we have two values, which are 1 and 2. And then
|
||||
we have a statement here, which is this big thing. So what we do with it, right, for each variable,
|
||||
give me the syntax tree representation of it. And then we want to shift off a value, right,
|
||||
so pull a value off the front of the list of values. There would be a few other ways to write it,
|
||||
so you know, work on the two lists in parallel, but I'm kind of lazy. So I'm not rewriting it.
|
||||
Set the scope on it to lexical, say it is a new declaration, register it in the symbol table,
|
||||
and then push it, right, push a new past off, which is we're going to bind this,
|
||||
right, push that new off into the init variable, which I have to find up here. Then at the end,
|
||||
we shove the init block onto the beginning of our block, right, so we start off in our block by
|
||||
just assigning these variables. Then we unshift it off, right, we shove our block into this list
|
||||
of block, right, our symbol table. Let me know if I'm going too fast or you're just throwing
|
||||
something at me as a valid comment here, really. Anyway, if we're at the end, what we want to do is
|
||||
make a list of statements, right, for each statement, push it in there, and then grab our block
|
||||
off of the top of the symbol table, right, pull it off, shove our statements into it,
|
||||
and then set it as the syntax tree for this node, right, for this part of the parse tree,
|
||||
right, so let me show you what this actually looks like. It's pretty nice.
|
||||
Past for the abstract syntax tree, let a equal the one, say a,
|
||||
pretty straightforward, so we start off, we get a new block here,
|
||||
right, of type of media, and it has a sim table attribute, right, so for this block,
|
||||
we've got a new variable called a, which is lexically scoped, and then we want to bind,
|
||||
right, there's our first child here, a list of statements, and an enlist of statements together
|
||||
just concatenate, there's no difference between them, right, so first we want to bind,
|
||||
right, into our new variable A, right, it's newly declared here, an integer, value of one,
|
||||
and then we call our namesay, scope package, right, so our global save function,
|
||||
on this value A, right, and the reason it was able to look up, right, this serialization is
|
||||
pretty poor, it just references the earlier thing because that's how I got it, right, by looking
|
||||
it up, let me show you, all the way down here somewhere, in symbol, yes, yeah, yeah, that's,
|
||||
yeah, that's all it means, so down here in symbol, so every time we just have, you know,
|
||||
just some plain text there and want to look something up, by default it's going to be global,
|
||||
but in the name of it, it's going to be the stringification of the symbol match there,
|
||||
then for every block, right, so we're going to start at the beginning and just walk through it,
|
||||
if the block, we call the symbol function to look up a symbol from its symbol table,
|
||||
and the scope is still packaged because we haven't found anything yet,
|
||||
but if we find something we haven't found yet, then we just set the scope to whatever the scope
|
||||
of that symbol is, it's going to be lexical, right, and then we return a new pass variable
|
||||
with that name in that scope, is that pretty clear, we, all right, I keep asking that,
|
||||
you can just stop that, anyway, I think we have one more thing, which is lambda's,
|
||||
oh, let me actually show you that it works,
|
||||
apparently works, right, for say one to three, we assign a is one, b is two, we say okay one,
|
||||
okay two, okay, one plus two, and everything seems to work out, okay, all right,
|
||||
make tests, still passes, all right, our four test files now,
|
||||
eight, is that where we are, apparently, so lambda is just a closure, right, it's just,
|
||||
you know, the lexical scope function, the function is sticking to variable,
|
||||
so the syntax of it is just the word lambda, an open parenthesis, the list of parameters
|
||||
that that function takes, closed parenthesis, and then a statement, video, okay, all right,
|
||||
here's our examples here in the test, right, we define an, oh, using let, we set okay to be a lambda
|
||||
on message, which is say the word okay, and then the message, and then here we call okay one,
|
||||
okay, on a function on one, right, pretty straight, I'll stop saying straight forward, I'm sorry,
|
||||
I know that was getting annoying, because it annoys me when I say it too much, anyway,
|
||||
so the beginning, we had a new past block, it's a declaration, and then we iterate over these
|
||||
variables, right, for each thing saved in the var name, that's a symbol, right, so we just bind
|
||||
it to the syntax representation there, which makes a new past var, set the scope on it to parameter,
|
||||
say, how we, we are declaring something, and then we also saved in the symbol table as a lexical
|
||||
variable, and then we push it in there, right, and we unshift it off, unshift it off, otherwise,
|
||||
right, so we're at the end, we take our statements, shove them into the block, set it as a return
|
||||
value, and we're done, so let's look at what this syntax tree looks like, right, so I cough, and then
|
||||
we check it out again, so we run past on, so make a lambda of a variable A, and we return
|
||||
A times 2, and so we see that makes a past block, it's a declaration, has this lexical variable called A,
|
||||
and it's got a, it's first statement in here, it's just a new parameter, right, called A,
|
||||
and then it has one statement in it, which is call, the function star, on this value,
|
||||
and this variable, all right, if we take a look at the, uh, pier generated by that,
|
||||
let's, uh, say, uh, define, uh, double to be lambda on A of times A2, yeah, that works out,
|
||||
oh, well, actually let me then call double, uh, say, double to, all right, so we first, um,
|
||||
get this subroutine down here, 13 something, just see down here is named 13 something, as generated,
|
||||
it doesn't give a meaningful name, it accepts one parameter, just parameter 23, that's going to be
|
||||
a lexical variable, so we'll just use this little thing to say stored in the lexical symbol table as A,
|
||||
and we look up the global function star, we then look up A again, because it might have changed in
|
||||
the meantime, we call star on A and 2, return it, swap in here, we lexically save it as double,
|
||||
get the save function, get the double function, call the double function on 2, call the save
|
||||
function on double, and her done, so it generates some, okay, bike, or assembly here,
|
||||
that's about it, again I have tests as well, uh, they run, make tests, everything checks out, okay,
|
||||
any, any questions about this, anything you want to see more on, yeah,
|
||||
what was the, uh, what was the, uh, what was the problem, the ration, it's really hard to build a
|
||||
compiler, it takes a long time, it takes a lot of expertise, it takes a lot of training, and
|
||||
well, if you're wanting people to be able to experiment with new things, they wanted to
|
||||
enable people to go out and, you know, build their own, well that was the rationale for the
|
||||
parrot compiler tools, specifically, um, for parrot, the original reasoning came around, was for
|
||||
Perl 6, storage, raising a hand, yes, oh, the name parrot,
|
||||
another, the m4, Perl, just like, for 5, yeah, then after the joke was done,
|
||||
who in the world had that part,
|
||||
she was around by the start,
|
||||
so it's, what about it,
|
||||
um, I can probably expand on that a little, okay, my specific interest is probably in how it does the
|
||||
cross language, hybridish type stuff, and that's probably how the VM is best interacted with,
|
||||
um, you can talk about how that's actually, like, conceptually just brought about, and now it's
|
||||
actually implemented in some, over a high of 10,000. The way that works is, uh, each language actually
|
||||
has its own, uh, its own namespace that it runs in, right, and so code that's running in
|
||||
Perl 6 runs in the Perl 6 namespace, so when it, it sets a global variable, that's visible to
|
||||
Perl 6 code, but it doesn't start stomping on other languages, right, it also just compiles
|
||||
everything down to peer, as you saw here, right, there's nothing different from peer that's
|
||||
generated by the Perl 6 compiler, versus peer that's generated by the Python compiler, or
|
||||
generate by the law code compiler, or anything like that, yeah, well, for, for various, for various
|
||||
meetings of support, we get different answers, um, there's currently a mostly complete tickle
|
||||
implementation, a mostly complete Louis implementation, a fairly complete law code implementation,
|
||||
um, of course just silly, oh, and, uh, coming along pretty nicely PHP implementation, and a
|
||||
very nice, uh, Perl 6 implementation, not quite done, um, Python, there's a little bit of a,
|
||||
Python compiler, but there hasn't really been enough interest in anyone to work on it very much,
|
||||
um, there's, uh, there's a fully complete HQ9 plus compiler, which is a language which consists
|
||||
of the letters HQ9 and plus, we're printing out hello world, printing out a quine, which is a
|
||||
program that prints its own source code, printing out 99 bottles of the beer, beer on the wall,
|
||||
and I don't remember what the last one was, but it's a joke language, um, there's a very
|
||||
complete APL implementation, which is kind of fun to be able to call APL from Perl 6, entertaining,
|
||||
um, APL is a really interesting language, um, I've been having to keep trouble keeping track of
|
||||
all of them lately because, uh, right now they're being moved out of the parrot repository into their
|
||||
own repositories, um, there's a, I wrote a kind of okay, uh, Ruby implementation, it's very slow at
|
||||
parsing, um, once the program is actually compiled it runs okay, but it's very, very slow, I started on a,
|
||||
small talk implementation, but the grammar's mostly complete, there's no standard library,
|
||||
so it's useless, mostly, um, scheme implementation, Perl 6, and there's a huge, there's a big
|
||||
wiki page on the parrot wiki that has all of the others that I'm not remembering, this is
|
||||
everything that nobody's bothered to move over yet, awesome, basic, uh, be fun, implementation is
|
||||
just scary, um, a few others that I know I'm forgetting, let's, I at least name all the big ones,
|
||||
two, some degree, some languages of, well, the active languages have had that problem, yes, um,
|
||||
but yeah, the parrot 1.0 is going to be out next Tuesday, is there a lease, and the headline for
|
||||
parrot 1.0 is it's a stable API for language implementers, which means they're going to have,
|
||||
start having a stable long term deprecation cycle, after this release, then the next major release,
|
||||
there's still some bike shedding on what they're calling a major releases, deprecation releases,
|
||||
whatever releases, but the next release that affects the deprecation cycle will be in June or July,
|
||||
forget which, and then after that it's going to be on a six month cycle, right, it's going to be
|
||||
every January, every June, right, so every six months, yeah. So is, uh, this 1.0 milestone, is that,
|
||||
give us any hope of seeing pro-six? Parrot is separate from the pro-six development,
|
||||
the pro-six compiler on parrot is currently passing, I think it's coming up on around 8,000 tests
|
||||
from the, instead of spec tests, there has been some speculation that a complete set of tests will
|
||||
be somewhere around 15,000, we're not there yet, we're still working on the test suite as well, so
|
||||
I would not be surprised if it was released in 3rd or 4th quarter this year, the first
|
||||
actual release of Rukudo was just this past month, it was alpha something named, but there was a
|
||||
release and it's going to continue having a monthly release cycle just as a parrot has been
|
||||
for, you foreseeable future. There's a lot of stuff that can be done if you want to help,
|
||||
so it's still a lot of, so a lot of work that's pretty accessible, even if it's just on the test suite,
|
||||
so pro-six is coming up right here, so that's actually pretty exciting, I can, uh,
|
||||
oh, I think I already compiled that, oh, that's really cool, everything's all screwed up right now,
|
||||
because, uh, parrots moving towards a lot of things are trying to rely on an installed parrot,
|
||||
instead of a parrot from the build tree, and so right now, and I just changed around to that,
|
||||
at around 12, 30 this morning, so there's still a few things that are fighting over which version
|
||||
of parrot it's using, and yeah, that's not something you'd run into on a reasonable system,
|
||||
it's not all hose, anything else you want to talk about?
|
||||
Parrots targeted platforms are Windows, macOS, I know we've got both Intel and PPC, macOS,
|
||||
64-bit and 32-bit Linux, they're looking to get packages in Ubuntu, packages in Fedora,
|
||||
packages in Debian, they've been fighting to get packages in Debian for the past year and a half,
|
||||
because everyone who keeps trying to sponsor them just disappears and doesn't respond to emails,
|
||||
I know we have a few people running it on various BSDs, I don't know if they are in the officially
|
||||
supported set or not, any other platforms you're curious about? There has been a lot of interest
|
||||
in getting a running on mobile devices. Another interesting thing that I saw was some people were
|
||||
working to get it running as a Firefox plugin, so you could then write your scripts instead of
|
||||
in JavaScript in any language pair of supports. Not that I know of.
|
||||
There has been some work at getting Java bytecode to run on Parrot, so you could then interoperate your
|
||||
compiled Java classes with, you know, use them from Parrot, which is interesting as well,
|
||||
as there's another project getting .NET bytecode running on it too.
|
||||
It's fun though.
|
||||
With Java that was originally Jonathan Worthington, who wrote most of it,
|
||||
I know he is doing some kind of DBI stuff, but I'm not sure why.
|
||||
Let's say your Python code or even really wanted to do your hash script to act as any database through
|
||||
a little bit of a DBI. Who else wants a penguin?
|
||||
Be careful you got a wire.
|
||||
Oh, all the way back there. I'm out of penguins now.
|
||||
The bytecode is a cross-platform. You compile your bytecode on one system. It will run that exact same
|
||||
file on any other architecture, regardless of NDN, regardless of processor.
|
||||
Right, as long as you have Parrot installed that, but it's not machine code. The closest you
|
||||
can get for that is there is a tool, which will embed a Parrot interpreter into a piece of
|
||||
bytecode, embed some bytecode into a Parrot interpreter to make a fake cutable instead of an
|
||||
executable, which is kind of silly, but works out.
|
||||
What's that? Now, performance, there are few bottlenecks in performance. Performance right now,
|
||||
I actually did have some statistics. I don't remember when I made these, but at the time,
|
||||
this was running on an unoptimized Parrot, and this is measuring some kind of loop or something
|
||||
running on the cardinal, which was my Ruby implementation on Parrot against the C version of
|
||||
Ruby. And about a ten times performance difference, but I was not able to run it on an
|
||||
unoptimized Parrot, so there was no jits, no kind of optimization at all. But there are two
|
||||
few big bottlenecks. One is the current Parrot architecture. There are several places where we go
|
||||
back and forth from C calling conventions, and Parrot calling conventions, and back and forth
|
||||
several times, which just kills performance horribly. And there are plans to fix that,
|
||||
but nobody has implemented them yet. There's a plan how to do it, it's just a lot of work,
|
||||
so it hasn't happened yet. Also, garbage collection, right now Parrot uses a stop-the-world
|
||||
market sweep, everything, garbage collector, which is, well, slow and bad. There have been a
|
||||
couple of projects to implement a generational garbage collector on Parrot. Apparently, it is
|
||||
mostly done, but just needs to be merged in and touched up, and it's been that way for a few months
|
||||
waiting for someone to finish it off. That was part of someone's Google Summer Code project,
|
||||
partially a few of the other Parrot contributors were working on it. So
|
||||
the core Parrot developers that I've talked to about this have very good hopes for Parrot's
|
||||
performance in the future. It's not horrible right now. It's not, you know, thousands of times slower,
|
||||
like a few things I've seen, but it's still, you know, not fast right now. Is that
|
||||
bad on the order you wanted to know? For example,
|
||||
let's just throw something together, i0 equals 0, greater than i0, a big number. Let's put another
|
||||
zero on there. I don't want to count them. Loop, and increment i0, go to loop.
|
||||
So let's run that. Oh, that was not enough zeros.
|
||||
Let's make a thousand times more.
|
||||
There, that was about three and a half seconds to run that many iterations. So in spinning
|
||||
the CPU uselessly, at least it can do that much. That's in no means a reasonable benchmark,
|
||||
not a very useful one, but it does mean something. There's also,
|
||||
it does have a jit, which is not as good as it could be yet. Not quite everything can be jitted yet,
|
||||
but I'm told there are plans for everything to be, so let's see about that.
|
||||
Anything else?
|
||||
How fast can you type?
|
||||
Maybe that.
|
||||
The Python interpreter or compiler right now does not very much. I can do the basics,
|
||||
define a class, call a function, define a function, instantiate a class, the basic stuff like that,
|
||||
but it doesn't have list comprehension, it doesn't have a lot of the fun stuff.
|
||||
What about the constructs that are different between languages? How does Perry handle that?
|
||||
Kind of thinking of examples of, and I really don't have a good understanding of
|
||||
enough languages to actually say which one has different stuff in them. I know there are different
|
||||
components in different languages. How does it deal with that in regard to like, so maybe in Perl,
|
||||
there's some magical object in the structure in certain way, and it's different in Python,
|
||||
where they build them. How does that, I mean, guessing it's in the interpreter itself in Perl, but
|
||||
if it's fundamentally different, should they accomplish similar goals? The good example maybe is
|
||||
like a reading loop that you think is differently there? The way that works is that the compiler
|
||||
generates the same, it's always just generating peer. So control constructs like that, like loops,
|
||||
and, you know, whatever else. There are several things like that I can see, that's the problem.
|
||||
I'm thinking more like, you know, something abstract that probably got implemented in some language
|
||||
that people use. I mean, there's probably examples, I'm not articulating that word, but
|
||||
in general, most of that stuff is exposed through the same core parent primitives. There are a few
|
||||
places that things are weird, for example, most scheme and list implementations that you look at.
|
||||
Don't use an array, is there that object? They have, you know, the nested cons cells, which if
|
||||
you implemented your language like that, if another language tried to work with one of your objects,
|
||||
it would be weird. You couldn't do array access on it. You'd have to call the, you know,
|
||||
the foreign function to do it. The parent took me to account that. He said, oh, that could be like an
|
||||
array in this language and that. I can actually fill, I guess you could. The parent stance on that
|
||||
is that they don't do anything like that. They do not define any kind of policy. You could define,
|
||||
you know, the module in Python that would, you know, kind of wrap that foreign class, right? Like
|
||||
to find your scheme module, right? So you'll import scheme, right? And then you could call scheme
|
||||
functions. That's a reason of a way to deal with that. But there's nothing in pair that tries to
|
||||
do that automatically. That tries to convert objects from one type to another type. Well, there's
|
||||
what we don't know. For example, in Ruby, a lot of the core classes like integer and string and
|
||||
such have a lot of methods on. And depending on how you implement things, if you just, you know,
|
||||
if I returned a string from Perl 6 to some Ruby code, the Ruby code working on it would, you know,
|
||||
if you tried to call that method, there's no method like that on this object, right? You could
|
||||
just call the Perl methods because that's a Perl object, right? It's just a different class.
|
||||
Right? So it doesn't translate that. Right. Exactly.
|
||||
And that makes sense. That has never been implemented. So it's been pushed off until someone
|
||||
implements it. It is not part of the one point or release. It is still part of the plan for the
|
||||
eventually we'll do this magic ponies release number. But currently there's no STM.
|
||||
The things it does have, it does have good threading, it does have a good event model.
|
||||
The object model is Perl 6's object model, which is a 2% of all other object models basically.
|
||||
So one interesting thing has been seen that you can define, you know, using roles in such
|
||||
on other languages that don't normally support that. One tension that has existed has been,
|
||||
it would be so easy to add this to my language, but the language doesn't support it. For example,
|
||||
I added the gather take control structure from Perl 6. I added that to Ruby, a Ruby compiler,
|
||||
because it was easy and made some things nicer to work with. But if anyone writes that in their
|
||||
Ruby code, it will be not bad. But it was kind of fun actually calling Ruby functions, which would
|
||||
take a variable and have that interoper with the Perl 6 gather construct and things like that.
|
||||
What I've seen is one of the benefits of Perl 6 is that if other open source language is a chance to
|
||||
be able to truly open source and gather the core work from another language that's abstracted to there.
|
||||
So that's what Perl's tried to do all along with it now, sharing that same core.
|
||||
Right now, all of the languages that I implemented, the
|
||||
call code in another language construct in. If you try to use it, we'll still look for that
|
||||
language to be in the language's directory of a paired installation, which it probably won't be,
|
||||
because like I said, all the languages are moving out. There's some infrastructure work that's going on
|
||||
on actually, where the language is going to be installed, and Perl can look them up for you, and
|
||||
I'm not sure how that's been working out because I haven't been following that mailing list thread.
|
||||
Right now, none of that works. After I think two or three months ago or something,
|
||||
I posted a blog post about I got all of it working and the fun examples and such.
|
||||
Reference in New Issue
Block a user