Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

--pirate and coroutines

2 views
Skip to first unread message

Michal

unread,
Oct 7, 2004, 11:09:46 PM10/7/04
to perl6-i...@perl.org

Hey all,

Here's a simple hand coded example that
(correctly, AFAIK) prints "ab" in vanilla
parrot, but goes off in an infinite
loop with the --python flag.

Why does --python mode modify the
behaviour of coroutines?

I thought perhaps they were used for
generators or "for...in" iteration, but
that doesn't seem to be the case. I
can't find any python stuff that uses
them at all. Is it dead code, or am I
missing something?

Sam sent me a patch for pirate that leans
on the work done in --python... I just got
my generator code working with vanilla
parrot, but it doesn't work at all with
the --python flag.

I know the --python stuff is temporary but
it would be nice to be able to integrate
the pie-thon code with pirate.

- Michal
http://withoutane.com/


## gen.pir #############################
#
# parrot gen.pir : prints "ab"
# parrot --python gen.pir : hangs
#

.sub __main__
.local object gen
.local object res

gen = global "_gen_g"

loop:
res = gen()
print res
goto loop

end
.end

.sub _gen_g prototyped
.local object res
res = new PerlString

res = "a"
.pcc_begin_yield
.return res
.pcc_end_yield

res = "b"
.pcc_begin_yield
.return res
.pcc_end_yield

print "\n"
end
.end

Leopold Toetsch

unread,
Oct 8, 2004, 4:31:08 AM10/8/04
to Michal, perl6-i...@perl.org
Michal wrote:
>
> Hey all,

>
> Why does --python mode modify the
> behaviour of coroutines?

Guido is to blame. Python generators/coroutines work like this:

iter = coro() # first time calling
for x = iter() ...# iterate

And that's what Parrot is doing too with the --python switch. But there
is more ugliness: Python returns "None" if the generator is left through
the end and a StopIteration is thrown (which you have to catch).

That's all really messy and needs definitely some cleanup. OTOH it was
the most straight forward translation of Python bytecode.

$ parrot --python pcoro.txt
StopIteration
in file '(unknown file)' near line -1
ab
$ cat pcoro.txt


.sub __main__
.local object gen
.local object res

.local object iter

gen = global "_gen_g"

iter = gen()
.local pmc None
None = new .None
loop:
unless iter, ex
res = shift iter
if res == None goto ex
print res
goto loop
ex:
end
.end

.sub _gen_g prototyped
.local object res
res = new PerlString

res = "a"
.pcc_begin_yield
.return res
.pcc_end_yield

res = "b"
.pcc_begin_yield
.return res
.pcc_end_yield

.local pmc None
None = new .None
.pcc_begin_return
.return None
.pcc_end_return
.end


Sam Ruby

unread,
Oct 8, 2004, 11:59:08 AM10/8/04
to Leopold Toetsch, Michal, perl6-i...@perl.org
Leopold Toetsch wrote:

> Michal wrote:
>
>> Hey all,
>>
>> Why does --python mode modify the
>> behaviour of coroutines?
>
> Guido is to blame. Python generators/coroutines work like this:
>
> iter = coro() # first time calling
> for x = iter() ...# iterate
>
> And that's what Parrot is doing too with the --python switch. But there
> is more ugliness: Python returns "None" if the generator is left through
> the end and a StopIteration is thrown (which you have to catch).
>
> That's all really messy and needs definitely some cleanup. OTOH it was
> the most straight forward translation of Python bytecode.

Ultimately, it would be nice if Perl and Python could run on the same
instance of Parrot; this would be pretty much be precluded by switches
such as this.

Pirate is currently running with --python due to a number of Python
specific behaviors introduced into a number of PMCs. I'd like to revert
back to running without the --python switch... which would require the
introduction of a number of new Python PMCs.

The number of such PMCs would likely number between one and three dozen.
I'm quite willing to work on a series of patches that adds these in
stages.

Are Python specific PMCs the right way to go? What are the implications
of having a PerlString and a PyString? I guess ultimately we are going
to need to decide what to do with things like:

mmd_lookup(MMD_ADD, PerlString, PyString)

Will the combinatorics involved in adding a new language overwhelm us?

Should the Python specific behavior be removed from the Perl PMCs? If
so, when?

- Sam Ruby

Michal

unread,
Oct 8, 2004, 2:15:51 PM10/8/04
to Leopold Toetsch, perl6-i...@perl.org
On Fri, 8 Oct 2004, Leopold Toetsch wrote:


