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

FYI compiling PIR function calls

0 views
Skip to first unread message

Leopold Toetsch

unread,
Sep 26, 2006, 3:41:18 PM9/26/06
to perl6-i...@perl.org
There seems to be the impression that generating PIR calls from a compiler is
hard because it may look like:

$S0 = obj.'_meth'(arg1, arg2)

but this also works:

.pcc_begin
.arg "hello"
.arg "\n"
.invocant obj
.meth_call "_meth"
.result $S0
.pcc_end

There's a similar construct for return values.
leo

Allison Randal

unread,
Sep 27, 2006, 3:12:29 AM9/27/06
to Leopold Toetsch, perl6-i...@perl.org

The basic problem is inconsistency. For hand-written code the current
PIR method call syntactic sugar is mildly annoying. (It'd be nice to
safely get rid of the quotes around the method name.) For generated code
it's a completely different syntax tree node. Opcode syntax like so:

opcode $S0, obj, arg1, arg2

can be represented with a simple parent node with a sequence of child nodes.

The syntax tree for methods (whether you use the syntactic sugar or the
long form) is more like a parent node (a "method"), with one invocant
child and two composite children for the argument list and return list,
respectively. To generate the PIR, you need unroll the composite
children in a way that's contextually dependent on other nodes further
up the tree.

And when some common language constructs are opcodes and some are method
calls, the burden of deciding which kind of syntax a particular
construct should use falls to the compiler writer. There are various
ways to implement it: a lookup table, a chunk of hard-coded PIR, etc.
But they all boil down to added complexity.

This isn't to say that method calls are "bad", but they are more complex
to work with. You want more features to be implemented only as methods
and to eliminate the opcodes. But there is real value in keeping the
opcode syntax for the common cases.

Allison

Leopold Toetsch

unread,
Sep 27, 2006, 5:38:10 AM9/27/06
to perl6-i...@perl.org
Am Mittwoch, 27. September 2006 09:12 schrieb Allison Randal:

> The basic problem is inconsistency. For hand-written code the current
> PIR method call syntactic sugar is mildly annoying. (It'd be nice to
> safely get rid of the quotes around the method name.)

Not easily:

obj.'foo'() # a methodname constant
.local string bar
bar = get_some_meth() # or bar = 'get_some_meth'()
obj.bar() # a method variable

But:

obj.foo() # still a methodname constant
# unless there's a variable 'foo'

To be on the safe side, method (and function) names *should* be quoted. I
don't think that this is inconsistent.

> And when some common language constructs are opcodes and some are method
> calls, the burden of deciding which kind of syntax a particular
> construct should use falls to the compiler writer. There are various
> ways to implement it: a lookup table, a chunk of hard-coded PIR, etc.
> But they all boil down to added complexity.

Well, when I write x86 or ppc JIT code, the burden of deciding, which syntax
to use falls on the compiler write that is me. While we could provide an
introspection API to available opcodes (and args) it still doesn't help much.
The compiler (writer) has to know, what a particular opcode is doing.

When I write code which calls some library function, I've to lookup the docu
and check the function name and the argument it takes. And I've to decide, if
I have an opcode available and use it, or if I've to call a library function.

This is just the usual job when creating a compiler. Introspection would have
little benefit IMHO:

interp = getinterp
info = interp.get_op_info() # hypothetical
$I0 = exists info['gcd'] # do we have a 'gcd' opcode

cl = getclass 'Integer'
$I0 = can cl, 'gcd'

While a compiler could use introspection or tables or whatever, these still
wouldn't help to figure out the semantics of a particular operation.

> Allison

leo

Jonathan Scott Duff

unread,
Sep 27, 2006, 10:02:53 AM9/27/06
to Leopold Toetsch, perl6-i...@perl.org
On Wed, Sep 27, 2006 at 11:38:10AM +0200, Leopold Toetsch wrote:
> Am Mittwoch, 27. September 2006 09:12 schrieb Allison Randal:
>
> > The basic problem is inconsistency. For hand-written code the current
> > PIR method call syntactic sugar is mildly annoying. (It'd be nice to
> > safely get rid of the quotes around the method name.)
>
> Not easily:
>
> obj.'foo'() # a methodname constant
> .local string bar
> bar = get_some_meth() # or bar = 'get_some_meth'()
> obj.bar() # a method variable
>
> But:
>
> obj.foo() # still a methodname constant
> # unless there's a variable 'foo'
>
> To be on the safe side, method (and function) names *should* be quoted. I
> don't think that this is inconsistent.

