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

[perl #40968] [BUG] :multi doesn't seem to work right

4 views
Skip to first unread message

Patrick R . Michaud

unread,
Nov 22, 2006, 12:03:28 PM11/22/06
to bugs-bi...@rt.perl.org
# New Ticket Created by Patrick R. Michaud
# Please include the string: [perl #40968]
# in the subject line of all future correspondence about this issue.
# <URL: http://rt.perl.org/rt3/Ticket/Display.html?id=40968 >


I'm filing this as a bug report, but it could just be that
I don't understand how underscore arguments to :multi are
supposed to work.

I'm guessing that an underscore argument in :multi is
intended to indicate a "don't care" argument. Here's a
simple test program:

$ cat multi.pir
.sub main :main
.local pmc asub
asub = get_global 'main'

$P0 = new .String
$P0 = 'hello'
foo($P0, asub) # call :multi(_, Sub)

foo(1, asub) # call :multi(int, Sub)

.end


.sub foo :multi(_, Sub)
.param pmc x
.param pmc y
print x
print " "
say ":multi(_, Sub)"
.end


.sub foo :multi(int, Sub)
.param int x
.param pmc y
print x
print " "
say ":multi(int, Sub)"
.end

$ ./parrot multi.pir
hello :multi(_, Sub)
1 :multi(int, Sub)
$

Unfortunately, the "_" in :multi doesn't seem to match a
string register or string constant argument, instead producing
a "Null PMC access in invoke()" error:

$ cat multi.pir
.sub main :main
.local pmc asub
asub = get_global 'main'

$P0 = new .String
$P0 = 'hello'
foo($P0, asub) # call :multi(_, Sub)

foo(1, asub) # call :multi(int, Sub)

foo('world', asub) # should call :multi(_, Sub)
.end


.sub foo :multi(_, Sub)
.param pmc x
.param pmc y
print x
print " "
say ":multi(_, Sub)"
.end


.sub foo :multi(int, Sub)
.param int x
.param pmc y
print x
print " "
say ":multi(int, Sub)"
.end

$ ./parrot multi.pir
hello :multi(_, Sub)
1 :multi(int, Sub)
Null PMC access in invoke()
current instr.: 'main' pc 40 (multi.pir:11)
$

Is this a bug (I think it is), or does the underscore in
:multi mean something other than "any argument"?

If it's a bug, I can add a few tests to t/pmc/multisub.t .

Pm

Leopold Toetsch

unread,
Nov 22, 2006, 3:03:10 PM11/22/06
to perl6-i...@perl.org, Patrick R.Michaud, bugs-bi...@rt.perl.org
Am Mittwoch, 22. November 2006 18:03 schrieb Patrick R.Michaud:
> Is this a bug (I think it is), or does the underscore in
>
> :multi mean something other than "any argument"?

The meaning is 'any PMC' [1], and it of course can't be a bug as there are no
specs ;)

leo

[1] multi_type:

compilers/imcc/imcc.y:729 ff
...
r = mk_const(interp, str_dup("PMC"), 'S');

Leopold Toetsch

unread,
Nov 22, 2006, 5:20:58 PM11/22/06
to perl6-i...@perl.org, Patrick R.Michaud
Am Mittwoch, 22. November 2006 21:03 schrieb Leopold Toetsch:
> Am Mittwoch, 22. November 2006 18:03 schrieb Patrick R.Michaud:
> > Is this a bug (I think it is), or does the underscore in
> >
> > :multi mean something other than "any argument"?
>
> The meaning is 'any PMC' [1], and it of course can't be a bug as there are
> no specs ;)

Implementing '_' as 'any type' wouldn't be that hard. Except the mentioned
imcc.y snippets[1], it'll need some native any type and adjustments in

static UINTVAL
mmd_distance(Interp *interp, PMC *pmc, PMC *arg_tuple)

near

