[e-lang] Proposal: The "where" expression
Mark S. Miller
markm at cs.jhu.edu
Tue May 29 00:27:11 EDT 2007
I had a perverse idea of a simple lightweight syntax for doing remote
evaluation of E code: The where-expression. The appeal of this syntax is that
it is so similar to the simple case of the existing when-expression, both
syntactically and semantically, so that it provides much power for a very low
incremental learning cost.
In the simple when-expression:
def p2 := when (p1) -> { ... p1 ... }
the expression in the block to the right of the "->" is postponed until p1 is
fulfilled. Only after p1 is fulfilled, this block will execute in its own
separate turn (top-level transaction). The when-expression immediately returns
a promise for the value that this block will evaluate to. All this is brought
about first by packaging up the block on the right into a call-back object.
The proposed where-expression:
def p2 := where (p1) -> { ... p1 ... }
instead packages up the block on the right into a PassByCopy call-back object
and passes it as the argument of a __whenMoreResolved message sent to p1.
Therefore, this block is expected to execute only after p1 is fulfilled, but
is expected to execute in a separate turn *in the vat* hosting the object p1
designates. In the when-expression, the expression on the right may safely
assume p1 is fulfilled (i.e., near or far). In the where-expression, the
expression on the right may safely assume p1 is near.
In both cases, p2 is immediately bound to a promise for what the expression on
the right will evaluate to. In the where-expression, this is generally a
remote promise.
Given this syntax, a pleasant way to spawn a vat for purely computational
purposes is to spawn it containing a pass-by-proxy mascot object that does
nothing, but serves to represent its hosting vat. Then, one could spawn
computation into that vat with the intuitive
def p2 := where (vatAMascot) -> { ...expr to evaluate in vat A... }
Expansion
A proposed expansion (after a bit of trivial simplification for readability):
(def [p2,r2] := Ref.promise()
(p1) <- __whenMoreResolved(
def _ implements PassByCopy {
to run(p1) {
try {
r2.resolve(... p1 ...)
} catch ex {
r2.smash(ex)
}
}
to __optUncall() {
return [eval,
"run",
[meta.context().getSource(),
meta.getEnv()]]
}
})
p2)
This presumes a working PassByCopy auditor, though the existing pbc
(pass-by-construction) auditor should be good enough to get started. In also
presumes a pervasive eval/2 function which can recreate a PassByCopy object
from its reflectively obtained AST and lexical environment. We are very close
to being able to support this, mostly pending the precise specification of
what such a lexical environment contains.
Security
As stated, the above proposal has a hidden security hazard. From all the rest
of E, a programmer looking at
def p2 := where (p1) -> { ... p1 ... x ... }
would be right to expect that p1 can only cause x to be manipulated in ways
that the expression above manipulates it. However, by passing the closure by
copy to p1's vat, we're also giving p1's vat (whom we might not trust) direct
access to x. I'm not sure what to do about this. Perhaps we should insist that
the block refer freely only to safe things and p1?
--
Text by me above is hereby placed in the public domain
Cheers,
--MarkM
More information about the e-lang
mailing list