Is there a reason that you would want to conflate method names and
variables used as a method name? If not, why not change the syntax
slightly so that method names in a variable are uniquely identified?
Here's a suggestion:

obj.foo() # a methodname constant


.local string bar
bar = get_some_meth()

obj.$bar() # a method variable

The same could be used for ordinary subroutines:

.local string mysub
mysub = "foo"
$mysub() # calls the foo subroutine

-Scott
--
Jonathan Scott Duff <du...@pobox.com>

Allison Randal

unread,
Sep 28, 2006, 2:25:16 PM9/28/06
to du...@pobox.com, Leopold Toetsch, perl6-i...@perl.org
Jonathan Scott Duff wrote:
>>
>> To be on the safe side, method (and function) names *should* be quoted. I
>> don't think that this is inconsistent.
>
> Is there a reason that you would want to conflate method names and
> variables used as a method name? If not, why not change the syntax
> slightly so that method names in a variable are uniquely identified?
> Here's a suggestion:
>
> obj.foo() # a methodname constant
> .local string bar
> bar = get_some_meth()
> obj.$bar() # a method variable
>

Exactly, change the most common case (of a method call by bare name) to
be the unmarked case, and use some additional marking on the less common
case of calling a method by a string name or method object. I wouldn't
use '$' to mark the string lookup because it's too confusing with the
temporary register variables ($S0, etc). But some other syntactic sugar
would work. This is clumsy, but then, it's also rare.

obj.{bar}() # a string method name
obj.{$S1}()

Allison

Chromatic

unread,
Sep 28, 2006, 2:59:52 PM9/28/06
to perl6-i...@perl.org, Allison Randal, du...@pobox.com, Leopold Toetsch
On Thursday 28 September 2006 11:25, Allison Randal wrote:

> Exactly, change the most common case (of a method call by bare name) to
> be the unmarked case, and use some additional marking on the less common
> case of calling a method by a string name or method object. I wouldn't
> use '$' to mark the string lookup because it's too confusing with the
> temporary register variables ($S0, etc). But some other syntactic sugar
> would work. This is clumsy, but then, it's also rare.
>
> obj.{bar}() # a string method name
> obj.{$S1}()

That's not bad; it reminds me a bit of Perl and Tcl.

To push a little more the other direction, is it possible for the compiler to
detect symbol and method name conflicts? It's only the collision that makes
a case ambiguous, right?

-- c

Patrick R. Michaud

unread,
Sep 28, 2006, 3:42:06 PM9/28/06
to chromatic, perl6-i...@perl.org, Allison Randal, du...@pobox.com, Leopold Toetsch
On Thu, Sep 28, 2006 at 11:59:52AM -0700, chromatic wrote:
> On Thursday 28 September 2006 11:25, Allison Randal wrote:
> > obj.{bar}() # a string method name
> > obj.{$S1}()

I'm not sure what's meant by "a string method name" above, but
I'd look at it as:

.local string abc

obj.'abc'() # call 'abc' method of obj
obj.abc() # always the same as above
obj.{abc}() # call method indicated by abc symbol
obj.{S0}() # call method indicated by S0
obj.$S0() # call method indicated by $S0

Having obj.abc() always mean obj.'abc'() seems to me like it's
most in line with what PIR-authors expect.

As noted in the last instance, I don't know that we need a
separate obj.{$S0}() case since the dollar sign is sufficient
to distinguish exactly what was meant. But there's also an
argument in favor of the consistency of {...} always meaning
"evaluate this" as opposed to "treat this as literal" given
by the bareword and 'abc' forms.

> To push a little more the other direction, is it possible for the
> compiler to detect symbol and method name conflicts?
> It's only the collision that makes a case ambiguous, right?

I don't think that the compiler always knows at compile time
what method names are available for any given object, so detecting
"collisions" could be problematic.

