[Grace-core] NS inheritance cannot work for grace

Richard Roberts rykardo.r at gmail.com
Wed Nov 29 11:29:50 PST 2017


I am following the discussion, although I am still feeling confused about a
few parts. I don't have much to add all of this, except fleshing out the
"dynamic" approach to solving the problem. Below I touch on what's
currently wrong my translation of Grace inheritance into SOMns; and then, I
describe a potential solution for resolving inheritance at runtime. It's a
terrible idea, but if you are interested it's there - I won't be offended
if it's ignored :)


Up until now, I had simply translated inherit clauses by invoking the
request to create the object to be inherited; then I had used a platform
class mirror to obtain the platform class used to create that object; and
finally, the installation of the inherited slots, methods, and initer
expressions was handled by the platform. That approach was working well in
cases where the expressions of the initialization method (of the inherited
object) did not refer to the scope enclosing the *declaration* of the
inherited object.

The minigrace tests I was hoping to run include class declarations whose
initer expressions refer to an object whose initer expressions need access
to the scope enclosing (the inherited) objects declaration. Once I realized
my translation was invalid in these situations, I started thinking more
about the problem. In particular, I'm completely at a loss for how to
translate the "unreversible" methods when requested by inheritance clauses
- although from the discussion above it seems I might not need to think
about that for some time. Unfortunately, the minigrace tests

I did think of one dynamic solution that resolves inheritance at run time,
but it requires changing Grace's inheritance semantics. Here's the change:

*if no inherit expression declared, *
    1 - make a fresh object
*else *
    1 - call inherit expression (if found).
       1.1 invoke the request declared in the inheritance clause
       1.2 assign the object to self.

2 - process trait expressions (if found).
*    for each trait*
     2.1 invoke the request declared in the uses clause
     2.2 add each trait object to a secret slot on the object
     2.3 add a method alias each method of the trait (can resolve excludes
and alias expressions here too)

3 - run the initer expressions

I've thought about this for about 2 minutes (so not very long) but I can't
see how this would necessarily change the behaviour. In particular, (1) all
of the initialization expressions `self` still refers to the fresh object
and (2) the initialization expressions declared by the inherited object
still run in the expected scope (where the inherited object is declared)
and (3) the structural type check should work as expected (provided that
the secret slots for the traits are ignored).

Anyway, I get the feeling it might be better to think more about what
manifest means and resolve the inheritance at compile time. Or take the
OCAML approach (that easy for me at least). Or yet another idea, we could
just a fresh object for each trait and superclass, and forwarding messages
up the chain when they fail, but then we need to think more carefully about
how to manage slots.


On Wed, Nov 29, 2017 at 11:47 PM, Stefan Marr <S.Marr at kent.ac.uk> wrote:

> Hi:
>
> I tried to read up a bit to be able to have an informed opinion on how to
> coerce SOMns into providing what you need.
> But, after a while, I gave up. So, I don’t understand all the details, I
> am not even sure yet I get the subtle points of your examples.
>
> To implement this efficiently, I think, Richards “wants” to take SOMns’
> object model, or at least the instantiation part, apart and properly adapt
> it to your needs.
> I suppose scoping etc are much easier to get right that way, and the
> resulting interpreter/object model code is hopefully a more direct
> representation of your spec. Which hopefully means it is going to be more
> maintainable in the long run.
>
> Can it be implemented efficiently? I don’t see why not. The key here seems
> to be that you require to statically know the shape of the resulting
> object/class. To me this means the actual object factory can be created
> lazily on first use, and then be reused.
>
>
> What I don’t really understand is where all the restrictions are supposed
> to be tested.
>
> Inheritance is always done via the `inherit` keyword? (I suppose it is a
> keyword).
>
> For the evil example, I don’t see an issue. It’s just that one would
> remember an object has a certain structure, and then error if that’s
> violated, right?
>
> What I am not clear about is what’s a fresh object, and how to test for
> that?
> Is that a property of the method? So, I can check
> method.objectFactoryInTailPosition == true?
> I don’t see how this would work. Grace got late binding, right?
>
> With respect to scoping, are there restrictions on where the inherit can
> appear in an object/class?
> Is the expression after it restricted somehow?
> I suppose that’s what Richard had problems with to properly map to
> Newspeak.
> I guess the best solution would be just to change what SOMns does for
> Grace, because currently, the relevant expression for Newspeak’s superclass
> resolution is evaluated strictly outside of the object/class body.
>
> Not sure this is of much help, for me, this might be better discussed via
> Skype so I can ask more questions…
>
> Best regards
> Stefan
>
> > On 29 Nov 2017, at 09:10, kjx <kjx at ecs.vuw.ac.nz> wrote:
> >
> >> A system where methods become inheritable or not based on the values of
> their arguments seems dubious to me.
> >
> > :-)
> >
> >> (if I can override “random”, evil is no longer reliable).
> >
> > so I should've said I was assuming random here was a module.
> > Although (modulo types & exceptions) it's not clear it matters what
> > that expression does, so long as it returns a boolean.
> >
> >>   def x = object {
> >>       method p { object { } }
> >>   }
> >>   method parent(o) { o.p }
> >>   object { inherit parent(x) }
> >
> > perhaps.
> > arguably, at the top level of a module, this may well meet the
> definition of inheritable / manifest.
> > If you can't override x or parent(_), why is this much worse than
> >
> > object { inherit x.p }
> >
> >
> >> It also pushes the “cannot be overridden” criterion deeply through the
> entire potential call stack
> >
> > not sure I follow this.
> >
> >> Otherwise, yes.
> >
> > Umm OK.
> >
> > James
> >
>
> --
> Stefan Marr
> School of Computing, University of Kent
> http://stefan-marr.de/research/
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailhost.cecs.pdx.edu/pipermail/grace-core/attachments/20171130/795c2d1f/attachment-0001.html>


More information about the Grace-core mailing list