diff --git a/thunks.go b/thunks.go index a8e7835..3f9d86f 100644 --- a/thunks.go +++ b/thunks.go @@ -38,9 +38,19 @@ func (rv *readyValue) bindToObject(sb selfBinding, origBinding bindingFrame, fie return rv } +func (rv *readyValue) aPotentialValue() {} + // potentialValues // ------------------------------------- +// evaluable is something that can be evaluated and the result is always the same +// It may require computation every time evaluation is requested (in contrast with +// potentialValue which guarantees that computation happens at most once). +type evaluable interface { + // fromWhere keeps the information from where the evaluation was requested. + getValue(i *interpreter, fromWhere *TraceElement) (value, error) +} + // thunk holds code and environment in which the code is supposed to be evaluated type thunk struct { env environment @@ -94,10 +104,10 @@ func (th *callThunk) getValue(i *interpreter, trace *TraceElement) (value, error // TODO(sbarzowski) force use cached/ready everywhere? perhaps an interface tag? // TODO(sbarzowski) investigate efficiency of various representations type cachedThunk struct { - pv potentialValue + pv evaluable } -func makeCachedThunk(pv potentialValue) *cachedThunk { +func makeCachedThunk(pv evaluable) *cachedThunk { return &cachedThunk{pv} } @@ -112,6 +122,8 @@ func (t *cachedThunk) getValue(i *interpreter, trace *TraceElement) (value, erro return v, nil } +func (t *cachedThunk) aPotentialValue() {} + // errorThunk can be used when potentialValue is expected, but we already // know that something went wrong type errorThunk struct { @@ -126,6 +138,8 @@ func makeErrorThunk(err error) *errorThunk { return &errorThunk{err} } +func (th *errorThunk) aPotentialValue() {} + // unboundFields // ------------------------------------- diff --git a/value.go b/value.go index b139b83..b4c8232 100644 --- a/value.go +++ b/value.go @@ -40,14 +40,15 @@ type value interface { // are not calculated before they are used). It is also a useful abstraction // in other cases like error handling. // -// It may or may not require computation. -// -// Getting the value a second time may or may not result in additional evaluation. +// It may or may not require arbitrary computation when getValue is called the +// first time, but any subsequent calls will immediately return. // // TODO(sbarzowski) perhaps call it just "Thunk"? type potentialValue interface { // fromWhere keeps the information from where the evaluation was requested. getValue(i *interpreter, fromWhere *TraceElement) (value, error) + + aPotentialValue() } // A set of variables with associated potentialValues.