However, it could certainly detect when a bareword symbol has
been used as a method name and warn about it, requiring the use of an
explicit obj.{symbol}() or obj.'symbol'() form to disambiguate it.

Pm

Chromatic

unread,
Sep 28, 2006, 3:47:10 PM9/28/06
to Patrick R. Michaud, perl6-i...@perl.org, Allison Randal, du...@pobox.com, Leopold Toetsch
On Thursday 28 September 2006 12:42, Patrick R. Michaud wrote:

> > To push a little more the other direction, is it possible for the
> > compiler to detect symbol and method name conflicts?  
> > It's only the collision that makes a case ambiguous, right?

> I don't think that the compiler always knows at compile time
> what method names are available for any given object, so detecting
> "collisions" could be problematic.  

Oh no, of course not.

> However, it could certainly detect when a bareword symbol has
> been used as a method name and warn about it, requiring the use of an
> explicit obj.{symbol}() or obj.'symbol'() form to disambiguate it.

Yes, that is what I meant. If there's a symbol in the current compilation
unit with the same name as a bareword method call, require disambiguation.
Otherwise, assume it's a bareword method call.

-- c

Leopold Toetsch

unread,
Sep 28, 2006, 4:23:51 PM9/28/06
to perl6-i...@perl.org
Am Donnerstag, 28. September 2006 21:42 schrieb Patrick R. Michaud:

I'm just quoting the relevant pieces here and add some comments below:

>     obj.'abc'()              # call 'abc' method of obj
>     obj.abc()                # always the same as above
>     obj.{abc}()              # call method indicated by abc symbol

This makes a lot of sense, and there are simple rules for the syntax:

* use {symbol}, if the thing isa symbol
* use 'name', if the 'name' contains non-identifier characters
(of if unsure, of if you are a compiler ;-)
* else you also might use bare word syntax

That should be it to deal with all that:

obj.S0() # emit warning but call 'S0' method

Rational: if bare <abc> isa identifier here, then C<S0> too.

obj.$S0() # illegal

leo

Allison Randal

unread,
Sep 28, 2006, 4:35:48 PM9/28/06
to Patrick R. Michaud, perl6-i...@perl.org
Patrick R. Michaud wrote:
> On Thu, Sep 28, 2006 at 11:59:52AM -0700, chromatic wrote:
>> On Thursday 28 September 2006 11:25, Allison Randal wrote:
>>> obj.{bar}() # a string method name
>>> obj.{$S1}()
>
> I'm not sure what's meant by "a string method name" above, but
> I'd look at it as:


You got it, I meant "a method name stored in a string variable/register".


> .local string abc
>
> obj.'abc'() # call 'abc' method of obj
> obj.abc() # always the same as above
> obj.{abc}() # call method indicated by abc symbol
> obj.{S0}() # call method indicated by S0
> obj.$S0() # call method indicated by $S0
>
> Having obj.abc() always mean obj.'abc'() seems to me like it's
> most in line with what PIR-authors expect.

Yup.

Allison

Allison Randal

unread,
Sep 28, 2006, 4:53:50 PM9/28/06
to Leopold Toetsch, perl6-i...@perl.org
Leopold Toetsch wrote:
> Am Donnerstag, 28. September 2006 21:42 schrieb Patrick R. Michaud:
>
>> obj.'abc'() # call 'abc' method of obj
>> obj.abc() # always the same as above
>> obj.{abc}() # call method indicated by abc symbol
>
> This makes a lot of sense, and there are simple rules for the syntax:
>
> * use {symbol}, if the thing isa symbol
> * use 'name', if the 'name' contains non-identifier characters
> (of if unsure, of if you are a compiler ;-)
> * else you also might use bare word syntax

The latter two are the same rules as the rules for declaring
methods/subs, which makes for nice consistency.

> That should be it to deal with all that:
>
> obj.S0() # emit warning but call 'S0' method
>
> Rational: if bare <abc> isa identifier here, then C<S0> too.

I can see the value of this warning for the transition, but long-term we
really don't want the code to be littered with warnings for deprecated
features. It'd be pretty simple to write a script that combs the .pir
files in the repository for any instance of a method name that looks
like a register name.