/*
* different native types are very different, except a PMC
* which matches any PMC
*/
if ((type_sig <= 0 && type_sig != enum_type_PMC) || type_call <= 0) {


[1]
compilers/imcc/imcc.y:729 ff

leo

Patrick R. Michaud

unread,
Nov 23, 2006, 11:48:06 AM11/23/06
to Leopold Toetsch, perl6-i...@perl.org, Patrick R. Michaud
On Wed, Nov 22, 2006 at 11:20:58PM +0100, Leopold Toetsch wrote:
> Am Mittwoch, 22. November 2006 21:03 schrieb Leopold Toetsch:
> > Am Mittwoch, 22. November 2006 18:03 schrieb Patrick R.Michaud:
> > > Is this a bug (I think it is), or does the underscore in
> > >
> > > :multi mean something other than "any argument"?
> >
> > The meaning is 'any PMC' [1], and it of course can't be a bug as there are
> > no specs ;)
>
> Implementing '_' as 'any type' wouldn't be that hard.

I'll take the position that implementing '_' as 'any type' is
the semantic we really want here. We already have a way to
say 'any PMC':

.sub foo :multi(pmc)

Here's a more detailed use case of why the current semantics
aren't useful. For subroutine calls, PAST-pm tries to pass
constants directly to subroutines (when it can) rather than
creating temporary PMCs and passing those. For example, a HLL
expression such as

3 .op. 4

gets turned into PIR like

$P0 = "infix:.op."(3, 4)

instead of

$P0 = new .Integer
assign $P0, 3
$P1 = new .Integer
assign $P0, 4
$P2 = "infix:.op."($P0, $P1)

The present case I've run into is the Perl 6 "smart match"
operator (infix:~~), where the operation to be performed depends
on the types of the arguments. For example, a pattern match
is defined as:

.sub "infix:~~" :multi(_, Sub)

For an expression such as $x ~~ /abc/, this works okay:

find_lex $P0, '$x' # get $x
find_name $P1, 'abc_sub' # get sub for /abc/
$P2 = "infix:~~"($P0, $P1) # call infix:~~

But for something like 'abc' ~~ /abc/, we end up with

find_name $P1, 'abc_sub' # get sub for /abc/
$P2 = "infix:~~"('abc', $P1) # call infix:~~

and it won't find the :multi(_, Sub) given above. So far I've
only found two workarounds -- one is to convert all arguments
to PMCs before calling any sub (this is what PAST-pm is
doing now), the other is to create additional
:multi(string|int|num, ...) subs that redispatch to the '_'
version:

.sub "infix:~~" :multi(int, Sub)


.param pmc x
.param pmc y

.return "infix:~~"(x, y)
.end

.sub "infix:~~" :multi(string, Sub)


.param pmc x
.param pmc y

.return "infix:~~"(x, y)
.end

# etc.

The first approach basically means we build a PMC for
every constant value, the second means that we end up
with three additional subs for every underscore in :multi.
And from a PIR-programmer perspective I don't see a lot
of downside to having '_' mean 'any value', but I can't
speak to the difficulty of implementing this in imcc.

Pm

Chromatic

unread,
Nov 23, 2006, 1:07:14 PM11/23/06
to perl6-i...@perl.org, Patrick R. Michaud
On Thursday 23 November 2006 08:48, Patrick R. Michaud wrote:

> Here's a more detailed use case of why the current semantics
> aren't useful.  For subroutine calls, PAST-pm tries to pass
> constants directly to subroutines (when it can) rather than
> creating temporary PMCs and passing those.  For example, a HLL
> expression such as
>
>     3 .op. 4
>
> gets turned into PIR like
>
>     $P0 = "infix:.op."(3, 4)
>
> instead of
>
>     $P0 = new .Integer
>     assign $P0, 3
>     $P1 = new .Integer
>     assign $P0, 4
>     $P2 = "infix:.op."($P0, $P1)

I read through the multi code last night (ow!) and don't see any reason not to
make the primitive types and their related PMCs equivalent in the distance
value function.

Of course, I severely distrust the distance value function after it finds the
distance for Pheme's best-matched 'atom?' variant at MMD_BAD_DISTANCE and
gets progressively worse for the others.

-- c

0 new messages