[e-lang] E patches for review: ELoader, seedVat
Kevin Reid
kpreid at switchb.org
Fri May 21 04:25:11 PDT 2010
On May 21, 2010, at 4:59, Thomas Leonard wrote:
>> 1. Envs also have the distinction which prohibits binding a noun
>> twice
>> within a single scope, and is controlled by nestOuter(). This is data
>> a ConstMap does not have.
>
> Is this useful when calling eval() from E?
The intent is that it should be possible to write an evaluator using
Env (Scope) as the environment type. This is not possible if Env does
not preserve this information.
>> 2. Once guard-based auditing is implemented, there will be an
>> additional indirection ('bindings'), besides slots, between env and
>> their values. The virtue of the distinct Env (Scope) type is that it
>> provides operations which allow clients to ignore these additional
>> features (slots and bindings) when they are not relevant to the
>> application.
>
> That's possible. I think it needs to be a separate type, though:
>
> - Scope: containing a ScopeLayout and an EvalContext with outers,
> fields
> and locals) used internally.
>
> - Env / ConstMap: no layout, just "outers".
No. "Scope" is an incorrect and deprecated name. It is to be renamed
to "Env". There is no distinction between them.
> But for simplicity I think I'd find it easier to understand if it was
> just a map from names to slots (or bindings), even if I had to write a
> little more code, e.g.
>
> code.eval(safeEnv | [ "answer" => makeFinalSlot(42) ])
>
> I don't really like all the "if (k.startsWith("&"))" in Scope.java.
I don't either; I feel those interfaces should be deprecated. The
solution I prefer is to have different methods for working with values
vs. slots vs. bindings.
>> Thomas, would you be interested in working on implementing guard-
>> based
>> auditing in E-on-Java? It would then be straightforward to add the
>> DeepFrozen auditor for E code to E-on-Java, which enables a variety
>> of
>> useful possibilities.
>
> I'm a bit confused about DeepFrozen. For example, could this be
> DeepFrozen?
>
> def requireOne :DeepFrozen {
> to run(x) {
> require(x == 1)
> }
> }
The correct syntax is
def requireOne implements DeepFrozen {
to run(x) {
require(x == 1)
}
}
> It seems not, because it mutates &require:
>
> ? (&require).isFinal()
> # value: false
> ? requireOne(1)
> ? (&require).isFinal()
> # value: true
>
> Can any useful code be DeepFrozen?
This is a mistake in the implementation of safeEnv (safeScope), not in
DeepFrozen. It should not be possible to observe whether a lazy eval
slot has been forced yet, because otherwise it leaks information among
users of a given safeEnv when it should not (regardless of the
existence of DeepFrozen).
> I'm also confused about bindings. ... Is this so that auditors don't
> get free access to all the values?
Yes. Auditors should be able to analyze the behavior of your code, but
not use the authority it bears.
> If so, why not just subclass FinalSlot, e.g.
>
> class AuditableFinalSlot extends FinalSlot implements AuditableSlot
>
> Then only give auditors auditable slots to look at (which would
> include
> everything in safeScope)?
Because this would prevent auditing from working at all on custom
slots unless they all carefully implemented AuditableSlot and were
audited to do so correctly -- and what does 'correctly' mean for a
sufficiently wacky slot? The binding system leaves it up to the
auditor to determine what an acceptable slot is.
(On the other hand, the binding system does make some annoying
complications, like &&foo, which are the part I like least about GBA
as it stands now (which is entirely my own design); so if you could
expand on this proposal and show it works better in practice, I'd be
interested to hear it.)
>> Perhaps, instead of using the persistence sealer, use the unsafe
>> loader, which presumably can (ought to be able to, anyway) uncall
>> makeTraceln?
>
> It can, but I don't want to let people get makeTraceln from <this>,
> e.g.
> with:
>
> def loader {
> to __optUncall() {
> return [makeLoader, "run", [sourceDir, envExtras, fqnPrefix]]
> }
> }
>
> You could recover makeLoader with:
>
> def makeLoader := <this>.__optUncall()[0]
>
> You can then use makeLoader to create loaders that log with any
> fqname,
> or uncall it to get makeTraceln. So, I think this needs to be sealed
> somehow.
Hold on. I'm not sure how what I proposed makes a difference here.
Could you explain the entire object graph leading up to makeTraceln?
I suspect a violation of the principle that any object with private
state must use an amplified uncall rather than __optUncall/0.
--
Kevin Reid <http://switchb.org/kpreid/>
More information about the e-lang
mailing list