[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