> obj.$S0() # illegal

Is '$' a valid identifier character? If so, then it's legal, but just
treated as part of the string name of the method. If not (which seems
more likely), then it's illegal anyway, so no special case is needed.

Allison

Leopold Toetsch

unread,
Sep 28, 2006, 5:16:02 PM9/28/06
to perl6-i...@perl.org
Am Donnerstag, 28. September 2006 22:53 schrieb Allison Randal:
> Leopold Toetsch wrote:
> > Am Donnerstag, 28. September 2006 21:42 schrieb Patrick R. Michaud:
> >> obj.'abc'() # call 'abc' method of obj
> >> obj.abc() # always the same as above
> >> obj.{abc}() # call method indicated by abc symbol
> >
> > This makes a lot of sense, and there are simple rules for the syntax:
> >
> > * use {symbol}, if the thing isa symbol
> > * use 'name', if the 'name' contains non-identifier characters
> > (of if unsure, of if you are a compiler ;-)
> > * else you also might use bare word syntax
>
> The latter two are the same rules as the rules for declaring
> methods/subs, which makes for nice consistency.

Yep.

> > That should be it to deal with all that:
> >
> > obj.S0() # emit warning but call 'S0' method
> >
> > Rational: if bare <abc> isa identifier here, then C<S0> too.
>
> I can see the value of this warning for the transition, but long-term we
> really don't want the code to be littered with warnings for deprecated
> features. It'd be pretty simple to write a script that combs the .pir
> files in the repository for any instance of a method name that looks
> like a register name.

Indeed. I'm pretty sure that there isn't one test nor other .pir in the tree
using this syntax. The rules are clear enough: C<S0> is parsed as IDentifier
in that case, which means:

obj.S0() := obj.'S0'()

That is: no warning needed at all.

> > obj.$S0() # illegal
>
> Is '$' a valid identifier character?

No. Just a PIR temp variable signature, which makes the thingy a variable or
synmbol.

> If so, then it's legal, but just
> treated as part of the string name of the method. If not (which seems
> more likely), then it's illegal anyway, so no special case is needed.

I wanted just to stress the illegality of it as it was differently used in a
previous mail.

> Allison

leo

Matt Diephouse

unread,
Sep 28, 2006, 8:57:51 PM9/28/06
to Allison Randal, Patrick R. Michaud, perl6-i...@perl.org
Allison Randal <all...@perl.org> wrote:
>
> > .local string abc
> >
> > obj.'abc'() # call 'abc' method of obj
> > obj.abc() # always the same as above
> > obj.{abc}() # call method indicated by abc symbol
> > obj.{S0}() # call method indicated by S0
> > obj.$S0() # call method indicated by $S0
> >
> > Having obj.abc() always mean obj.'abc'() seems to me like it's
> > most in line with what PIR-authors expect.
>
> Yup.
>

Why not handle this like we handle subroutines? That is, why don't we
have a find_method opcode that returns a bound method? That simplifies
parsing for IMCC and makes PIR a little simpler.


obj.'abc'() # call 'abc' method of obj

obj.abc() # same as above
$P0 = find_method obj, abc # get bound method indicated by abc symbol
$P0() # actually call it

--
Matt Diephouse
http://matt.diephouse.com

Chromatic

unread,
Sep 28, 2006, 9:04:31 PM9/28/06
to perl6-i...@perl.org, ma...@diephouse.com
On Thursday 28 September 2006 17:57, Matt Diephouse wrote:

> Why not handle this like we handle subroutines? That is, why don't we
> have a find_method opcode that returns a bound method? That simplifies
> parsing for IMCC and makes PIR a little simpler.
>     obj.'abc'() # call 'abc' method of obj
>     obj.abc()  # same as above
>     $P0 = find_method obj, abc # get bound method indicated by abc symbol
>     $P0() # actually call it

Does that make emitting PASM a lot more difficult? All of a sudden, invoking
$P0 means that $P0 has to know that it stores something in the appropriate
invocant PMC register.

I suppose that means creating a CurriedInvocantMethodCall PMC that does all of
this magic in invoke(). That's not awful, but....

-- c

0 new messages