this morning it struck me that it would be nice to have Parrot not only run Perl 6 and similar byte code, but that any of the common interpreted languages be compiled to this same byte code.
Then no matter whether running a Perl 6, Python, Ruby, Tcl maybe even bash script the same interpreter library would be used. Then likely it would already be in memory speeding up start time.
And this would also ease cross language module/library inclusion. Imagine instantiating some Python class from Perl!
Apache would essentially have a mod_parrot. Maybe, if this can be tested very hard, we'd even have a Parrot kernel module for all Unices supporting that. Then exec() could perform compiled scripts right away, like machine code :-)
coralament / best Grötens / liebe Grüße / best regards / elkorajn salutojn
Daniel Pfeiffer
Availability of all the pieces your vision requires is at
least several years away, barring miracles. I don't par-
ticularly expect it to happen.
--
Cameron Laird <Cam...@Lairds.com>
Business: http://www.Phaseit.net
Personal: http://phaseit.net/claird/home.html
I think this was one of the early design goals of the people working
on Parrot. In fact, the name Parrot is taken from a April Fools hoax
merging of the worst parts of Perl and Python. But, having an
efficient common backend for several languages is a sound engineering
decision, so it is no longer a joke!
In fact I believe I read a "proof-of-concept" version of Python is
already running in Parrot.
.NET is already doing this for Windows. Not too popular because the
only way to do it is to buy Visual Studio.NET or download the massive
free .NET runtime. As Microsoft shoves .NET down more and more
throats, expect to see this at a computer near you.
There are some doubts about Parrot outside of the Perl community.
Larry Wall was adamant that Parrot would be a register machine, and
not a stack machine, but outside of the Perl community, people are
uncertain about Parrot's ability to do efficient register allocation.
Take this with a grain of salt, I avoid Perl whenever I can, and I get
all my Parrot news from Slashdot :-P
Particularly myself; in fact, it was named Parrot precisely to represent its
language-agnosticism.
The thought is also behind why I wrote the Python::Bytecode module, why I
learnt Ruby, and why I've been asking interesting questions about access to
the Ruby AST.
I don't think the reality is as far away as you imply.
--
The problem with big-fish-little-pond situations is that you
have to put up with all these fscking minnows everywhere.
-- Rich Lafferty
Simon certainly has worked with this far more than I.
As others have written, still others have tried, including Andrew
Kuchling for Python. Two of his comments discribing the problems in
doing so are
Andrew
da...@dalkscientific.com
> Then no matter whether running a Perl 6, Python, Ruby, Tcl maybe even
> bash script the same interpreter library would be used. Then likely it
> would already be in memory speeding up start time.
I for one have two thoughts about the continued success of Python. First
because I like Python and want to keep using it. Second is that the more
people that use Python, hopefully the less people that will use TCL
Take care,
Jay
Maybe it's not dead; it may have just ceased to be.
I had similar problems, since my next stop after the "Parrot tour",
where all this boring VM stuff was decided, happened to be New York
City, home of the extremely famous tic-tac-toe chicken.
(http://members.tripod.com/the-wire/wire0102/ny0102.html)
Since then, of course, the bird has been rescued, given a new home,
and is now much happier.
Whether we need to give a new home to our brand new Virtual Machine
performing bird is not clear, but I'm happily convinced that its soul
will not die off, and that people will make the most of its talents in
the most humane way possible.
--
"(Because if life's not shit, then you're not doing it right.)"
- Rebecca Luckraft
I'd think it quite plausible that if someone took the project on,
there could readily be a pretty functional Python compiler for Parrot
/before/ a Perl 6 one would be likely to emerge...
--
(reverse (concatenate 'string "ac.notelrac.teneerf@" "454aa"))
http://www3.sympatico.ca/cbbrowne/sap.html
Signs of a Klingon Programmer - 7. "Klingon function calls do not have
'parameters' - they have 'arguments' -- and they ALWAYS WIN THEM."
Only just this morning? I take it that parrot itself only came to your
attention recently, since that concept has been with the VM since it's
inception.
> Then no matter whether running a Perl 6, Python, Ruby, Tcl maybe even
> bash script the same interpreter library would be used. Then likely
> it would already be in memory speeding up start time.
The difficult task is compiling those languages into parrot bytecode.
This may not be horrible if those languages have their own bytecode,
which can then be translated into parrot bytecode. As an example, there
already exists a perl script which translates java .class files into
parrot bytecode.
For other languages, a compiler would actually be needed -- eg, for
bash.
> And this would also ease cross language module/library inclusion.
> Imagine instantiating some Python class from Perl!
Ya mean the same way that you can, using Jython, instantiate Python
classes from Java and vice-versa? :)
> Apache would essentially have a mod_parrot.
Well, obviously it would.
> Maybe, if this can be tested very hard, we'd even have a Parrot kernel
> module for all Unices supporting that. Then exec() could perform
> compiled scripts right away, like machine code :-)
Or, your whatever_2_parrot compiler insert an appropriate #! line at the
beginning, pointing to the parrot VM -- this is much simpler, as it
takes advantage of an existing mechanism.
--
my $n = 2; print +(split //, 'e,4c3H r ktulrnsJ2tPaeh'
."\n1oa! er")[map $n = ($n * 24 + 30) % 31, (42) x 26]
> Daniel Pfeiffer wrote:
> >
> > Hi,
> >
> > this morning it struck me that it would be nice to have Parrot not
> > only run Perl 6 and similar byte code, but that any of the common
> > interpreted languages be compiled to this same byte code.
Oh, yes. This is our answer to M$s lacking .NET technologies ;-)
> Only just this morning? I take it that parrot itself only came to your
> attention recently, since that concept has been with the VM since it's
> inception.
Sincerely yours, Roman A.Suzi
--
- Petrozavodsk - Karelia - Russia - mailto:r...@onego.ru -
Just my £0.02
--
FM
How cool would it be to just set up a computer with a listening parrotd
and DHCP client, plug it in to the Beowulf and have it automagically
recognised as a node and delegated tasks?
I have been thinking quite a bit about cross-platform Beowulfing
recently. My initial idea was to set up an rlogin or something on the
node machines, and have the Apple (that's what I call the conducting
machine: "Apple" because it sends Jobs away, does nothing for a while
then gets Jobs back :-) distribute the source code for the node service
and job processor, configure and build the code, then log out and use
the new node as normal. This would be faster (provided the building
didn't fall over) as Beowulfs go, but less secure and probably harder to
set up.
Comments [rational variety preferred]?
--
FM
Security is a *hard* problem.
Curses! You stole my idea :-) I see what you mean about security being
a problem...
--
FM
What advantage would this have over putting a #! line in the bytecode?
Most existing *nix kernels (except some very old ones) will look at the
#!, parse out the path to an executable program, and the run it.
> I may be wrong. This parrotd system would also help in projects like
> Beowulfs (although why you'd be using byte-compiled languages in
> parallel computing is beyond me), because you could use inetd or
> similar to spawn a parrot when data was received on a certain port.
I don't really see the point of having a parrotd, except if you want to
create something vaguely like PersistantPerl.
--
FM
Then why not just have a libparrot? Let the OS's caching sort it out --
if it's being used, libparrot will stay in memory. Assuming you aren't
going to replicate OS-level functionality, like processes and memory
protection.
Ian
But not quite more secure. Imagine userX running a script that does
something nasty - like replace some command and then wait for root to
call it. This was a very simple example, since probably parrot would
recreate interpreters per script, but I guess it still could be possible
since it would be the same process...
I guess it's a lot safer to just fork as it is now.
--
WK (written at Stardate 56849.3)
"Data typing is an illusion. Everything is a sequence of bytes."
-Todd Coram
It can't. Parrot can only understand parrot bytecode.
> Why not leave it running, so that any Perl/Python/Tcl/Ruby/Java/sh/
> BASIC/whatever code can get to it immediately?
Ignoring the problem of compiling those languages down to parrot
bytecode...
How should the kernel detect that a parrot-bytecode file is, in fact,
parrot bytecode?
For normal exe files, there's the execute bit and some standard headers.
For normal scripts, there's the execute bit and the #! line.
> A parrotd exec would consist of: "Run this." "OK".
> A #! consists of "Does this file exist?" "Yes." "Does it
> work?" "Yes." "OK, run this." "OK".
> I contend that a properly set up parrotd *should* be faster than the
> equivalent "each language set up separately" environment.
The speed hit of exec() is *not* the time it takes to check if the file
named on the #! line exists and has the executable bit set.... the speed
it is due to the time it takes to load that program into memory.
With that in mind, if you can special-case the kernel to pass scripts on
to special daemons, rather than loading up an interpreter for each
script, it will almost surely be faster, and not just for perl/parrot.
Some years back, RMS proposed a standard 'scripting' language called
Guile. See, various languages like Tcl, Perl, Python, etc. were
being developed and none of them were 1) developed under the FSF nor
2) a variation of Scheme. (A simplified and perhaps biased
interpretation of mine.)
A key part of his proposal was that Guile would support translators
from other languages, like Python, C, etc., to Guile.
It didn't happen. Writing those translators are hard because each
of the languages has different object models, which must be implemented
nearly perfectly. Guile is a full-fledge language built on years of
research into Lisp and scheme, so I would be surprised if it was any
easier to implement in Parrot's byte code. It didn't happen with
Guile, it's even less likely to happen with Parrot.
I can "imagine if parrot ..." But it isn't going to happen without
*huge* amounts of work; comparable to writing Jython. (A Python
implementation written on top of Java rather than C.)
On the other hand, consider the gcc suite of tools. These convert C,
C++, Pascal, Fortran, Objective C, ... into a more generic form. So
there is some known success in doing this. But I've looked at gcc
code and it isn't something I want to hack, while I've contributed code
to Python's C implementation.
Andrew
da...@dalkescientific.com
> Frodo Morris wrote:
> >
> > Benjamin Goldberg wrote:
> > > Frodo Morris wrote:
[...]
>
> > Why not leave it running, so that any Perl/Python/Tcl/Ruby/Java/sh/
> > BASIC/whatever code can get to it immediately?
>
> Ignoring the problem of compiling those languages down to parrot
> bytecode...
>
> How should the kernel detect that a parrot-bytecode file is, in fact,
> parrot bytecode?
>
> For normal exe files, there's the execute bit and some standard headers.
> For normal scripts, there's the execute bit and the #! line.
At least on *BSD, /sys/kern/imgact_*.c control which executable types
are allowed. There are imgact_aout.c, imgact_elf.c, imgact_gzip.c and
imgact_shell.c, and maybe one could add an imgact_parrot.c?
Regards,
Slaven
--
Slaven Rezic - slaven...@berlin.de
Berlin Perl Mongers - http://berliner.pm.org
Isn't it a commonplace that the n x m translation problem is best solved
by having a common intermediate? This seems more efficient when
m+n < n*m
it seems that only those with sufficient muscle can force this on the
world eg Sun/IBM/M$. They can clearly see the need to support only one
backend.
Funnily enough they kept telling me that as soon as I switched to
F99/C++ etc etc that everything would be portable. Now the buzz is
C#/Mono or Java, and perhaps Parrot. As long as the wheels keep turning
and the $'s flow they'll keep promising the next sliced bread.
--
Robin Becker
Yep, it is a commonplace, but that doesn't make it true:)
You see, for the common constructs this might be true, but each
language has it weird corners and for those you'll end up with
language pair specific translations inside the intermediate language,
i.e. if there *is* such a translation. There will always be some left
overs that can't be (easily) translated. e.g. suppose one of the
languages support continuations, but the others don't, bad luck.
Ofcourse for parrot this isn't a show stopper per see, as parrot
doesn't have to translate into each of the supported languages, it
just has to understand them. But still, parrot will have to support
all the dark corners of all supported languages, quite a mess me thinks.
--
groetjes, carel
> Some years back, RMS proposed a standard 'scripting' language called
> Guile. See, various languages like Tcl, Perl, Python, etc. were
> being developed and none of them were 1) developed under the FSF nor
> 2) a variation of Scheme. (A simplified and perhaps biased
> interpretation of mine.)
I've never seen any even perceived advantages of guile other than the
FSF thing. I don't get the impression that it is that great even as a
scheme implementation.
Cheers,
M.
--
We've had a lot of problems going from glibc 2.0 to glibc 2.1.
People claim binary compatibility. Except for functions they
don't like. -- Peter Van Eynde, comp.lang.lisp
...each. ;-)
Well, I suppose Sun and IBM are sort of sharing.
Paul
P.S. Projects like Parrot only really tend to succeed if they either
produce results quickly enough for casually interested parties or have
enough direction and motivation for the prolonged period of time that
they aren't producing highly usable output. Despite hearing about
Parrot occasionally, I'm not so sure that Parrot exhibits either of
these properties, but it would be nice to be proved wrong.
I would have to think for a bit to come up with a proof, but
it seems fairly likely to me that that would be impossible.
At the very least, for it to be possible, you would have to
program indefinite-length pointers and allow all available disk
space to be used as extended memory.
The problem that people keep forgetting is that Turing Equivilence
requires indefinite memory. Turing Machines are defined as having
infinite "tapes". Given any finite memory size, I can come up with
an interpreter the emulation of which would not fit in that finite
memory size.
--
Would you buy a used bit from this man??
Your confusion is in thinking that "portable" is a binary value. Fortran
was certainly more portable than assembler, as was C. Tcl is certainly
more portable than Fortran or C.
The other problem, of course, is that people keep improving their
capabilities, so what was portable is no longer adequate. Fortran is
quite portable, as long as you don't want to do 3D graphics driven by a
data glove.
As long as you don't want to do development in multiple languages or
dynamically load code safely over the net into some other OS process,
Tcl and Python are pretty good choices. Otherwise, you might want to
consider C# or Java.
See how it works? :-)
English was portable until everyone started using it ;)
--
Robin Becker
you can "dynamically load code safely over the net into some other OS process"
with python, too. Where do you see the problem?
with the other point (developing in multiple languages) i fully agree.
Although C/C++ and Java seem to be pretty well integratable with python.
I wonder if it would be possible to modify/extend the python-VM to allow for
"efficient" execution of C#. We would be set, then, wouldn't we?
regards,
holger
--
FM
There's also the problem of motivation: who's going to write those
translators?
Tcl and Python programmers? They have nicely usable
implementations already. Translation to Guile would buy them
nothing, except for having to rewrite every single C extension.
Guile programmers? If they're Guile programmers, they must like
programming in Scheme. Why would they work on translators for languages
they'll never use?
A Guile programmer might write a Python translator out of pure
bloody-minded evangelism, of course, but it would require supernatural
determination to continue *maintaining* it for the long-term, and
there would still be the risk that the outside community would look at
the translator and ignore it, saying (it's too slow | it doesn't run
extension X that I really need | Guile doesn't run on my platform).
Similar arguments can applied to translators to Parrot, of course.
--amk (www.amk.ca)
ABBESS: In food, in sport, and life-preserving rest
To be disturbed would mad man or beast.
-- _The Comedy of Errors_, V, i
I am not sure i understand this. Why does python need to enter
restricted mode?
And doesn't PSYCO also do JIT-alike compiling? That's at least how
i understood Armin. As he also suggests to rewrite the python-core
in python to make it faster (with psyco) maybe this could help
with an c#-interpreter?
wildly-guessing'ly yours,
holger
I don't think C# allows this, but am no expert. The implication is that
C# can be very much more agressive in its JIT compilation. When it sees
x*y for x and y known ints it can compile an integer multiply. Python
only sees x*y and without the type information it is forced to do type
lookup at run time.
As you point out psyco can do the compilation, but only into the generic
multiply (unless psyco can be hinted in some way).
The pyrex project goes further and allows C style typing which makes it
very fast, but it isn't JIT.
--
Robin Becker
XML, but it wasn't a programming language. And they all kicked to
death because XML parsing is now considered a MUST for any "sane"
language.
--
Giuseppe "Oblomov" Bilotta
"Da grande lotterò per la pace"
"A me me la compra il mio babbo"
(Altan)
("When I grow up, I will fight for peace"
"I'll have my daddy buy it for me")
Better put: python allows names to be dynamically rebound to
(reference to) object of any type regardless of previous binding.
> I don't think C# allows this, but am no expert. The implication is
that
> C# can be very much more agressive in its JIT compilation. When it
sees
> x*y for x and y known ints it can compile an integer multiply.
Python
> only sees x*y and without the type information it is forced to do
type
> lookup at run time.
>
> As you point out psyco can do the compilation, but only into the
generic
> multiply (unless psyco can be hinted in some way).
I believe that Psycho *does* compile to specific int multiply. Hence
up to 10x speedup. That's what Armin means by 'specializing'
compiler. The same 'x*y' could also be compiled to float multiply if
that also happens on another entry to same code. Correct version
would be selected as needed. Process has setup time and space
overhead, which is why programmer must specify (inner) functions to
psyco-ize.
Terry J. Reedy
There are some restrictions especially with new-style classes.
> I don't think C# allows this, but am no expert. The implication is that
> C# can be very much more agressive in its JIT compilation.
PSYCO is - in effect - extremly aggressive about optimization. It works
with the actual runtime types and defers compilation until type
information is available (when the execution path hits it). It allows
for multiple optimized code sets for one place. Depending on the
actually arriving types one code-fragment of the code set is choosen.
PSYCO emits machine code.
You might like to take a look at
if you didn't already.
> When it sees
> x*y for x and y known ints it can compile an integer multiply. Python
> only sees x*y and without the type information it is forced to do type
> lookup at run time.
Psyco will optimize this in common cases to a single machine
code instruction. Furthermore it might completly sum up compuations
with constants. But Psyco doesn't have any specializing optimizer.
This is all a result of how PSYCO works.
The more of the interpreter is written in python the more it
can optimize. That's because it can't really do much
about compiled machine code (C-extensions, C-core).
OM'ly
holger
Parrot will still have an NxM problem with datatypes. Parrot supports
datatypes through PMCs, which are basically arrays of C functions
equivalent to PyObject, so you'd have a PerlInt, PerlString,
PythonInt, PythonString, etc. Different PMCs would have different
results for various operations, so PerlInt 1 + PerlString "2" == 3,
while PythonInt 1 + PythonString "2" raises TypeError.
Bridging data types across languages allows the NxM specter to
reappear. What does PerlString "2" + PythonInt 1 do? Who decides?
When someone writes RubyInt and RubyString (assuming Ruby's strings
aren't identical to Perl's), do the PythonString and PerlString
maintainers need to add support for them?
Perl's strings are mutable and Python's aren't; do we need to copy all
the string parameters whenever Python code calls Perl code? Or will
it work as long as the Perl code doesn't trying modifying a string?
So much for seamless cross-language calls, then.
Even for the more limited world of Python extensions, it's hard to
ensure that data types interoperate as much as possible. For the
wider, weirder world of "all datatypes for all scripting languages",
arranging sensible conversions will be even more difficult.
--amk (www.amk.ca)
PROSPERO: A turn or two I'll walk,
To still my beating mind.
-- _The Tempest_, IV, i
>In message <2002110618...@prim.han.de>, holger krekel
><py...@devel.trillke.net> writes
>.....
>>I am not sure i understand this. Why does python need to enter
>>restricted mode?
>>
>>And doesn't PSYCO also do JIT-alike compiling? That's at least how
>>i understood Armin. As he also suggests to rewrite the python-core
>>in python to make it faster (with psyco) maybe this could help
>>with an c#-interpreter?
>>
>>wildly-guessing'ly yours,
>>
>> holger
>>
>I think that python allows any reference to change type dynamically.
>
>I don't think C# allows this, but am no expert. The implication is that
>C# can be very much more agressive in its JIT compilation. When it sees
>x*y for x and y known ints it can compile an integer multiply. Python
>only sees x*y and without the type information it is forced to do type
>lookup at run time.
>
>As you point out psyco can do the compilation, but only into the generic
>multiply (unless psyco can be hinted in some way).
>
I would think you could generate machine code speculatively as cached segments
based on the assumption that types for variables involved in the segment
would not change after the first binding, and then dynamically check a segment cache
validity flag and do what it currently does as fallback if the flag was set. The flag
would of course have to be set by code that does type-changing rebindings for the
particular set of variables used in a segment, so there is some overhead, but maybe
not high percentagewise. I imagine you'd have to play with tuning the segment
lengths and variable set sizes etc., but if the speculative assumption were right
sufficiently often, especially in hot loops with function calls to builtins which
would have type-signature-specific machine language variants available for common
situations, you'd get a speedup with no change in semantics. Of course, this implies
a pretty different VM implementation and support library, and multiple dynamically
coexisting representations of code at a different granularity level.
But once programmers knew that this was going on, they would watch how they
bound things to take advantage. And the nice thing is the language definition would
not change.
I guess I would want to get some statistics on dynamic rebinding type changes before
starting such a big project though. Has anyone done that already?
>The pyrex project goes further and allows C style typing which makes it
>very fast, but it isn't JIT.
Regards,
Bengt Richter
I don't think this is really correct -- I think it was mostly because
Tcl was a lame language, and was being pushed as an application
scripting language. Of course, Lisp is close to RMS's heart, which is
why the FSF proposed Scheme as an alternative over other languages.
Simplicity was always essential for an application scripting language,
which is probably why Perl wasn't a serious contender. It was also a
long time ago, when Python was young. And the translation dream.
> A key part of his proposal was that Guile would support translators
> from other languages, like Python, C, etc., to Guile.
>
> It didn't happen. Writing those translators are hard because each
> of the languages has different object models, which must be implemented
> nearly perfectly. Guile is a full-fledge language built on years of
> research into Lisp and scheme, so I would be surprised if it was any
> easier to implement in Parrot's byte code. It didn't happen with
> Guile, it's even less likely to happen with Parrot.
Part of the problem with Guile was that there wasn't any developer drive
-- RMS and some others had a vision of translators, but they weren't
involved in developing Guile -- it was mostly Scheme-o-philes, who
unsurprisingly weren't very interested in translators. The only truly
serious effort was to translate elisp, and even that wasn't really done
in a community manner.
Guile's implementation was also taken from another Scheme
implementation, which was not originally developed with any
consideration to translators.
But you're right, it is a really hard problem anyway. And there's lots
of details.
You have to deal with competing naming conventions -- Scheme allows
almost all characters in its functions, for instance. Lots of languages
have different namespaces for functions and variables. Something like
Smalltalk has an entirely different notion of method naming, even though
its semantics are close to these other languages. It seems small, but
it's a pain.
There's also issues with errors -- if you want a usable language, a
traceback like Python's should be a bare minimum in this day. But what
does that look like with mixed languages? What does that even look like
with one language, ontop of a VM that's meant to be generic? This is
often dealt with very poorly as VM developers mostly test with trivial
and correct programs.
And of course there's a huge number of problems with objects. Mutable
vs. immutable strings being a good example -- it's not just a n x m
problems, it's a straight-up no-good-solution problem. There's no
*right* way to deal with this. Each language means something different
by "string", and yet it's so important to each language that if you
expect them to interoperate *at all* you need to deal with that. Do you
annotate functions and methods so that some automatic interoperation
layer can be used? Do you force users to use awkward constructions,
exposing the fact that they're accessing another language? Do you
create wrappers? Do you just punt, and assume some simplistic behavior
will be good enough, even though it's not predictable to the programmer?
C#/CLR I believe has resolved these issues by forcing the languages to
adapt to a common set of semantics. I just can't imagine a common set
of semantics that would bring Perl and Python together -- Python and
Ruby, sure, but there's not enough common ground with Perl to do that.
> I can "imagine if parrot ..." But it isn't going to happen without
> *huge* amounts of work; comparable to writing Jython. (A Python
> implementation written on top of Java rather than C.)
>
> On the other hand, consider the gcc suite of tools. These convert C,
> C++, Pascal, Fortran, Objective C, ... into a more generic form. So
> there is some known success in doing this. But I've looked at gcc
> code and it isn't something I want to hack, while I've contributed code
> to Python's C implementation.
I don't know if GCC has a lot to offer in way of advise or experience.
It can compile many languages into various instructions, but it doesn't
do anything for interoperability AFAIK (except for deliberately similar
languages, like C and C++, which were built for interoperability).
Ian
(snip some)
> that's what I call the conducting
> machine: "Apple" because it sends Jobs away, does nothing for a while
> then gets Jobs back :-)
lol :-))))
(snip some more)
Laotseu
But you were around for this, weren't you, Darren?
--
Cameron Laird <Cam...@Lairds.com>
Business: http://www.Phaseit.net
Personal: http://phaseit.net/claird/home.html
Indeed. I was one of the first users, I suspect, compiling my own
safe-tcl interpreter. I have no idea what I was thinking when I included
Tcl in that list. Some double-negation turning into a single-negation
twixt brain and fingers, I think.
--
FM
> As you point out psyco can do the compilation, but only into the generic
> multiply (unless psyco can be hinted in some way).
You hint pysco by calling the function with ints :)
I hadn't appreciated how clever psyco was until I went to Armin's
EuroPython talk. You can get the slides at psyco.sf.net, but I can't
remember how much of the interesting stuff was in the slides and how
much was in what he said.
Cheers,
M.
--
This song is for anyone ... fuck it. Shut up and listen.
-- Eminem, "The Way I Am"
> > I think that python allows any reference to change type dynamically.
>
> There are some restrictions especially with new-style classes.
But *references* can still change type!
I don't know whether SSA or something would help compiling Python.
Maybe.
Cheers,
M.
--
My hat is lined with tinfoil for protection in the unlikely event
that the droid gets his PowerPoint presentation working.
-- Alan W. Frame, alt.sysadmin.recovery
Each script would need to be done in a seperate safe interpreter which
goes away at the end of the script, so there was no cross process
pollination.
--
Tcl - The glue of a new generation. <URL: http://wiki.tcl.tk/ >
Even if explicitly stated to the contrary, nothing in this posting
should be construed as representing my employer's opinions.
<URL: mailto:lvi...@yahoo.com > <URL: http://www.purl.org/NET/lvirden/ >
Perhaps a parallel example are the Java implementations of Python and
Tcl - these were written by Java programmers interested in having the
facilities of python / tcl in their java applications.
Perhaps Guile programmers never saw a need for the facilities of perl/tcl/
python.
As long as your application is elegant, ergonometrically superior, and
technologically sexy, it will be an applicable name...
> In article <mailman.1036579568...@python.org>,
> Carel Fellinger wrote:
>> Ofcourse for parrot this isn't a show stopper per see, as parrot
>> doesn't have to translate into each of the supported languages, it
>> just has to understand them. But still, parrot will have to support
>> all the dark corners of all supported languages, quite a mess me thinks.
>
> Parrot will still have an NxM problem with datatypes. Parrot supports
> datatypes through PMCs, which are basically arrays of C functions
> equivalent to PyObject, so you'd have a PerlInt, PerlString,
> PythonInt, PythonString, etc. Different PMCs would have different
> results for various operations, so PerlInt 1 + PerlString "2" == 3,
> while PythonInt 1 + PythonString "2" raises TypeError.
There may be difficulties like the ones you bring up, but my feeling is the
Parrot people ought to go for solving the easy 90 percent of the problem,
even if it means that little code from any language will work out of the box
(except perhaps perl6; it is their baby, after all). Another approach is to
get great interoperability with the top three or four languages, like Perl6,
Python and Ruby, and do the rest later if there is interest. IMO, if
authors have to rewrite a few percent of their code to interoperate with
Parrot, and the benefit is we can start using it in a year instead of three,
that's a deal I'd take any day of the week. Perfectionism is the enemy of a
project like Parrot.
It seems to me that there should be little problem getting Python or any
other language to function well in Parrot, especially if the Parrot people
try to make this easy as I imagine they would. Indeed, it should be no more
difficult than getting the same languages to work in machine language, which
has obviously been done.
The problem arises when the APIs that are used to facilitate communications
between Parrot programs do not support semantics in a given language. Here
we have the hard problem of choosing between great flexibility and great
performance. It seems like an ideally-written Parrot would give each
program the ability to define its own semantics, and then other programs
could choose to be compatible or not. For example, my program could conform
with protocol X, and if you support protocol X, you can use my program, call
its functions etc. You and I both know what to expect. The key with Parrot
is that it must expect the unexpected -- it doesn't know what people will
want to do with it in the future and so it should try to avoid arbitrary
limits.
With that done, the languages will have to evolve some to work with Parrot.
For example, Python will need to have a way to understand that it is calling
a function or creating an object that uses Perl6 semantics and it will need
to not expect that object to behave exactly as would a Python object.
Languages could also try to provide a protocol bridge so that an object
using Perl6 semantics looks and feels just like a Python-compliant object,
but again IMO the Parrot people should narrow their focus and let other
people do this.
Note that I have never written a compiler and I'm therefore substantially
less knowledgeable about this issue than many on this list. Corrections, as
always, are welcome.
steve
--
But then Parrot/Python becomes a variant of Python, and you have to
ask why work on one variant and not another? Why work on
Parrot/Python and not .NET/Python, which would also be a variant?
Months ago I once predicted that Mono (the effort to write a Linux
.NET implementation) would likely founder on the sheer complexity of
duplicating a large and possibly-shifting standard CLR, while Parrot,
which had a seemingly simpler task, would get its first usable version
out more quickly. Astonishingly, just the opposite has happened; Mono
has been making releases every few months and steadily writing more
add-on libraries, while Parrot has advanced much more slowly. I'd
like to dust off Mark Hammond's python.NET code, but unfortunately
Mono doesn't yet implement enough of the necessary APIs to support it.
--amk (www.amk.ca)
HAMLET: Ay, madam, it is common.
-- _Hamlet_, I, ii
Is it just me, or does anyone else think it peculiar that someone
'@esperanto.org' is championing a unified approach to language?
Daniel, is this part of a scheme to bring Python, Perl, TCL, Ruby
programmers around to your way of thinking?
;)
a
> Is it just me, or does anyone else think it peculiar that someone
> '@esperanto.org' is championing a unified approach to language?
Now, now :-). Esperanto is an auxiliary language, so its intend is to
be a second language that everyone learns in addition to their primary
tongue, rather than a replacement for it.
--
Erik Max Francis / m...@alcyone.com / http://www.alcyone.com/max/
__ San Jose, CA, USA / 37 20 N 121 53 W / &tSftDotIotE
/ \ The conviction of wisdom is the plague of man.
\__/ Montaigne
Church / http://www.alcyone.com/pyos/church/
A lambda calculus explorer in Python.
Hmmm, according to OED, "bast" means "sanctuary, refuge, asylum".
:Imagine if parrot could understand all currently- and popularly-
:implemented interpreted languages.
Such as Forth, Word Perfect Macros, Microsoft Visual Basic,
and Befunge?? (You haven't been very specific on the meaning of
'popularly'.)
Now, Parrot is intended for interpreted languages, right? And
the fundamental feature of such languages is that you should
be able to compute a string and then execute the string as
a statement. So Parrot will have to know how to execute statements
in arbitrary source languages. This means that it isn't enough
to have a (say) bash-to-parrot translator that translates
the program and hands it off to parrotd: the entire translator
is going to have to be input along with the translated source.
This indirectly raises an interesting point. If parrotd is glued into
the operating system as part of exec() as has been proposed (as opposed
to the counter proposal to just liet #! do its standard job) then the
implication is that there is only one parrot implimentation per system.
How would one then test new versions of Parrot? With #! it's easy: you
just name the path to the alternative interpreter and the kernel
invokes it. But if parrotd is built right into exec() then in order to
support multiple versions of Parrot, you would have to build the new
versions -in- Parrot and pass them in as yet another layer of
interpreter. e.g., parrotd version 6.302 is running and it has been
passed a copy of the bash2parrot 4.19 translator in case it needs to
interpret a computed string that invokes a program that needs to layer
on the experimental parrotd 6.4.9 interpreter that has to be passed the
perl2parrot translator in case it needs to interpret a computed string
that invokes a program that needs to have -another copy- of parrotd
6.302 layered on [you can't count on parrotd 6.4.9 running parrotd
6.302 programs the same way that parrotd 6.302 would run them] that has
the <etc.> interpeter layered on to run <etc.>.
Scheme is right at home at dealing with these kinds of layering issues,
using a process called "reflection" [well developed by Brian Reid and
Jeem Desriviers]. They aren't straight-forward issues: think about
debugging, and think about re-entrancy, and think about problems in
cross-layer pollution -- you don't want a wild pointer in the fifth
layer down to affect your third layer, right?
Speaking of layers: I take it that some thought has been put into
how to do operating-system escapes? So that one can (for example)
handle graphics? Or even just sockets? Seeing as some of the most popular
interpreted languages are by no means restricted to text-only
and have networking capabilities? But of course the appropriate calls
could come within one of the computed strings, so any escape cannot
be absolute and must instead be handled via the interpretation layer
(c.f. the above in which I showed that parrotd must be built in
Parrot if you want parrotd to be handled at the exec() level...)
--
"The human genome is powerless in the face of chocolate."
-- Dr. Adam Drewnowski
Is it (currently) possible to put Word Perfect macros into a file, and
run that file as a script?
And I think that it's actually highly probable that a translator from
MSVB to Parrot will be written... or rather, a translator from MSIL or
from .NET to Parrot.
> Now, Parrot is intended for interpreted languages, right? And
> the fundamental feature of such languages is that you should
> be able to compute a string and then execute the string as
> a statement. So Parrot will have to know how to execute statements
> in arbitrary source languages.
Well, not parrot *itself* ... you'll have a compiler (written in parrot)
which translates the other language to parrot bytecode. When some piece
of code does eval $string, it calls to the translator, then runs the
resultant bytecode.
> This means that it isn't enough to have a (say) bash-to-parrot
> translator that translates the program and hands it off to parrotd:
> the entire translator is going to have to be input along with the
> translated source.
Fortuantly, parrot is able to defer loading of modules until they're
needed. You hand off the translated source, and as soon as it runs into
an eval $string operation, it loads up the translator, then runs the
translator and continues on it's merry way.
> This indirectly raises an interesting point. If parrotd is glued into
> the operating system as part of exec() as has been proposed (as
> opposed to the counter proposal to just let #! do its standard job)
> then the implication is that there is only one parrot implimentation
> per system.
Yes, this does sound like what was being proposed.
However, nothing prevents you from having more than one parrot kernel
plugin, the selection of which would be distinguished by a version
number in the header of the bytecode file.
> How would one then test new versions of Parrot?
Well, instead of typing in "bytecodeprogram" at the commandline, you
would have to type in "parrot bytecodeprogram", where "parrot" is your
path to your newer version of parrot.
Or perhaps you would do:
parrot_daemon --nokernel &
parrot_send_to_daemon bytecodeprogram
(or something like that)
Obviously this won't be *quite* the same environment as the kernel's
plugged-in parrot interpreter daemon, but it will be sufficiently close
for *most* forms of testing.
> With #! it's easy: you just name the path to the alternative
> interpreter and the kernel invokes it. But if parrotd is built right
> into exec() then in order to support multiple versions of Parrot, you
> would have to build the new versions -in- Parrot and pass them in as
> yet another layer of interpreter.
I don't understand what you mean by this.
> e.g., parrotd version 6.302 is running and it has been passed a copy
> of the bash2parrot 4.19 translator
Err, no. You would have a program which was originally written in bash,
then translated into parrot bytecode. All places where strings need to
be translated at runtime (via the eval command) are set up to load up
the bash translator, then translate that string, then run the string.
The bash2parrot translator would not be *included* in the translated
bytecode, though -- only the name of the module, or maybe the filename
of the module. Vaguely like how one shared object can depend on another
one, or even whole reams of other ones -- but they don't get loaded
until functions in them get called.
> in case it needs to interpret a computed string that invokes a program
Ok, at this point, stop, and take a breath. When your translated bash
program wants to "invoke a program", *how* that program's guts work is
beyond it's concern -- it merely calls fork and exec and wait.
The fact that the exec() may send the filename and args and environment
to a different parrot daemon is irrelevant to that process.
> that needs to layer on the experimental parrotd 6.4.9 interpreter that
What do you mean 'layer on' ?
> has to be passed the perl2parrot translator in case it needs to
Again, nothing is passing around translators -- they only get loaded
when they are needed.
> interpret a computed string that invokes a program
> that needs to have -another copy- of parrotd 6.302 layered on [you
> can't count on parrotd 6.4.9 running parrotd 6.302 programs the same
> way that parrotd 6.302 would run them] that has the <etc.> interpeter
> layered on to run <etc.>.
Your confusion seems to mainly stem from three things: You're not
paying attention to process boundaries, and you think that every
translated program in language X has the translator for X to parrot
embedded into it, and exec() doesn't invoke a sub-process, it replaces
the current process with a new process (That's why you have to fork()
first if you want a sub-process).
Once you have a better understanding of the unix process model, the
problems you've sketched will disappear.
> Scheme is right at home at dealing with these kinds of layering
> issues, using a process called "reflection" [well developed by Brian
> Reid and Jeem Desriviers]. They aren't straight-forward issues: think
> about debugging, and think about re-entrancy, and think about problems
> in cross-layer pollution -- you don't want a wild pointer in the fifth
> layer down to affect your third layer, right?
Fortuantly for us, seperate processes have their own memory address
spaces, so this isn't a concern.
> Speaking of layers: I take it that some thought has been put into
> how to do operating-system escapes? So that one can (for example)
> handle graphics? Or even just sockets? Seeing as some of the most
> popular interpreted languages are by no means restricted to text-only
> and have networking capabilities?
Remember, the parrot interpreter is written in C... it has to be.
Obviously, one would have parrot opcodes which result in calls to C
functions, which perform socket operations or graphics or whatever.
> But of course the appropriate calls could come within one of the
> computed strings, so any escape cannot be absolute and must instead be
> handled via the interpretation layer (c.f. the above in which I showed
> that parrotd must be built in Parrot if you want parrotd to be handled
> at the exec() level...)
You can't write parrotd in parrot -- you have to write it in something
which runs on the hardware (elf or a.out).
Writing parrotd in parrot is similar to writing a turing machine VM in
the language you use to write descriptions of turing machines, and then
having exec() detect when you're running a compiled turing machine and
handing it off to the turing machine VM ... if it doesn't get passed off
to *something* running on the actual hardware, it's going to loop
forever.
--
my $n = 2; print +(split //, 'e,4c3H r ktulrnsJ2tPaeh'
."\n1oa! er")[map $n = ($n * 24 + 30) % 31, (42) x 26]
> Walter Roberson wrote:
> >
[...]
> > Speaking of layers: I take it that some thought has been put into
> > how to do operating-system escapes? So that one can (for example)
> > handle graphics? Or even just sockets? Seeing as some of the most
> > popular interpreted languages are by no means restricted to text-only
> > and have networking capabilities?
>
> Remember, the parrot interpreter is written in C... it has to be.
> Obviously, one would have parrot opcodes which result in calls to C
> functions, which perform socket operations or graphics or whatever.
>
I dont't think it will be opcodes, but rather a combination of loadlib
(load a DLL) and dlfunc (create a parrot-callable subroutine from a
DLL function). See core.ops.
Regards,
Slaven
--
Slaven Rezic - slaven...@berlin.de
Visualize Makefiles with GraphViz:
http://user.cs.tu-berlin.de/~eserte/src/perl/GraphViz-Makefile/
Ok, so loadlib is one op, and dlfunc is another op :)
One particular point of possible interest: there
was, quite predictably a Guile Tk (guile-tk) <URL:
http://wiki.tcl.tk/GuileTk >.
'Fact, I don't think it's obvious right now.
For more on achieved experience with such attempts at
automatic translation, see the histories of CORBA,
SOAP, ...
Then, then:) Some odd twenty years ago some serious money was spent
to prove Esperanto suited to be *the interlingua* for computer based
natural language translation. Being readable was its main advantage:)
--
groetjes, carel
[lots of technical stuff]
Ack. My brain hurts. Make it stop....
--
David K. Wall - use...@dwall.fastmail.fm
/me recalls the captured prisoners in Quake2
> Then, then:) Some odd twenty years ago some serious money was spent
> to prove Esperanto suited to be *the interlingua* for computer based
> natural language translation. Being readable was its main advantage:)
There is at least one automatic language translator used Esperanto (or
an additionally marked up variant) as an intermediary langauage; it
translates from the source language into Esperanto and then into the
destination language:
http://download.travlang.com/Ergane/
--
Erik Max Francis / m...@alcyone.com / http://www.alcyone.com/max/
__ San Jose, CA, USA / 37 20 N 121 53 W / &tSftDotIotE
/ \ The meaning of life is that it stops.
\__/ Franz Kafka
Alcyone Systems' Daily Planet / http://www.alcyone.com/planet.html
A new, virtual planet, every day.
tuple_list = [(1,'a'),(3,'b'),(2,'l'),(8,'p')]
Then I want to get two lists from this tuple_list. The
first list contains the first elements in the tuple of
the tuple_list.
first_list = [1,3,2,8]
And the second list contains all the second elements,
also maintaining the original order as in tuple_list.
second_list = ['a','b','l','p']
So how to get this easily? Thanks!
=====
Cheers
-Mindy
__________________________________________________
Do you Yahoo!?
U2 on LAUNCH - Exclusive greatest hits videos
http://launch.yahoo.com/u2
> Hey, given a tuple t(a,b), is there any function in
> Python that I can get a, b individually from t?
> Actually, I have a list whose element is tuples. Say:
>
> tuple_list = [(1,'a'),(3,'b'),(2,'l'),(8,'p')]
>
> Then I want to get two lists from this tuple_list. The
> first list contains the first elements in the tuple of
> the tuple_list.
>
> first_list = [1,3,2,8]
>
> And the second list contains all the second elements,
> also maintaining the original order as in tuple_list.
>
> second_list = ['a','b','l','p']
>
> So how to get this easily? Thanks!
the magic of zip will do it for you ;-)
>>> first_list, second_list = zip(*tuple_list)
chris
--
Chris <clie...@gmx.net>
>Hey, given a tuple t(a,b), is there any function in
>Python that I can get a, b individually from t?
>Actually, I have a list whose element is tuples. Say:
>
>tuple_list = [(1,'a'),(3,'b'),(2,'l'),(8,'p')]
>
>Then I want to get two lists from this tuple_list. The
>first list contains the first elements in the tuple of
>the tuple_list.
>
>first_list = [1,3,2,8]
>
>And the second list contains all the second elements,
>also maintaining the original order as in tuple_list.
>
>second_list = ['a','b','l','p']
>
>So how to get this easily? Thanks!
>
This sounds like homework. Is it?
Regards,
Bengt Richter
if t is a tuple, then t[0] is the first element, t[1] is the second, etc.
you could also say:
a,b = t
and a will equal the first element, and b the second (assuming t is a length
2 tuple or list)
> Actually, I have a list whose element is tuples. Say:
>
> tuple_list = [(1,'a'),(3,'b'),(2,'l'),(8,'p')]
the old reliable way is:
first_list = []
second_list = []
for a,b in tuple_list:
first_list.append( a )
second_list.append( b )
Which you could make into a function if you need to do it often.
If you are using a recent python (say 2.1 or 2.2), you can possibly use list
comprehensions, but I'll leave that for someone else to explain.
As a short note of style, calling it "tuple_list" is a bit misleading,
because a tuple is not a list, and a list is not a tuple. But they are both
sequences, so I tend to use the label "seq" for such things if they are
temporary, or the suffix "_seq" if I want to specify an object that is
iterable.
You can always convert back and forth using the list() and tuple()
constructors.
Hope this helps.
--
Chad Netzer
cne...@mail.arc.nasa.gov
interesting, but elas: words only. The project I was refering to
aimed higher:)
--
groetjes, carel
dict = {"a":1, "b":3, "l":2, "p":8, "m":(1,2,3,4,5), "z":"blah"}
dict.keys()
>>> ("a", "b", "l", "p","m","z")
dict.values()
>>> (1,3,2,8,(1,2,3,4,5),"blah")
dict["a"]
>>>1
Kevin.
"Mindy" <css...@yahoo.com> wrote in message
news:mailman.1036801694...@python.org...
> dict["m"]
> >>>(1,2,3,4,5)
Thanks for your reply.
In this example, actually what I want is to get
1,2,3,4,5 seperately from (1,2,3,4,5) and put them
into five different lists, say, list1 =
[1],list2=[2],list3=[3],list4=[4],list5=[5].
Is there any simply way to "split" a tuple? Thanks!
a, b, c, d, e = thetuple
will 'split' the tuple as you appear to request: i.e.,
just assign the tuple (which must have exactly five
items) to a target composed of five names.
When you get to as many as five things, this is not
a common tack; rather than keeping five separate list
variables, one would normally keep a list of five lists
and work by looping, e.g.:
listoflists = [ [] for i in range(5) ]
and then
for i in range(5):
listoflists[i].append(thetuple[i])
but that's a choice of practicality and flexibility; if
you prefer to write things out five times, Python most
assuredly doesn't impede you from doing that.
Alex
> Hey, given a tuple t(a,b), is there any function in
> Python that I can get a, b individually from t?
> Actually, I have a list whose element is tuples. Say:
>
> tuple_list = [(1,'a'),(3,'b'),(2,'l'),(8,'p')]
>
> Then I want to get two lists from this tuple_list. The
> first list contains the first elements in the tuple of
> the tuple_list.
>
> first_list = [1,3,2,8]
>
> And the second list contains all the second elements,
> also maintaining the original order as in tuple_list.
>
> second_list = ['a','b','l','p']
>
> So how to get this easily? Thanks!
Probably easiest is with list comprehensions:
first_list = [ first for first, second in tuple_list ]
second_list = [ second for first, second in tuple_list ]
One alternative (more verbose, maybe even simpler)
is with an explicit loop:
first_list = []
second_list = []
for first, second in tuple_list:
first_list.append(first)
second_list.append(second)
Yet another (more concise, maybe a bit obscure) hinges
on built-in function zip and the *args construct for
passing all items of a sequence as individual positional
parameters:
first_list, second_list = map(list, zip(*tuple_list))
zip(*tuple_list) would by nature return a list of
TUPLES, i.e. (1, 3, 2, 8) and ('a', 'b', 'l', 'p'),
rather than of lists as you wish -- which is why we
map the built-in callable named `list` (costructor
of the list type) over the result to build a list
from each of the tuples. A similar idea can also
use list comprehensions rather than map, of course:
first_list, second_list = [list(x) for x in zip(*tuple_list)]
As you can see, we're alas quite a way from our ideal
of "one, and preferably only one, obvious way" to perform
a task. Personally, I'd choose the very first idiom I
suggested here, to repeat:
first_list = [ first for first, second in tuple_list ]
second_list = [ second for first, second in tuple_list ]
on the grounds that it IS obvious -- indeed, utterly
simple. "Do the simplest thing that can possibly work"...
Alex
And Guile programmrs is the right choice of words. Most Scheme
programmers does not use Guile. In most cases there are better
alternatives such as DrScheme and Bigloo.
A common bytecode that Perl, Python, Ruby and Tcl would all compile to? Hmm.
Scary, and for several reasons. Firstly, I'm not at all convinced that the
object models are compatible enough. And secondly, how are you going to avoid
requiring a resident interpreter/compiler to handle the case where you've got
dynamic code coming from a source that doesn't generate parrot bytecodes
directly (e.g. a normal programmer^Wperson!) After that, there's worrying about
security models to do as well. ;^)
One way forward, at least with Tcl, would be to implement a Tcl interpreter in
terms of parrot bytecodes (rather like Jacl is a Tcl interp written in Java) but
that tends to bring out questions like "why bother?" Could it be done without
requiring a chunky auxiliary C library to provide little things like
cross-platform select() support? This sort of thing tends to make me suspicious
that this is little more than a pipe-dream, well, at least as far as Tcl's
concerned. (I don't know the other languages nearly well enough to comment in a
useful way.)
Alternatively, formulate Parrot as a sort-of disjoint union of the bytecodes
used in each language, so unifying them without unifying anything. >:^D
Donal.
--
Donal K. Fellows http://www.cs.man.ac.uk/~fellowsd/ donal....@man.ac.uk
-- OK, there is the MFC, but it only makes the chaos object orientated.
-- Thomas Nellessen <nell...@gmx.de>
[Scary ... worrying ... security ... suspicious ... pipe-dream]
Brazil (1985).
--
Joe Schaefer "The eternal mystery of the world is its comprehensibility."
--Albert Einstein
If you were writing a VM for one language, and then tried to extend it
for the others, then I would agree wholeheartedly. However, it's no
more strange than using MSIL for C++ and VB and other languages.
> And secondly, how are you going to avoid requiring a resident
> interpreter/compiler to handle the case where you've got
> dynamic code coming from a source that doesn't generate parrot
> bytecodes directly (e.g. a normal programmer^Wperson!)
In all cases that I can think of, your dynamic code is essentially a
string which gets eval()ed (with a language-dependent eval). The
solution is to make the eval() function/operator compile into a sequence
of operations along the lines of: Load the compiler for this language,
(if it's not already loaded), pass that string to the compiler, run the
generated bytecode.
> After that, there's worrying about security models to do as well. ;^)
>
> One way forward, at least with Tcl, would be to implement a Tcl
> interpreter in terms of parrot bytecodes (rather like Jacl is a Tcl
> interp written in Java)
Considering that Jcl and Jython exist, it seems like a reasonable goal
would be to make an interpreter which turns Java's .class files into
Parrot .pasm files. Once that tool exists, one could simply translate
Jcl and Jython into parrot... there would be no need to re-implement
them.
And one day, in the distant future, there will be a Perl6 decompiler,
which will turn Parrot bytecode into Perl6. Then we'll be able to
convert the translated Jython and Jcl into Perl6 :)
> but that tends to bring out questions like "why bother?" Could it be
> done without requiring a chunky auxiliary C library to provide little
> things like cross-platform select() support?
No matter *what* language you're using, some sort of interface to select
or poll will be needed, and that interface would be implemented in C.
Whether it's "chunky" or not depends on how that interface appears on
the high-level end of things.
> This sort of thing tends to make me suspicious that this is little
> more than a pipe-dream, well, at least as far as Tcl's concerned. (I
> don't know the other languages nearly well enough to comment in a
> useful way.)
>
> Alternatively, formulate Parrot as a sort-of disjoint union of the
> bytecodes used in each language, so unifying them without unifying
> anything. >:^D
The set of bytecodes which Parrot will be using has been decided, and
while it's not fixed in stone, it's quite unlikely to get a whole other
language's bytecodes added to it.
Assuming you thouroughly understand Tcl's bytecodes, why not take a look
at Parrot, and see whether the set of bytecodes that parrot supports is
sufficient to do everything that Tcl's bytecodes do?
Seems like an awful lot of overhead for every keystroke, window event,
and async file operation.
Why would any of these require that strings be eval()ed?
You compile the string to bytecode, *once*, and pass this compiled code
as the callback for your keystrokes, window events, and async file
operations. You wouldn't pass a string to be eval()ed -- that would be
silly.
Furthermore, even if one did do something that foolish, the compiler
needs to be loaded only once... So, (ignoring the first one, where the
compiler gets loaded) each keystroke, window event, or async file
operation would merely compile the string to bytecode, then run the
bytecode. This is no different from what Tcl does all the time, except
that it's a different kind of bytecode.
Bindings substitute their values. File events get additional arguments.
Etc.
> Furthermore, even if one did do something that foolish, the compiler
> needs to be loaded only once...
I missed your parenthetical comment on first reading. Yes, sorry.
So? Pass these in as arguments. There's no need to recompile a
procedure for each and every different set of arguments that might be
passed to it. That would defeat the point of having procedures in the
first place.
> > Furthermore, even if one did do something that foolish, the compiler
> > needs to be loaded only once...
>
> I missed your parenthetical comment on first reading. Yes, sorry.
Peculiar -- if I'd been reading someone else's description of it, and he
didn't say, "(if it's not already loaded)", I would have *assumed* that
it wouldn't be loaded if it already had been, *unless* he said something
to the contrary (like, "yes, I really do mean reload the compiler from
disk each and every time we eval() a string")
A binding isn't a procedure. Indeed, I'm pretty sure that [eval] doesn't
cache bytecode in bindings because it's more inefficient than
regenerating the bytecodes each time. It's good style to invoke a
procedure, but hardly necessary. And indeed, putting something like
"break" or "continue" inside a procedure called by a binding doesn't
have the same effect as putting it in the binding.
That depends on your interface to Tk ... in perl, a binding *is* a
procedure. Well, actually it's either a procedure or a method name.
bind $b '<Button>', sub { print "Button pressed.\n" };
The 'sub' keyword creates an unnamed procedure.
> Indeed, I'm pretty sure that [eval] doesn't
> cache bytecode in bindings because it's more inefficient than
> regenerating the bytecodes each time. It's good style to invoke a
> procedure, but hardly necessary. And indeed, putting something like
> "break" or "continue" inside a procedure called by a binding doesn't
> have the same effect as putting it in the binding.
What are the semantics of "break" and "continue" in a procedure, when
they don't refer to a label or loop within that procedure?
> Darren New wrote:
> > Seems like an awful lot of overhead for every keystroke, window event,
> > and async file operation.
>
On Mon, Nov 11, 2002 at 02:31:33PM -0500, Benjamin Goldberg wrote:
> Why would any of these require that strings be eval()ed?
In Tk, every event binding is a string which is substituted and then
treated as code, eg
bind .b <Button> { puts "Clicked %W" }
This substitution is of a different kind than the normal $-substitution
of commands as they are executed (indeed, $-substitution will take place
next, so that
bind .b <Button> { puts "$%W" }
will write to stdout the contents of the variable with the same name as
the clicked widget.
Tcl/Tk optimization guides seem to have long recommended putting no code
of consequence in a widget binding, for this very reason.
Jeff
They return with a different exit code, I believe. In other words, it
depends on the caller.
Security and Microsoft outlook/Internet Explorer - past 5 years or more...
--
Tcl - The glue of a new generation. <URL: http://wiki.tcl.tk/ >
Even if explicitly stated to the contrary, nothing in this posting
should be construed as representing my employer's opinions.
<URL: mailto:lvi...@yahoo.com > <URL: http://www.purl.org/NET/lvirden/ >
(JCL is something else. I'd rather not remember it thankyouverymuch.)
> would be to make an interpreter which turns Java's .class files into
> Parrot .pasm files. Once that tool exists, one could simply translate
> Jcl and Jython into parrot... there would be no need to re-implement
> them.
>
> And one day, in the distant future, there will be a Perl6 decompiler,
> which will turn Parrot bytecode into Perl6. Then we'll be able to
> convert the translated Jython and Jcl into Perl6 :)
$10 says that only ever happens with a performance hit. The problem is that not
all bytecodes are created equal. (And Jacl is an implementation of Tcl in Java
more in the way that the usual form of Tcl is an implementation of the language
in C. The fact that Java uses bytecodes is pretty much just a distraction
here. We also have another way of integrating Tcl with Java that keeps Tcl
implemented in C, but which integrates almost identically with the Java
language.)
> > This sort of thing tends to make me suspicious that this is little
> > more than a pipe-dream, well, at least as far as Tcl's concerned. (I
> > don't know the other languages nearly well enough to comment in a
> > useful way.)
[...]
> Assuming you thouroughly understand Tcl's bytecodes, why not take a look
> at Parrot, and see whether the set of bytecodes that parrot supports is
> sufficient to do everything that Tcl's bytecodes do?
I know a bit about Tcl bytecodes, and a key factor about them is that they are
very tightly targetted towards implementing Tcl.
Hmm. A quick scan through the documentation doesn't really raise my hopes. Or
even leave me with a deep enough understanding of what's going on; is there any
deeper description than http://www.parrotcode.org/docs/parrot_assembly.pod.html
about? (OK, Tcl's bytecodes need documentation too, but I've already gone to
the effort to understand those as part of my maintenance and development
duties. I've just not got enough hours in the day.) Unfortunately, the bits
that I'm most interested in seem to be the bits with least info (isn't that
always the way with complex software systems?)
First impressions: what is meant by "string" anyway? Character sequence? Byte
sequence? UTF-8 sequence? ISO 8859-1 sequence? [FX: Reads docs] Oh, they
carry about what their encoding is with them? That must make working with them
fun. How does it handle things like the blecherous monstrosities[*] used for
system encodings in the Far East? On a quite separate point, is there a
strncmp() equivalent? That would make implementing Tcl much easier...
More generally, Tcl would need to use PMCs throughout. The problem is that
Tcl's value semantics (copy-on-write) do not line up well with that which Parrot
seems to use (object-based) and which, IIRC from the discussions at the time
when Parrot was being created, are closely based on those used in Perl even if
not precisely coincident. Hence we'd be unable to use ground values except as
part of the implementation of higher-level concepts. That'll impact badly on
performance.
It's at this point that I feel a round of "Stuff it. I'll stick to implementing
in C." coming on. I've been quietly watching Parrot for a while now, and I
still don't think that implementing Tcl in it is really a winning proposition.
I'd love someone to prove me wrong, but proof is building a Tcl interpreter in
or on top of Parrot and running the Tcl test suite on it (and getting a decent
proportion of the tests passing.)
BTW, how does Parrot handle calls to foreign code? The docs I've seen are on
the hazy side, and integration with existing C, C++ and FORTRAN monoliths is
(alas) all too important in particularly commercial development.
Donal.
[* The cluster of things known as "Shift-JIS" justifies this term. IMHO. ]
--
Donal K. Fellows http://www.cs.man.ac.uk/~fellowsd/ donal....@man.ac.uk
-- The small advantage of not having California being part of my country would
be overweighed by having California as a heavily-armed rabid weasel on our
borders. -- David Parsons <o r c @ p e l l . p o r t l a n d . o r . u s>
OK, let's go for a more concrete question. What sequence of bytecodes would let
me open a socket and talk to a remote host? The Parrot I/O operation opcodes
don't mention anything about sockets and nor can I tell how I would invoke a
piece of helper C or C++ to do the job on my behalf.
Donal.
--
Donal K. Fellows http://www.cs.man.ac.uk/~fellowsd/ donal....@man.ac.uk
<snip interesting discussion, which mostly goes over my head :>
>
> BTW, how does Parrot handle calls to foreign code? The docs I've seen are on
> the hazy side, and integration with existing C, C++ and FORTRAN monoliths is
> (alas) all too important in particularly commercial development.
>
On this particular point; has anyone thought of writing a unified C-API for Tcl,
Perl, Python, Ruby, (Java) etc? What I mean by this is that each of these
languages can be extended in C, and quite often are. Also, whenever I see
interesting new C/C++ libraries implemented, I also tend to see seperate
language bindings for each of these languages. This seems like a massive
duplication of effort. Would it be possible to abstract over the C API's of
these languages to a common core of functionality which all share (e.g. getting
an interpreter handle, registering a command, setting a variable etc)? I have
only dealt with Tcl's C interface, so this may be too difficult, but it seems
like it would be a huge step forward.
In terms of problems implementing this, I can see several problems:
1. Method of calling C-coded procedures. In Tcl, arguments are passed to C
procedures as Tcl_Obj's. Obviously this would be different for Perl or Python.
Is it possible to come up with an API which can convert to the appropriate
object type, or to some intermediate type?
2. Accessing functions which are not present in all languages. I'm sure there
are API's in Tcl which only make sense with respect to Tcl, and probably the
same in the other languages. So, how would one create a general API which
allows you to call language specific APIs? In the same way one handles platform
specific APIs?
3. Versioning. Which language versions are compatible with which abstract API? I
can see this one becoming insane over time. However, there are people with much
more experience with these issues than me, so there might be a way.
4... probably more, this is all coming of the top of my head.
Hmm.. the more I think about this, the more problems it seems to present. I'd
love to be able to write an extension, and have it instantly work with x
different langauges. Also, I'd love to be able to use Python and Perl
extensions from Tcl, without loading seperate interpreters and all that. Am I
dreaming of an impossible Utopia?
Neil "soo naive" Madden
--
package r Tkhtml;package r http;pack [scrollbar .v -o v -co {.h yv}] -s right\
-f y;pack [html .h -ys {.v set}] -f both -e 1;bind .h.x <1> {eval g [.h href %x\
%y]};proc g u {set t [http::geturl $u];.h cl;.h p [http::data $t];http::cleanup\
$t;.h co -base $u};g http://mini.net/tcl/976.html;proc bgerror args {};# NEM :-)
Erm... that's the old IBM Job Control Language? You mean this one?
http://www.tuxedo.org/~esr/jargon/html/entry/JCL.html
Bleh, forget I mentioned it. :) Twas a horrible typo :)
> > would be to make an interpreter which turns Java's .class files into
> > Parrot .pasm files. Once that tool exists, one could simply
> > translate Jcl and Jython into parrot... there would be no need to
> > re-implement them.
> >
> > And one day, in the distant future, there will be a Perl6
> > decompiler, which will turn Parrot bytecode into Perl6. Then we'll
> > be able to convert the translated Jython and Jcl into Perl6 :)
>
> $10 says that only ever happens with a performance hit. The problem
> is that not all bytecodes are created equal. (And Jacl is an
> implementation of Tcl in Java more in the way that the usual form of
> Tcl is an implementation of the language in C.
So Jacl still converts Tcl into, well, Tcl bytecodes, even though it's
doing so in Java? Blech.
Hmm, is there a way of making tcl dump the tcl-bytecodes to a file?
If so, one could probably make an attempt to translate those bytecodes
into parrot. (And ignore Jacl).
Having read http://www.parrotcode.org/docs/strings.pod.html only just
now myself, it's possible I could be wrong on this, but...
Each string's encoding can be one of native, utf8, utf16, utf32, or
foreign. So those "blecherous monstrosities" will either be converted
to one of the utf formats, or else have their own string vtable.
For now, they will probably be converted... the strings.pod.html says
this at the bottom:
Foreign Encodings
Fill this in later; if anyone wants to implement
new encodings at this stage they must be mad."
> On a quite separate point, is there a strncmp() equivalent? That
> would make implementing Tcl much easier...
You mean, for testing the first n characters of two strings for
equality? There isn't that I know of, but one could always be added;
furthermore, it supposedly will be possible to make lightweight strings
which are substrings of other strings, without any copying involved.
You could make your strncmp be a wrapper around making a substring of
the first n characters of each of your two strings, and comparing those
substrings.
> More generally, Tcl would need to use PMCs throughout.
Why? (Not an objection, but I don't know much about Tcl's bytecode)
> The problem is that Tcl's value semantics (copy-on-write) do not line
> up well with that which Parrot seems to use (object-based)
Parrot will do copy-on-write.
Furthermore, Parrot may implement some strings as ropes, so that the
amount that needs to be copied will be even smaller.
> and which, IIRC from the discussions at the time when Parrot was being
> created, are closely based on those used in Perl even if not precisely
> coincident.
Perl is likely never going to implement strings as ropes. It does now
have copy-on-write, though this is a recent development.
Perl5.6+ has two internal encodings for strings -- bytes and utf8.
Parrot not only allows native, utf8, utf16, and utf32, but it also
allows any kind of user-defined encoding one might want. I doubt that
perl5 will ever do this.
> Hence we'd be unable to use ground values except as part of the
> implementation of higher-level concepts. That'll impact badly on
> performance.
>
> It's at this point that I feel a round of "Stuff it. I'll stick to
> implementing in C." coming on. I've been quietly watching Parrot for
> a while now, and I still don't think that implementing Tcl in it is
> really a winning proposition.
> I'd love someone to prove me wrong, but proof is building a Tcl
> interpreter in or on top of Parrot and running the Tcl test suite on
> it (and getting a decent proportion of the tests passing.)
Parrot does everything in two steps -- compile, then run. Most likely,
it will have a compiler which converts Tcl bytecode to Parrot bytecode.
Whether or not Parrot will ever translate from Tcl source to Parrot
bytecode is another question entirely.
Thinking a bit more, particularly about how Tcl often needs to interpret
strings at runtime, I realize that no non-trivial Tcl program can work
without having a string-to-bytecode compiler. Needless to say, this
poses a problem.
> BTW, how does Parrot handle calls to foreign code? The docs I've seen
> are on the hazy side, and integration with existing C, C++ and FORTRAN
> monoliths is (alas) all too important in particularly commercial
> development.
Although I don't know *how* it will handle foreign code, I do know that
it *will* handle foreign code, and have a better interface than Perl5's
cruddy XS extension language.
> Donal K. Fellows wrote:
>
> <snip interesting discussion, which mostly goes over my head :>
>
> >
> > BTW, how does Parrot handle calls to foreign code? The docs I've seen are on
> > the hazy side, and integration with existing C, C++ and FORTRAN monoliths is
> > (alas) all too important in particularly commercial development.
> >
>
> On this particular point; has anyone thought of writing a unified C-API for Tcl,
> Perl, Python, Ruby, (Java) etc? What I mean by this is that each of these
> languages can be extended in C, and quite often are. Also, whenever I see
> interesting new C/C++ libraries implemented, I also tend to see seperate
> language bindings for each of these languages. This seems like a massive
> duplication of effort. Would it be possible to abstract over the C API's of
> these languages to a common core of functionality which all share (e.g. getting
> an interpreter handle, registering a command, setting a variable etc)? I have
> only dealt with Tcl's C interface, so this may be too difficult, but it seems
> like it would be a huge step forward.
Look at
http://www.swig.org/
Regards,
Slaven
--
Slaven Rezic - slaven...@berlin.de
Tired of using file selectors? Real programmers use the TAB key for
completion and not for jumping around. Try
http://search.cpan.org/search?mode=module&query=Tk::PathEntry
Just as there are "stdio", "unix", and "win32" ParrotIO layers, one
would define a "socket" layer (and maybe an "xti" layer, for the really
adventurous). Obviously, this needs a bit more C code to be added.
Once that layer is added, you could read from and write to sockets just
like you would from files.
"Neil Madden" <nem...@cs.nott.ac.uk> wrote in message
news:LRaA9.1325$J55.2...@newsfep2-win.server.ntli.net...
> Hmm.. the more I think about this, the more problems it seems to present.
I'd
> love to be able to write an extension, and have it instantly work with x
> different langauges. Also, I'd love to be able to use Python and Perl
> extensions from Tcl, without loading seperate interpreters and all that.
Am I
> dreaming of an impossible Utopia?
I wrote some DLL helper logic that makes it easy to query a vtable by name
in another DLL.
The vtables can be created in whatever way, but the vtable is not assocated
with allocated memory, as is the case with COM. This makes it quite flexible
without really being limited because one could decide that the first
function should return a 'this' pointer and the second function should be
the destructor, or whatever.
In any DLL that can link statically with a piece of C, you can use this
framework to pass functions around. (Even if you can only link dynamically,
you could have a helper dll to expose vtables). I use some #define macros to
create the vtables statically (see snippet below). It's then very easy to
take arbitrary C functions and wrap them up in one or more vtables. However,
vtables need not be statically allocated (and this is significantly
different from public dll functions).
Because the vtables are looked up by name initially, you could handle
versioning like in COM: "mycomponent.vtablename.1", where
"mycomponent.vtablename" would refer to the most recent version - but it is
preferable to always specificy an exact version.
Contrary to COM this is completely cross platform as there is no OS magic
involved.
When a vtable is created, it is helpful to write a C prototype struct that
matches, because this makes things easier clientside - but it is not
required (see snippet below).
On the clientside I wrote some small wrappers to ease loading dll's
dynamically and in C++ to wrap the optional prototype. I only did this for
Windows, but the principles are essentially the same on Linux, just like
Ruby loads .so files.
The framework is generic - here is what I did to access functionality in a
OCaml parser application I wrapped up as selfcontained dll - without using
public dll functions except for init, query vtable and uninit functions: I
picked all the most relevant OCaml API logic for allocating memory on the
OCaml runtime stack and created a set of vtables approximately one for each
.h file in the API. The Ocaml OCaml functions I wrote (parse_file) I had to
dynamically call a function to locate the OCaml function address. In the dll
init logic I performed this operation and added the result to a vtable
already prepared for the purpse. The client of the dll loads the dll, calls
init and then queries relevant vtables, but in principle has no clue that it
really is OCaml the executes the logic (in principle because in praxis I
wanted to know in order to efficiently allocate memory).
The same thing could be done in Ruby, wrapping rb_... functions into vtables
and having separate vtables for calling Ruby code - this vtables would be
created dynamically or at least filled dynamically.
Any language that supports C integration and dynamic link libraries can use
this framework.
Incidentally Parrot works a lot with vtables, so there could be some overlap
here (I didn't know that at the time I wrote the framework though).
I have not put the code online, but if anyone is interested, let my know.
Below is a readme snippet, a bit technical and not the only way to use the
framework (it would be possible to map Ruby functions into dynamically
created vtables for instance).
Mikkel
<snip>
Interfaces are organized in vtable maps which are statically allocated
arrays of VtblMapEntries.
VTBL_MAP_BEGIN(<vtbl_map_name>)
VTBL_MAP_ENTRY(name, vtbl)
... more entries here ...
VTBL_MAP_END
The name <vtbl_map_name> is later used be the linker, such that the map
can be hooked into a master
map of all vtable interfaces compiled together.
The master map is located in a central compilation unit such that new
vtable maps can easily be
added to the master map without modifying the source of any of the
existing map providers.
Before entering the map into the mastermap, it must be declared - unless
the map is earlier in the same
compilation unit as the master map:
VTBL_DECLARE_MAP(<vtbl_map_name>)
... more maps declared here ...
Following the map declareations, there is a master map which is scanned
by the default lookup function:
VTBL_MASTER_MAP_BEGIN(<vtbl_master_map_name>)
VTBL_MASTER_MAP_ENTRY(<vtbl_map_name>)
... more master map entries here ...
VTBL_MASTER_MAP_END
Typically, a dynamically loaded library (dll) will have a purpose
specific mastermap using a selection
of available vtbl interface maps.
Example:
we have the following functions in a .c file. Moreover, we have the
malloc and free functions
from the std library. We want all four functions wrapped in two
interfaces: FooBar and Mem.
First we create a header file for the interfaces:
<file "examples.h">
struct
{
int (*get)(int x);
void (*set)(int x, int val);
void *(*create)(int x);
} ExamplesVectorVtbl;
struct
{
void *(*allocate)(size_t size);
void (*deallocate)(void *p);
} ExamplesMemoryVtbl;
</file>
<file "examples.c">
#include <memory.h>
#include "vtbl.h"
#include "examples.h"
void set(void *p, int x, int val) { return ((int*)p)[x] = val; };
int get(void *p, int x) { return ((int*)p)[x]; }
void *create(int x) { return calloc(x * sizeof(int)); };
ExamplesVectorVtbl { get, set, create } vector_vtbl;
/* shows that existing library functions can be packaged as well */
ExamplesMemoryVtbl { calloc, free } mem_vtbl;
VTBL_MAP_BEGIN(examples_vtbl_map)
VTBL_MAP_ENTRY("Examples.Vector", vector_vtbl)
VTBL_MAP_ENTRY("Examples.Memory", mem_vtbl)
VTBL_MAP_END
</file>
<file "master.c">
/* to get vtbl.h and the lookup function in vtbl.c */
#include "vtbl.c"
VTBL_DECLARE_MAP(examples_vtbl_map)
VTBL_MASTER_MAP_BEGIN(vtbl_master_map)
VTBL_MASTER_MAP_ENTRY(examples_vtbl_map)
VTBL_MASTER_MAP_END
void *GetNamedInterface(char *name)
{
return vtbl_master_map_lookup(vtbl_master_map, name);
}
</file>
<file "client.c">
#include "examples.h"
void *GetNamedInterface(char *name);
void test()
{
/* since interfaces are static, pMem and pVec need not be
deallocated */
Examples_Memory *pMem =
(Examples_Memory*)GetNamedInterface("Examples.Memory");
Examples_Vector *pVec =
(Examples_Vector*)GetNamedInterface("Examples.Vector");
void *v1 = pMem->allocate(sizeof(int[4]));
void *v2 = pVec->create(4);
pVec->set(v1, 2, 42);
pVec->set(v2, 0, pVec->get(v1, 2));
pMem->deallocate(v1);
pMem->deallocate(v2);
}
</file>
Typically the client would have loaded a dynamically linked library and
found the address of the published
GetNamedInterface function. Once that function is avaible, it is easy to
access all the remaining functions
via the named interfaces.
</snip>