> Guido is to blame. Python generators/coroutines work like this:
>
> iter = coro() # first time calling
> for x = iter() ...# iterate
>
> And that's what Parrot is doing too with the --python switch. But there
> is more ugliness: Python returns "None" if the generator is left through
> the end and a StopIteration is thrown (which you have to catch).
>
> That's all really messy and needs definitely some cleanup. OTOH it was
> the most straight forward translation of Python bytecode.


I get it now. Thanks.

When you have the AST handy, it's easier and cleaner
to just produce a different set of opcodes when you
know you're in a generator. Instead of returning None
at the end, pirate just directly raises a StopIteration
exception. That seems to me like it's a lot cleaner.

Is there any way we could get a temporary --pirate flag that
did everything --python did EXCEPT for the generator stuff?


- Michal
http://withoutane.com/

Dan Sugalski

unread,
Oct 8, 2004, 2:49:52 PM10/8/04
to Sam Ruby, Leopold Toetsch, Michal, perl6-i...@perl.org
At 11:59 AM -0400 10/8/04, Sam Ruby wrote:
>Leopold Toetsch wrote:
>
>>Michal wrote:
>>
>>>Hey all,
>>>
>>>Why does --python mode modify the
>>>behaviour of coroutines?
>>
>>Guido is to blame. Python generators/coroutines work like this:
>>
>> iter = coro() # first time calling
>> for x = iter() ...# iterate
>>
>>And that's what Parrot is doing too with the --python switch. But
>>there is more ugliness: Python returns "None" if the generator is
>>left through the end and a StopIteration is thrown (which you have
>>to catch).
>>
>>That's all really messy and needs definitely some cleanup. OTOH it
>>was the most straight forward translation of Python bytecode.
>
>Ultimately, it would be nice if Perl and Python could run on the
>same instance of Parrot; this would be pretty much be precluded by
>switches such as this.
>
>Pirate is currently running with --python due to a number of Python
>specific behaviors introduced into a number of PMCs. I'd like to
>revert back to running without the --python switch... which would
>require the introduction of a number of new Python PMCs.

As would I. I'd like to hold off until after 0.1.1 gets released this
weekend (give or take) but after that I'm all for diving into this
and getting it nailed down. If it comes together quickly we can put
out a 0.1.2 release with everything fixed up.

>The number of such PMCs would likely number between one and three
>dozen. I'm quite willing to work on a series of patches that adds
>these in stages.

Cool. One of the things we should do, and if one of the Ruby guys
wants to chime in that'd be great, is to see where we've got areas of
commonality so we can see about sharing most of the PMC code with
common parent classes or something.

>Are Python specific PMCs the right way to go?

Mostly, yes.

> What are the implications of having a PerlString and a PyString? I
>guess ultimately we are going to need to decide what to do with
>things like:
>
> mmd_lookup(MMD_ADD, PerlString, PyString)
>
>Will the combinatorics involved in adding a new language overwhelm us?

Possibly, yeah. The MMD system should do inheritance, though that's
not in right now. That ought to cut down on the combinatorial problem.

It's also likely, for better or worse, that the various language base
types will have minimal knowledge of each other. There's not much for
that, unfortunately -- if we have a system with 50 or 60 basic types
(factoring in the perl 5, perl 6, python, ruby, and basic parrot
types) there's going to be a lot of code to write.

On the one hand that's going to be a pain. On the other, it's a pain
because we get functionality (i.e. data sharing across langauges)
that we didn't have before, so I can live with that. :)

>Should the Python specific behavior be removed from the Perl PMCs?
>If so, when?

Yes, and right after we release 0.1.1.
--
Dan

--------------------------------------it's like this-------------------
Dan Sugalski even samurai
d...@sidhe.org have teddy bears and even
teddy bears get drunk

Leopold Toetsch

unread,
Oct 9, 2004, 5:21:09 AM10/9/04
to Michal, perl6-i...@perl.org
Michal <mic...@withoutane.com> wrote:

> When you have the AST handy, it's easier and cleaner
> to just produce a different set of opcodes when you
> know you're in a generator.

Yep.

> Is there any way we could get a temporary --pirate flag that
> did everything --python did EXCEPT for the generator stuff?

Probably not. We'll have a set of PMCs that do the right thing.
A better idea is just to fix coroutines. I don't care if pie-thon.pl
breaks.

> - Michal

leo

Sam Ruby

