Guard-based auditing

From Erights

(Difference between revisions)
Jump to: navigation, search
(update on status, use XXX)
(describe guard-based auditing plan so far)
Line 1: Line 1:
-
This is a new design for auditing in E. It is an alternative to the unshadowable-names/synEnv system currently implemented in [[E-on-Java]], and the give-the-auditor-access-to-everything previously used by [[E-on-CL]].
+
This is a new design for auditing in E. It is an alternative to the unshadowable-names/synEnv system currently implemented in [[E-on-Java]], and the give-the-auditor-access-to-everything currently in [[E-on-CL]].
-
 
+
-
It is currently provided in [[E-on-CL]] and [[User:Markm]] plans to implement it in [[E-on-Java]].
+
==Basic implementation==
==Basic implementation==
-
In [[environment]]s, nouns are associated with "bindings" instead of [[slot]]s. A binding is an object which holds a [[slot]] and a [[guard]], and alleges that that slot was returned from that guard (except for object expressions; see below).
+
[[Environment]]s holding an opt[[Guard]] along with each binding. For each noun, the scope alleges that the corresponding [[slot]] (not slot value!) was returned from that guard (except for object expressions; see below).
-
These properties of binding objects happen to make them very much like [[VarSlot]]s except for being immutable, so they implement the slot protocol and are called [[CoercedSlot]]. CoercedSlots are [[PassByConstruction]] and non-[[transparent]] [[Selfless]].
+
As a consequence of this, environments must not be [[Selfless]], since it is not necessarily possible to go from some product of a guard to a value it coerces to the same result. They may be [[PassByConstruction]], however.
-
Note that [[FinalPattern]]s and [[VarPattern]]s must get [[FinalSlot]] and [[VarSlot]] guards; e.g. <code>def x :int := 1</code> results in the binding object <code>makeCoercedSlot(FinalSlot[int], makeFinalSlot(1), null)</code> (except that implementations may optimize it to not require constructing an intermediate FinalSlot if the guard coerces).
+
(Note that [[FinalPattern]]s and [[VarPattern]]s must get FinalSlot and VarSlot guards; e.g. <code>def x :int := 1</code> has a guard-in-environment of <code>FinalSlot[int]</code>.)
-
If a pattern does not have a guard, then <code>any</code> is used. Examples: <code>def x := y</code> has a binding guard of <code>[[FinalSlot]][any]</code>, and <code>def &x := y</code> has a binding guard of <code>[[any]]</code>.
+
Environments gain the method fetchGuard/2, similar to fetchSlot/2.
-
Environments gain the methods fetchBinding/2, getBindings/0 (returns an object mapping nouns to bindings), and getSlots/0 (returns an object mapping nouns to slots), and lose iterate/1.
+
[[Audition]]s have one relevant method, [[Audition#getGuard/1|getGuard/1]]. Given a noun (string), it returns the environment's optGuard for that binding. (XXX seems to be some optional/required confusion here. Does this return null, or does it return 'any'? --[[User:Kevin Reid|Kevin Reid]] 08:58, 19 February 2008 (CST)) If the noun is not one of the free variables of the audition's object expression, or if the audit has already terminated, then an exception is thrown.
-
[[Audition]]s have one relevant method, [[Audition#getGuard/1|getGuard/1]]. Given a noun (string), it returns the guard of the matching binding. If the noun is not one of the free variables of the audition's object expression, or if the audit has already terminated, then an exception is thrown.
+
An additional component on kernel [[ObjectExpr]]s: the "<code>as</code>" clause, syntactically preceding the "<code>implements</code>", behaves like it but with the additional effect of making its value be the guard for the binding of the object name (without coercing the object). That is, <code>def x as Y {}</code> audits x with Y, and also causes the binding to be <code>("x", makeFinalSlot(<x>), FinalSlot[Y])</code>.
-
 
+
-
An additional component on kernel [[ObjectExpr]]s: the "<code>as</code>" clause, syntactically preceding the "<code>implements</code>", behaves like it but with the additional effect of making its value be the guard for the binding of the object name (without coercing the object). That is, <code>def x as Y {}</code> audits x with Y, and also causes the binding to be <code>("x", makeFinalSlot(<x>), FinalSlot[Y])</code>. In the E AST, the current <var>auditorExprs</var> :List[EExpr] is replaced with a new node type "AuditorExprs" with fields (<var>as</var> :nullOk[EExpr], <var>implements</var> :List[EExpr]).
+
-
 
+
-
Bindings may be reified in E programs using the prefix &amp;&amp; operator. (This is necessary to support nonkernel <code>[[meta.getState]]()</code>, and beneficial to the extends-syntax "<code>super</code>".) "&amp;&amp;" is a single token and operator, not two prefix operators. As an expression, it is BindingExpr(NounExpr); as a pattern it is BindingPattern(NounExpr). The pattern does not take a guard like [[SlotPattern]] does.
+
-
 
+
-
The expansion of ObjectExpr's "extends" clause is changed such that "<code>extends <var>someNoun</var></code>" results in <code>super</code> defined as "<code>def &amp;&amp;super := &amp;&amp;<var>someNoun</var></code>"; if the expression in the extends clause is not a noun then the expansion remains the current "<code>def super := <var>someExpr</var></code>"
+
-
 
+
-
Because bindings are Selfless, the evaluator need not make any effort to preserve their identities.
+
All bindings in the [[safeScope]] expose their values in their guards; that is, they are <code>("foo", bar, FinalSlot[Same[bar]])</code>.
All bindings in the [[safeScope]] expose their values in their guards; that is, they are <code>("foo", bar, FinalSlot[Same[bar]])</code>.
-
 
-
CoercedSlots are PassByConstruction; their uncall is makeCoercedSlot.attempt(guard, value). This performs guard.coerce(value, ...); if the guard fails, or returns a reference which is not the same as the original value, then the resulting CoercedSlot has LostApproval[guard] instead of the original guard. LostApproval is equivalent to [[any]], and is used merely to report what the original guard was and why it is missing. ({{XXX|LostApproval is not implemented in E-on-CL}})
 
==Implications for auditors==
==Implications for auditors==
-
 
-
{{XXX|write this}}
 
==Implications for guards==
==Implications for guards==
-
 
-
To support multiple independently-written auditors on the same object, it must be possible to have single guards which satisfy multiple auditors' criteria. It is also desirable that programmers need not write code to match exactly an auditor's view of what is necessary. Therefore, we add the optional operation rangeSupersetOf/1 to guards.
 
-
 
-
  to rangeSupersetOf(other :Guard) :nullOk[boolean]
 
-
 
-
If X.rangeSupersetOf(Y) returns true, X is claiming that every value returned by Y (as a guard) would have been returned by X under some circumstances; that is, the 'range' of X is a 'superset of' the range of Y. For example, int.rangeSupersetOf(1..10) should be true, as should [[DeepFrozen]].rangeSupersetOf(int).
 
-
 
-
Returning false indicates that X is not a range superset of Y; returning null indicates that X doesn't know.
 
==Open questions==
==Open questions==
-
{{XXX|write this}}
+
If environments are PassByConstruction, then, if a passed guard coerces some slot to a different slot upon unserialization, should the binding have the coerced value (i.e. now coerced twice), or should the binding forget the guard?
-
 
+
-
[[Category:Resolved design issues]]
+
-
[[Category:Message rangeSupersetOf/1]]
+

Revision as of 14:58, 19 February 2008

This is a new design for auditing in E. It is an alternative to the unshadowable-names/synEnv system currently implemented in E-on-Java, and the give-the-auditor-access-to-everything currently in E-on-CL.

Contents

Basic implementation

Environments holding an optGuard along with each binding. For each noun, the scope alleges that the corresponding slot (not slot value!) was returned from that guard (except for object expressions; see below).

As a consequence of this, environments must not be Selfless, since it is not necessarily possible to go from some product of a guard to a value it coerces to the same result. They may be PassByConstruction, however.

(Note that FinalPatterns and VarPatterns must get FinalSlot and VarSlot guards; e.g. def x :int := 1 has a guard-in-environment of FinalSlot[int].)

Environments gain the method fetchGuard/2, similar to fetchSlot/2.

Auditions have one relevant method, getGuard/1. Given a noun (string), it returns the environment's optGuard for that binding. (XXX seems to be some optional/required confusion here. Does this return null, or does it return 'any'? --Kevin Reid 08:58, 19 February 2008 (CST)) If the noun is not one of the free variables of the audition's object expression, or if the audit has already terminated, then an exception is thrown.

An additional component on kernel ObjectExprs: the "as" clause, syntactically preceding the "implements", behaves like it but with the additional effect of making its value be the guard for the binding of the object name (without coercing the object). That is, def x as Y {} audits x with Y, and also causes the binding to be ("x", makeFinalSlot(<x>), FinalSlot[Y]).

All bindings in the safeScope expose their values in their guards; that is, they are ("foo", bar, FinalSlot[Same[bar]]).

Implications for auditors

Implications for guards

Open questions

If environments are PassByConstruction, then, if a passed guard coerces some slot to a different slot upon unserialization, should the binding have the coerced value (i.e. now coerced twice), or should the binding forget the guard?

Personal tools
more tools