[Grace-core] More thoughts on modules

James Noble kjx at ecs.vuw.ac.nz
Thu Jun 9 04:27:01 PDT 2011


> An advantage of including partial revelations is that it can be used to limit access to particular methods when objects (or their types) are imported.

thinking about this, I'm really not sure how this works in a primarily structural world.

Say I've the module 

interface module M {
   type T extends {
     wallClockTime -> TimeOfDay
    }
}

all very nice.  Then the implementation

module WhiteHouse {
 class OvalOffice {
   wallClockTime -> TimeOfDay {...}
   armageddon -> Void { ... }   // really don't call this ever
  }
}

OK so here's the exported  partial revelation 

implementation module SafeForTours
    implements M /// do I have to say this?   
  {
    import WhiteHouse;
    type T = WhiteHouse.OvalOffice.
    const office = T.new()
}

so far so good.  and secure with nominal types. 
but what's to stop some inquisitive visitor doing 
a structural pattern match

match (SafeForTours.office) 
   case { o : interface { armageddon -> Void } -> o.armageddon }

oops.  


As far as I can see, with reasonable semantics, to prevent this you'd
at least need lisp style namespaces (i think some Smalltalks used
them too) so the name WhiteHouse#armageddon (or however we 
 write it) is *different* to the armageddon in any other module. 
in particular it can only be uttered by the WhiteHouse module -
or importing it gives the other module permission to access it.

How that then works with cross module inheritance etc
where we want names to be implement in many modules
I'm really not sure - probably all modules need to start by
importing the underlying types to make sure they're
defining the  same message.
 
This again complicates the message resolution rules etc,
and can no doubt lead to lots of nasty inconsistencies.

This does serve to show the unit of protection here is the 
name, specifically the method name, not the object.


Mark Miller objects-as-capabilities would do this by a proxy:

implementation module SafeForTours
    implements M /// do I have to say this?   
  {
    import WhiteHouse;
    class SafeOffice {
    const realOffice = WhiteHouse.OvalOffice.new();
    wallClockTime -> TimeOfDay {return realOffice.wallClockTime}
     }
    type T = SafeOffice.
    const office = T.new()
}

the SafeOffice class is what gets passed out - and it is a 
small matter of programming that the code for SafeOffice
*never* leaks the underlying realOffice. 


I'd want to take that one stage further, even dynamically,
writing something like

implementation module SafeForTours
    implements M /// do I have to say this?   
  {
    import @Owned WhiteHouse;
    class SafeOffice {
    const realOffice = self.WhiteHouse.OvalOffice.new();
    wallClockTime -> TimeOfDay {return realOffice.wallClockTime}
     }
    type T = SafeOffice.
    const office = T.new()
}

where import @Owned
 - makes a new *inner class* of SafeOffice which is a copy of the WhiteHouse class
 - marks that class as owned by the 'this" instance of SafeOffice

then use static (and for Grace, dynamic) checks to ensure that only
a particular instance of SafeOffice (or other classes nested inside it)
can send any message *at all* to that object's owned realOffice instance - 
any programmer leaks in the SafeOffice class are caught by the ownership
system.    That's what *I'd* like in!





sorry if the example is morbid. I blame flying. And the TSA.
Who were very polite it must be said. 

James 



More information about the Grace-core mailing list