On Thu, 19 Dec 2002, Leopold Toetsch wrote:

> David Robins wrote:
> > On Wed, 18 Dec 2002, Leopold Toetsch wrote:
> >>    morph "dest" to be a "ret"?
> >>unimplemented, unused, but your examples seems to be a typical test case.
> > "dest" could be any type, so it's not reasonable to expect any type to be
> > able to morph to my chosen destination PMC type (unless default->morph can
> > be changed to do a standard new for the type).
> In pdd02_vtables.pod morph() is defined to do exactly this.

I was looking at the default.pmc code.  I'll read the doc.

Doc says that

 This method is primarily used when the interpreter has need of
 coercing a PMC to a particular type, and isn't meant as a general
 purpose casting tool. Compilers should only emit valid
 transformations.

which doesn't seem to indicate that morph is the Right Thing, at least
conceptually (since I want to destroy the old PMC and create a new one all
the time, so I don't want the PMC wasting time trying to convert itself into
the new type if I'm just going to clobber the value anyway).

> > Maybe the ops should instead be changed to be
> >
> >   PMC* binaryOp(PMC* rhs) and
> >   PMC* unaryOp(void)
> >
> > after all, most of the time _someone_ has to create a destination PMC, and
> > except for the reuse angle (and 'new' is probably quite fast), the PMC
> > handling the op is in the best place to do it.
>
> The question is, how often may a PMC be reused, and how often has it to
> be a new one. And for which vtable to you call above Op?.

Well, if the HL (or even IMCC) is "$a = $b + $c", how should that be
translated?  The existing type of $a sure shouldn't influence the result.
Supposing $b is a PerlInt, and $a maps to P0, $b to P1, and $c to P2, then:

  add P0,P1,P2

calls PerlInt's add op, which in most cases wants the result to be a
PerlInt, except in some (when P2 is a float) it should be a PerlFloat, say:

  PMC* add(PMC* value) {
    if(value is not a float) {
      PMC* ret = SELF.clone();
      ret->cache.int_val += value->vtable->get_integer(INTERP);
      return ret;
    }
    /* since addition commutes, flip it around so we get a float back */
    return value->vtable->add(INTERP,SELF);
  }

"value is not a float" is intentionally nebulous, there's no way to check if
a value is a float, except maybe by comparing the get_number/get_integer
returns, but that's slow and float roundoff will get you anyway.  For
PerlInt it might suffice to check that 'value' is not a PerlFloat.

Not that C++ is a paragon of virtue, but operators in C++ work this way, as
does Perl5's overload extension.

Even in the existing case, the '$b' vtable will be called; that should not
be changed.

> The HL normally has smome rules, what the LHS has to be, so normally,
> you do a "new Px, .Type" for the LHS and you have already a PMC of the
> correct type. When the HL has different concepts, this might not be useful.

The (or one of the) subjects of the op has a better idea of the result type
than the caller (for example, $b and $c could be floats, or integers, and
the target should match, but the HL doesn't know which they are at compile
time).

Another interesting question: interoperability between languages.  What do
you get when you add a PerlInteger and a RubyInteger?  This seems like an
interesting can of worms, actually - the best idea I can come up with is
that a whole lot of morphing should be done at the interface ("interface"
defined as "the place where the two languages meet", in this case).

> leo

Dave
Isa. 40:31

Reply via email to