unread,
Oct 9, 2004, 10:46:20 AM10/9/04
to perl6-i...@perl.org
Dan Sugalski wrote:
>
>> Are Python specific PMCs the right way to go?
>
> Mostly, yes.
>
>> What are the implications of having a PerlString and a PyString? I
>> guess ultimately we are going to need to decide what to do with things
>> like:
>>
>> mmd_lookup(MMD_ADD, PerlString, PyString)
>>
>> Will the combinatorics involved in adding a new language overwhelm us?
>
> Possibly, yeah. The MMD system should do inheritance, though that's not
> in right now. That ought to cut down on the combinatorial problem.
>
> It's also likely, for better or worse, that the various language base
> types will have minimal knowledge of each other. There's not much for
> that, unfortunately -- if we have a system with 50 or 60 basic types
> (factoring in the perl 5, perl 6, python, ruby, and basic parrot types)
> there's going to be a lot of code to write.
>
> On the one hand that's going to be a pain. On the other, it's a pain
> because we get functionality (i.e. data sharing across langauges) that
> we didn't have before, so I can live with that. :)

A review of the current use of PARROT_PYTHON_MODE checks inside of
classes/*.pmc shows that the predominant use of this is to override the
get_string method to perform python specific formating.

* The Co-Routine pmc also has a part of the inter/next Python
implementation.

* The PerlNum pmc also overrides repr, and has a puzzling change to
the behavior of set_number_native(*).

* The PerlString pmc is more interesting in that it overrides add and
modulus.

For complete compatibility with CPython, a PyInt pmc would also differ
in the divide method.

Python is also considerably more strict than the current Parrot PMCs.
Addition of a number to a string causes a TypeError exception to be raised.

What we are likely to end up with is a nearly complete disjoint set of
PMCs per language.

Inheritance can reduce the combinatorial problem, but it can introduce a
precendence question. The most interesting case still seems to be:

mmd_lookup(MMD_ADD, PerlString, PyString)

- Sam Ruby

Michal

unread,
Oct 9, 2004, 4:23:10 PM10/9/04
to Sam Ruby, perl6-i...@perl.org
On Sat, 9 Oct 2004, Sam Ruby wrote:

> Inheritance can reduce the combinatorial problem, but it can introduce a
> precendence question. The most interesting case still seems to be:
>
> mmd_lookup(MMD_ADD, PerlString, PyString)


What if, as a fallback mechanism, the foreign
object were cast into a simpler type? The PyString
could just have a marker on it that says it should
be downcast into a native string (or ParrotString) in
cross language situations. You could do the same for
all the basic types.

That way, if you evaluate $perlString + $pyString
in perl, you get perlish behavior, and if you
evaluate perlString+pyString in python, you get
pythonic behavior.

The only requirement is that you have an adapter
to make the language-specific types adhere to the
generic interface. Zope and Twisted do this kind
of thing all the time:

http://twisted.sourceforge.net/TwistedDocs-1.2.0/howto/components.html


- Michal
http://withoutane.com/

Dan Sugalski

unread,
Oct 11, 2004, 11:24:58 AM10/11/04
to Michal, Sam Ruby, perl6-i...@perl.org
At 4:23 PM -0400 10/9/04, Michal wrote:
>On Sat, 9 Oct 2004, Sam Ruby wrote:
>
>> Inheritance can reduce the combinatorial problem, but it can introduce a
>> precendence question. The most interesting case still seems to be:
>>
>> mmd_lookup(MMD_ADD, PerlString, PyString)
>
>
>What if, as a fallback mechanism, the foreign
>object were cast into a simpler type? The PyString
>could just have a marker on it that says it should
>be downcast into a native string (or ParrotString) in
>cross language situations. You could do the same for
>all the basic types.
>
>That way, if you evaluate $perlString + $pyString
>in perl, you get perlish behavior, and if you
>evaluate perlString+pyString in python, you get
>pythonic behavior.

This, I think, is something I'd prefer to not do. An operation should
behave identically regardless of the language that's performing the
operation. The alternative, a separate and distinct op, is probably a
better option here, though that's got issues as well.

Then there's the question of what things that aren't base types
should do. Should PyString+RubyObjectWhichIsAString do concatenation
or addition? And how exactly would you tell if the object really is a
string or not? (And what about objects that are multiple things
simultaneously -- that is, should behave as a string and a number)

I think we may want to think about multiple inheritance for PMC
classes and add in some basic attribute types to inherit from. (Like
Stringish, Intish, FloatIsh, BigNumish, Booleanish, to denote things
that should be considered strings or whatever, rather than just
having a string representation)

Sam Ruby

unread,
Oct 11, 2004, 2:03:43 PM10/11/04
to Dan Sugalski, Michal, perl6-i...@perl.org
Dan Sugalski wrote:

> At 4:23 PM -0400 10/9/04, Michal wrote:
>
>> On Sat, 9 Oct 2004, Sam Ruby wrote:
>>
>>> Inheritance can reduce the combinatorial problem, but it can
>>> introduce a
>>> precendence question. The most interesting case still seems to be:
>>>
>>> mmd_lookup(MMD_ADD, PerlString, PyString)
>>
>> What if, as a fallback mechanism, the foreign
>> object were cast into a simpler type? The PyString
>> could just have a marker on it that says it should
>> be downcast into a native string (or ParrotString) in
>> cross language situations. You could do the same for
>> all the basic types.
>>
>> That way, if you evaluate $perlString + $pyString
>> in perl, you get perlish behavior, and if you
>> evaluate perlString+pyString in python, you get
>> pythonic behavior.
>
> This, I think, is something I'd prefer to not do. An operation should
> behave identically regardless of the language that's performing the
> operation. The alternative, a separate and distinct op, is probably a
> better option here, though that's got issues as well.

Separate op won't work for Python. Consider:

def f(x,y): return x+y
print f(5,6) # 11
print f("a","b") # ab

Also:

def f(x,y): return x.__add__(y)
print f(5,6) # 11
print f("a","b") # ab

In fact, it gets stranger. Methods can be detached from their classes
and accessed as functions:

print int.__add__(3,4)
z="a".__add__
print z("b")

> Then there's the question of what things that aren't base types should
> do. Should PyString+RubyObjectWhichIsAString do concatenation or
> addition? And how exactly would you tell if the object really is a
> string or not? (And what about objects that are multiple things
> simultaneously -- that is, should behave as a string and a number)

We are going to find a lot of surprises. In Perl 5, hashes can only be
indexed by strings. In Python, anything that contains a __hash__ method
may be used as an index. At the moment Parrot's PerlString doesn't have
a hash method.

Here's a script that will run in both Python and Perl. It simply will
return different results.

print "1" + "2" ,"\n",;
print "45%s8" % "7" ,"\n",;
print 45 / 7 ,"\n",;
print ['a','b','c'] ,"\n",;
print ['a'] + ['b'] ,"\n",;
print 9 + None ,"\n",;

> I think we may want to think about multiple inheritance for PMC classes
> and add in some basic attribute types to inherit from. (Like Stringish,
> Intish, FloatIsh, BigNumish, Booleanish, to denote things that should be
> considered strings or whatever, rather than just having a string
> representation)

A first approximation might be to define a ParrotString with minimal
methods, and allow each language to subclass it and add additional behavior.

But actually, my recommendation is that we don't go that far yet.
Yesterday, I coded up a number of python pmcs:

pyboolean.pmc pyfloat.pmc pylist.pmc pyobject.pmc pytuple.pmc
pydict.pmc pyint.pmc pynone.pmc pystring.pmc

Actually, when I say "coded", all I did was copy some existing pmcs and
made minimal changes (global renames, removed the checks for
PARROT_PYTHON_MODE by making such paths the defaults, added some
get_repr implementations, and some minor tweaks like making integers no
longer promote to floats).

While I got a version of Pirate to work with these new classes, the
result feels a bit like cheating. What I would like to do is to evolve
this into a complete Python object model, focusing first on being a
faithful implementation of Python, initially at the expense of
interlanguage interop.

Once enough of that is in place, we can start to explore what it would
take to make interop more of a reality. And how to structure the code
so that things like Python and Perl support could be a shared library
that is only loaded when the application requires it.

- Sam Ruby

Aaron Sherman

unread,
Oct 11, 2004, 3:19:20 PM10/11/04
to Sam Ruby, Perl6 Internals List
On Mon, 2004-10-11 at 14:03, Sam Ruby wrote:

> Here's a script that will run in both Python and Perl. It simply will
> return different results.
>
> print "1" + "2" ,"\n",;
> print "45%s8" % "7" ,"\n",;
> print 45 / 7 ,"\n",;
> print ['a','b','c'] ,"\n",;
> print ['a'] + ['b'] ,"\n",;
> print 9 + None ,"\n",;

That last line fails under my python, but ignoring that:

example 1: I don't get the complexity here. Python's add is a special
case function that doesn't have much to do with the Parrot addition
operators except in that, in some cases, it calls them (and in other
cases, it calls ops like "join"). We have to distinguish the job of the
compiler writer from the job of the Parrot interpreter writer here, and
I don't think this is Parrot's concern.

example 2: This is just abusing the difference between "%" in Python and
in Perl. No shock there. Don't confuse syntax with semantics.

example 3: Python does integer math on integers, Perl does
floating-point. Again, not an issue.

I'll stop there. I think it's clear that there's two desires here. One I
think is reasonable, and one is (IMHO) not.

To want to be able to pass a PyString to a Perl function is fine.

To want to be able to pass a PyString to a Perl function and have it
mutate any code that uses it into Python semantics just doesn't make
sense to me.

The caller's semantics will drive how such things behave, and those
semantics will be imposed by the compiler in many cases, not Parrot.

If, for example, the caller turns:

a + b

into:

[...]
join result, a, b
[...]

then that's what happens, and if "a" happens to be a PerlString, too bad
that it doesn't think that "+" can mean concatenation.

If your compiler turns everything into an object, then the surprises
that develop from using variables that are alien to your object tree are
not, in fact, surprising.

Your concerns about hash behavior make more sense to me, and I do think
that hashing should be a core property of all PMCs. For those who don't
agree, go take a look at the mess that is C++-STL, and try this:

std::hash_map<std::string> myhash;

I love the STL in concept, but in practice it's full of gotchas like
this because the object tree is too disjoint because the foundation was
never set in such a way that the later pieces fit.

--
781-324-3772
a...@ajs.com
http://www.ajs.com/~ajs

Dan Sugalski

unread,
Oct 11, 2004, 3:26:35 PM10/11/04
to Sam Ruby, Michal, perl6-i...@perl.org

Oh, sure it'd work, if you had an ADD_OR_CONCATENATE op with an
appropriate MMD table. :)

Still, the downside is that you'd like:

a + b

to do the same thing no matter what language emitted the code.
(Though arguably perl's + is the same as, say, a lisp +, but
different from a VB/Python +, they just happen to have the same sigil)

>Also:
>
> def f(x,y): return x.__add__(y)
> print f(5,6) # 11
> print f("a","b") # ab
>
>In fact, it gets stranger. Methods can be detached from their
>classes and accessed as functions:
>
> print int.__add__(3,4)
> z="a".__add__
> print z("b")

Ah, I get stranger things than that with my breakfast cereal. (Which
is one of the reasons I tend to have a bagel for breakfast, but
that's neither here nor there) That's not actually a big problem,
though it's something we'd *definitely* want to wedge into the code
generator. (One of those places where dealing with the AST is a lot
nicer than dealing with the bytecode)

With AST access, the z="a".__add__ would end up with code to check
for an __add__ method and if found create an anonymous method closure
PMC for z. Invoking z invokes the closure, sets up the object slot,
and makes the method call as it ought. (Whether it should go search
the hierarchy when bound or invoked is a separate thing)

>>Then there's the question of what things that aren't base types
>>should do. Should PyString+RubyObjectWhichIsAString do
>>concatenation or addition? And how exactly would you tell if the
>>object really is a string or not? (And what about objects that are
>>multiple things simultaneously -- that is, should behave as a
>>string and a number)
>
>We are going to find a lot of surprises. In Perl 5, hashes can only
>be indexed by strings. In Python, anything that contains a __hash__
>method may be used as an index. At the moment Parrot's PerlString
>doesn't have a hash method.

Yeah. Perl 6 is opening that one up, and it's one of the reasons that
each element in a key structure is tagged with both its actual and
intended type. (Though that's not as yet exposed)

>Here's a script that will run in both Python and Perl. It simply
>will return different results.
>
> print "1" + "2" ,"\n",;
> print "45%s8" % "7" ,"\n",;
> print 45 / 7 ,"\n",;
> print ['a','b','c'] ,"\n",;
> print ['a'] + ['b'] ,"\n",;
> print 9 + None ,"\n",;

Yep, though in part because "1" gets turned into a PerlString by the
perl compiler and a PythonString by the python compiler, with
different semantics.

This is a barrel 'o worms, no doubt. Luckily I don't have to care, as
such, since it's a language issue. (Though I do have to care about
providing the mechanisms to make it not only possible but actually
easy to do, but that's not too tough. The tough part's making it so
that language implementers find it easier to do it in the way that
makes interop easy than do it the hard way :)

>But actually, my recommendation is that we don't go that far yet.
>Yesterday, I coded up a number of python pmcs:
>
> pyboolean.pmc pyfloat.pmc pylist.pmc pyobject.pmc pytuple.pmc
> pydict.pmc pyint.pmc pynone.pmc pystring.pmc
>
>Actually, when I say "coded", all I did was copy some existing pmcs
>and made minimal changes (global renames, removed the checks for
>PARROT_PYTHON_MODE by making such paths the defaults, added some
>get_repr implementations, and some minor tweaks like making integers
>no longer promote to floats).
>
>While I got a version of Pirate to work with these new classes, the
>result feels a bit like cheating. What I would like to do is to
>evolve this into a complete Python object model, focusing first on
>being a faithful implementation of Python, initially at the expense
>of interlanguage interop.

Seems like the right thing to do to me.

Sam Ruby

unread,
Oct 11, 2004, 4:11:34 PM10/11/04
to Dan Sugalski, perl6-i...@perl.org
Dan Sugalski wrote:

>> Separate op won't work for Python. Consider:
>>
>> def f(x,y): return x+y
>> print f(5,6) # 11
>> print f("a","b") # ab
>
> Oh, sure it'd work, if you had an ADD_OR_CONCATENATE op with an
> appropriate MMD table. :)

Conceptually, "+" is not an op at all in Python, it is syntatic sugar
for a method call. Consider:

def f(x,y): return x+y

class g:
def __init__(self,value): self.value=value
def __add__(self,value): return str(self.value)+str(value)

print g(1)+1

CPython returns "11".

> Still, the downside is that you'd like:
>
> a + b
>
> to do the same thing no matter what language emitted the code. (Though
> arguably perl's + is the same as, say, a lisp +, but different from a
> VB/Python +, they just happen to have the same sigil)

I don't think that a substrate like Parrot should "take sides" on issues
such as these. add_p_p_p is a function that takes as input two PMCs and
produces another PMC. The data types of the output can't be reliably
determined by the input. The underlying function performed is entirely
dependent on the PMCs in question.

I would suggest that the responsibility of Parrot begins and ends with
doing the appropriate MMD.

>> Also:
>>
>> def f(x,y): return x.__add__(y)
>> print f(5,6) # 11
>> print f("a","b") # ab
>>
>> In fact, it gets stranger. Methods can be detached from their classes
>> and accessed as functions:
>>
>> print int.__add__(3,4)
>> z="a".__add__
>> print z("b")
>
> Ah, I get stranger things than that with my breakfast cereal. (Which is
> one of the reasons I tend to have a bagel for breakfast, but that's
> neither here nor there) That's not actually a big problem, though it's
> something we'd *definitely* want to wedge into the code generator. (One
> of those places where dealing with the AST is a lot nicer than dealing
> with the bytecode)
>
> With AST access, the z="a".__add__ would end up with code to check for
> an __add__ method and if found create an anonymous method closure PMC
> for z. Invoking z invokes the closure, sets up the object slot, and
> makes the method call as it ought. (Whether it should go search the
> hierarchy when bound or invoked is a separate thing)

Alternately, __add__ would simply be a attribute of the string PMC, with
a value being the same closure which you describe. Ideally, the
creation of this closure could be deferred until the attribute was
actually retrieved.

Similarly, the add(PMC, PMC) function in PyObject should look for, and
attempt to invoke, any such __add__ methods. That way, classes derived
from PyObject could override "+" by providing an appropriate
implementation of an __add__ method.

>> But actually, my recommendation is that we don't go that far yet.
>> Yesterday, I coded up a number of python pmcs:
>>
>> pyboolean.pmc pyfloat.pmc pylist.pmc pyobject.pmc pytuple.pmc
>> pydict.pmc pyint.pmc pynone.pmc pystring.pmc
>>
>> Actually, when I say "coded", all I did was copy some existing pmcs
>> and made minimal changes (global renames, removed the checks for
>> PARROT_PYTHON_MODE by making such paths the defaults, added some
>> get_repr implementations, and some minor tweaks like making integers
>> no longer promote to floats).
>>
>> While I got a version of Pirate to work with these new classes, the
>> result feels a bit like cheating. What I would like to do is to
>> evolve this into a complete Python object model, focusing first on
>> being a faithful implementation of Python, initially at the expense of
>> interlanguage interop.
>
> Seems like the right thing to do to me.

As I am doing this work, should I put this on my server some place?
Check it in some place? Send it as patches?

- Sam Ruby

Leopold Toetsch

unread,
Oct 12, 2004, 4:07:43 AM10/12/04
to Dan Sugalski, perl6-i...@perl.org
Dan Sugalski wrote:
> At 2:03 PM -0400 10/11/04, Sam Ruby wrote:
>> Separate op won't work for Python. Consider:
>>
>> def f(x,y): return x+y
>> print f(5,6) # 11
>> print f("a","b") # ab
>
> Oh, sure it'd work, if you had an ADD_OR_CONCATENATE op with an
> appropriate MMD table. :)

Yes, *but" we have to do that for any string PMC, not only for a Python
string. *If* we are executing a Python module, the MMD("add",
any_string, any_string) operation is concat.

> Still, the downside is that you'd like:
>
> a + b
>
> to do the same thing no matter what language emitted the code. (Though
> arguably perl's + is the same as, say, a lisp +, but different from a
> VB/Python +, they just happen to have the same sigil)

No. I don't think that the "no matter what language" holds. Just the
opposite. In a Perl module MMD("add", string, string) is C<+>, in a
Python module its C<concat>. But these different functions occupy the
same MMD slot.

>> z="a".__add__
>> print z("b")

> ... That's not actually a big problem, though it's

> something we'd *definitely* want to wedge into the code generator. (One
> of those places where dealing with the AST is a lot nicer than dealing
> with the bytecode)

No chance AFAIK to fix that at code generation level:

def f(a,b): return a + b

There is absolutely no indication that, when strings are passed, it
should do concatenation.

So again: if the code origin is Python, we have to do concat at runtime,
*if* both argments are strings.

>> Here's a script that will run in both Python and Perl. It simply will
>> return different results.
>>
>> print "1" + "2" ,"\n",;
>> print "45%s8" % "7" ,"\n",;

> Yep, though in part because "1" gets turned into a PerlString by the

> perl compiler and a PythonString by the python compiler, with different
> semantics.

The question is, if we can afford do have different semantics.

> This is a barrel 'o worms, no doubt. Luckily I don't have to care, as
> such, since it's a language issue. (Though I do have to care about
> providing the mechanisms to make it not only possible but actually easy
> to do, but that's not too tough.

Again: def f(a,b): return a+b

> ... The tough part's making it so that

> language implementers find it easier to do it in the way that makes
> interop easy than do it the hard way :)

It's of course a language issue. *But* if we want to run Python, we have
basically two choices:
1) force Python coders to write "a".concat("b") with a language change
2) implement the MMD add function for strings, so that it acts
differently depending on the code origin.
The latter minimizes the difference of String/PerlString/PyString to
probably nothing.

2) could look like:
- we have *one* string PMC type
- if we start running Python code, we replace the relevant vtable slots
of add, modulo, ... with pythonic operations.
- and we push a restore handler onto the context, that undos these
change, when we come back to run Perl code.

>> [ python pmcs ]

>> ... What I would like to do is to

>> evolve this into a complete Python object model, focusing first on
>> being a faithful implementation of Python, initially at the expense of
>> interlanguage interop.

> Seems like the right thing to do to me.

Yes, but the can of worms remains and needs a solution.

leo

Sam Ruby

unread,
Oct 12, 2004, 8:29:13 AM10/12/04
to Leopold Toetsch, Dan Sugalski, perl6-i...@perl.org
Leopold Toetsch wrote:
> Dan Sugalski wrote:
>
>> At 2:03 PM -0400 10/11/04, Sam Ruby wrote:
>>
>>> Separate op won't work for Python. Consider:
>>>
>>> def f(x,y): return x+y
>>> print f(5,6) # 11
>>> print f("a","b") # ab
>>
>> Oh, sure it'd work, if you had an ADD_OR_CONCATENATE op with an
>> appropriate MMD table. :)
>
> Yes, *but" we have to do that for any string PMC, not only for a Python
> string. *If* we are executing a Python module, the MMD("add",
> any_string, any_string) operation is concat.

In Python terms, __add__ is but one of several methods that strings
have. Other common ones include index, join, lower, replace, and split.

In Ruby, "+" for String is is also a concatenation, and common methods
include each, length, index, join, downcase, replace, and split. Note
that the definition of index (search for a given substring) handles the
case of "not found" differently than the similarly named Python function.

>> Still, the downside is that you'd like:
>>
>> a + b
>>
>> to do the same thing no matter what language emitted the code. (Though
>> arguably perl's + is the same as, say, a lisp +, but different from a
>> VB/Python +, they just happen to have the same sigil)
>
> No. I don't think that the "no matter what language" holds. Just the
> opposite. In a Perl module MMD("add", string, string) is C<+>, in a
> Python module its C<concat>. But these different functions occupy the
> same MMD slot.
>
>>> z="a".__add__
>>> print z("b")
>
>> ... That's not actually a big problem, though it's something we'd
>> *definitely* want to wedge into the code generator. (One of those
>> places where dealing with the AST is a lot nicer than dealing with the
>> bytecode)
>
> No chance AFAIK to fix that at code generation level:
>
> def f(a,b): return a + b
>
> There is absolutely no indication that, when strings are passed, it
> should do concatenation.
>
> So again: if the code origin is Python, we have to do concat at runtime,
> *if* both argments are strings.

Lets make this more interessting:

def f(x): return x("d")
def g(x): return f(x.index)
print g("abcdefg")

The desired result is "3".

Do we want to go so far as "if the code origin in Python, then
MMD("get_attr", string, "index") returns the Python str.index function
bound to this instance?

>>> Here's a script that will run in both Python and Perl. It simply
>>> will return different results.
>>>
>>> print "1" + "2" ,"\n",;
>>> print "45%s8" % "7" ,"\n",;
>
>
>> Yep, though in part because "1" gets turned into a PerlString by the
>> perl compiler and a PythonString by the python compiler, with
>> different semantics.
>
> The question is, if we can afford do have different semantics.

I don't see how these problems can be solved in general at either code
generation or runtime.

>> This is a barrel 'o worms, no doubt. Luckily I don't have to care, as
>> such, since it's a language issue. (Though I do have to care about
>> providing the mechanisms to make it not only possible but actually
>> easy to do, but that's not too tough.
>
> Again: def f(a,b): return a+b
>
>> ... The tough part's making it so that language implementers find it
>> easier to do it in the way that makes interop easy than do it the hard
>> way :)
>
> It's of course a language issue. *But* if we want to run Python, we have
> basically two choices:
> 1) force Python coders to write "a".concat("b") with a language change
> 2) implement the MMD add function for strings, so that it acts
> differently depending on the code origin.
> The latter minimizes the difference of String/PerlString/PyString to
> probably nothing.

Or we require a Python programmer to use the "str" function on any
potentially foreigh object received as a parameter if they wish to
depend on Python string semantics.

- Sam Ruby

Leopold Toetsch

unread,
Oct 12, 2004, 9:31:50 AM10/12/04
to Sam Ruby, perl6-i...@perl.org
Sam Ruby <ru...@intertwingly.net> wrote:
> Leopold Toetsch wrote:

> In Python terms, __add__ is but one of several methods that strings
> have. Other common ones include index, join, lower, replace, and split.

I just used __add__ as an example. Of course all (differing) vtables and
methods would need the adjustment depending on the code origin.

> Do we want to go so far as "if the code origin in Python, then
> MMD("get_attr", string, "index") returns the Python str.index function
> bound to this instance?

Baically yes, albeit C<get_attr> isn't a MMD function. Its a plain
vtable function C<get_attr_str>.

>> It's of course a language issue. *But* if we want to run Python, we have
>> basically two choices:
>> 1) force Python coders to write "a".concat("b") with a language change
>> 2) implement the MMD add function for strings, so that it acts
>> differently depending on the code origin.
>> The latter minimizes the difference of String/PerlString/PyString to
>> probably nothing.

> Or we require a Python programmer to use the "str" function on any
> potentially foreigh object received as a parameter if they wish to
> depend on Python string semantics.

That's similar to or a generalization of 1). It IMHO implies that Python
on Parrot willl not be used much.

> - Sam Ruby

leo

Steve Fink

unread,
Oct 12, 2004, 11:59:14 AM10/12/04
to Leopold Toetsch, Sam Ruby, perl6-i...@perl.org
Perl5 has the notion of contexts, where an expression may behave very
differently in string, boolean, or list context. Perl6 intends to expand
that notion. What if the whole context notion were moved down into
Parrot? Every function call and every MMD dispatch could have an
additional context parameter, and 'add' could then behave very
differently in Pythonic context as opposed to Perl Boolean context?

I guess I'm not actually saying anything here, other than suggesting the
possibility of unifying this problem with Perl's context problem.

Thomas Sandlass

unread,
Oct 14, 2004, 5:26:53 AM10/14/04
to
st...@fink.com (Steve Fink) wrote in message news:<20041012155...@kevin.fink.com>...

> Perl5 has the notion of contexts, where an expression may behave very
> differently in string, boolean, or list context. Perl6 intends to expand
> that notion.

I always thought that the context is a parser notion. This means the
perl6 compiler generates code for '$a + $b' such that the numeric
values of $a and $b are stored in e.g. in N1 and N2 and uses the
parrot instruction 'add N0, N1, N2' which doesn't go through MMD.


> What if the whole context notion were moved down into
> Parrot? Every function call and every MMD dispatch could have an
> additional context parameter, and 'add' could then behave very
> differently in Pythonic context as opposed to Perl Boolean context?

I think context is provided by the instructions used in the code.
Parrot has the 4 basic contexts integer, numeric, string and
magic/object/mmd. Boolean context is the interpretation of integer
values by test instructions. And throwing away return values or so
can be construed as void context.

Python will use only object context, while Perl 6 numerifies and
stringifies as needed. More interesting is IMHO the question how
one tells the Perl 6 compiler to emit MMD code where it usually
wouldn't.


MfG, TSa.

0 new messages