[e-lang] Object coercion / adaptation
Mark S. Miller
e-lang@mail.eros-os.org
Sun, 05 May 2002 14:53:32 -0700
At 02:08 PM 5/3/2002 Friday, Ka-Ping Yee wrote:
>> "getOptMeta" is rather horrible, but "conform" has too narrow a meaning --
>> getOptMeta is for a general purpose dispatch on a brand, modeled on Joule's
>> Energetic Secrets protocol. It can be used for much else besides type
>> conformance. However, I'd dearly like to get rid of the name "getOptMeta".
>[out of order]
>Or, put another way: as far as i can tell, the current contract to which
>getOptMeta commits is "given a brand, return whatever". That's too vague
>for me; i'd prefer a more specific contract like "given a guard, return
>a representative for yourself that conforms to it".
In general, I *VERY STRONGLY* agree with the design heuristic you present
above. getOptMeta (or whatever we rename it to) is our second exception to
this heuristic. To understand why this exception is a good idea, let's
start with our first exception: method dispatch.
E objects are closures. Closures are functions-with-state, and a
conventional function simply has parameters. Conventional functions don't
have a built-in notion of method dispatch.
Seen from this perspective, E's plumbing expression
http://www.erights.org/elang/blocks/defPlumbing.html is properly seen as
more primitive that E's normal object definition expression. The plumbing
expression defines an object as a simple function, and a call to an object is
an application of this function to the message as the unitary argument.
Except for Miranda Methods, E's object expressions could be seen as
syntactic sugar for use of the plumbing expression. Our old friend the point
def point {
to getX() :any {x}
to getY() :any {y}
to add(other) :any { ... }
}
is nearly equivalent to
pragma enable("plumbing")
def point match msg {
switch msg {
match [`getX`, []] { x }
match [`getY`, []] { y }
match [`add`, [other]] { ... }
}
}
and indeed, method dispatch is defined by such expansions in
(chronologically) Smalltalk-72, Actors, T, and Joule. An object is just a
function of a message. (Or rather, a function-with-state.)
Such objects-as-functions, when described at the function level of
abstraction, violate your design heuristic in exactly the same fashion --
they "do whatever they do", depending on the meaning of the message they are
applied to. But everyone is happy to make this exception, because method
dispatch is needed in order to create the world in which your heuristic
applies -- a world in which distinct methods are used for distinct tasks.
So long as the above mechanism is adequate *as* a method dispatch mechanism,
we don't need to make any further exceptions.
The security properties of the above method dispatch mechanism corresponds
directly to capability security as normally practiced, such as by KeyKOS and
EROS. The message name (or order code) is guessable data, and the message
itself is a transparent data structure, such that any intermediary
forwarding the message can play man-in-the-middle. This
transparency-by-default is essential for pervasive virtualizability.
T was the first language to explore a method dispatch mechanism with
stronger security properties. In T, the role normally played by "message
name" or "order code" is instead played by a first class anonymous selfish
object. I don't remember what this was called, so I'll call it the
"dispatch object". The use of a message name in the caller's environment is
looked up in the caller's lexical scope in order to find the dispatch object
to be used in the message. The use of a method name in the callee's
environment was looked up in the callee's lexical scope to find the dispatch
object used to index the callee's dispatch table. The same dispatch object
might be known by different names to different callers, and by yet different
names to different potential callees, but as long as they are all talking
about the same dispatch object it all works.
Besides more flexible name-space management, this mechanism also provides T
with some interesting security properties. Specifically, if Alice doesn't
have access to the dispatch object normally named "Point_getX", then she
can't get the X coordinate of any point. However, since, in T, the message
structure is still transparent, if she virtualizes a point (plays MITM)
which she can pass to someone who wants the point's X coordinate, she can
steal the dispatch object normally named "getX", and so obtain the X
coordinate of all points she has access to. So this scheme has properties
stronger than normal capability practice, but the extra security is weaker
than an oo equivalent of single key cryptography.
Inspired by this, Joule's Energetic Secrets mechanism
ftp://ftp.webcom.com/pub1/agorics/postscript/MANUAL.B17.ps.Z
provides similar first-class-ness of dispatch objects, but the extra
security is an oo equivalent of public key cryptography, implicitly using
Sealer/Unsealer pairs as part of the message dispatch mechanism. Using E
terminology, the message being passed is a SealedBox whose Brand is the
dispatch object. The callee uses this Brand to look up a corresponding
Unsealer, which was lexically bound by the callee's use of a method name. If
the callee finds such an Unsealer, it uses it to unseal the message and
obtain the arguments. Joule has no implicit continuations, so any response
to the caller would only be sent along these arguments, and therefore only
could be sent if these arguments could be obtained. There's more to it than
that, some of which is very clever, but that's the relevant part for the
current story.
In E, for a variety of reasons (ask if your curious), I reverted to the
simple capability story for the normal message sending case. I see
getOptMeta as a method only in the same way I see an E object as a function.
An E object-as-function is the gateway to our first (conventional) method
dispatch mechanism. getOptMeta, found through this mechanism, is the
gateway to our second (Energetic-Secrets-like) method dispatch mechanism.
In a system like E, when functions are generally objects, essentially all
functions should assume that their argument is a message, and complain about
not understanding a particular kind of message, rather than becoming
confused by treating it as something else. This is one way to explain what
is meant by "everything is an object" http://www.paulgraham.com/reesoo.html .
In a similar though weaker vein, in a system where some objects implement
a protocol for a second level of dispatch with different security
properties, it's good to have universal support for invoking that second
level, and for a callee to complain that it didn't recognize a Brand (a
second level complaint) rather than complain that it didn't recognize
getOptMeta/1 (a first level complaint).
E's getOptMeta mechanism is security-equivalent to Joule's Energetic
Secrets, but as a method dispatch mechanism it is substantially harder to
use. However, for conformance, which is expected to remain by far the
common case, it is easier to use than an adaptation of Energetic Secrets
would be. (In E, since the continuation isn't included in the message, is
implicit, and isn't first class, it's not obvious what such an adaptation
would look like anyway.)
[out of order]
>I see that general purpose dispatch on a brand is that *mechanism*
>currently used to implement getOptMeta, and that mechanism could be used
>to implement other things, but i'd rather not mix these different
>purposes just because they have similar mechanisms.
Does the above adequately answer this?
>Also, as long as
>it's a Miranda method, getOptMeta can't really be used for general purpose
>anything, since its implementation is internal. (I know it can be
>overridden, but the part that has to do with dispatching on a brand
>is internal, and E code cannot manipulate that dispatch table -- in fact
>we currently rely on the fact that it cannot.)
As far as I can tell, all user-defined behavior that we should support can
be defined by wrapping (ie, virtualizing, MITM) the Miranda getOptMeta.
Such virtualization can't violate its built-in security properties, but
also, AFAI can see, doesn't prevent any pattern we should allow. In
particular, a user defined getOptMeta can do its own dispatch on the brand.
----------------------------------------
Text by me above is hereby placed in the public domain
Cheers,
--MarkM