1 import Base 2 import capabilities.bend as Cap 3 import component.bend as C 4 5 # Consumer-owned vocabulary, equality, legal move enum and endpoints are trusted 6 # declarations. Local acceptance never commits the surrounding transaction. 7 type WriteStatus is Data: 8 WriteAccepted{} 9 WriteRejected{error: WriteError} 10 type Outcome is Data: 11 StateMoved{} 12 StateMismatch{expected: Value,actual: Value} 13 StateAccessRejected{access: C.Access} 14 StateWriteRejected{error: WriteError} 15 def move_written(~H: Type,~Value: Data,~WriteError: Data,pair: H & WriteStatus) -> H & Outcome: 16 match pair: 17 case (owner,WriteAccepted{}): (owner,StateMoved{}) 18 case (owner,WriteRejected{error}): (owner,StateWriteRejected{error}) 19 def apply(~H: Type,~Value: Data,~WriteError: Data,~write: Cap.Request>,+expected: Value,+target: Value,+actual: Value,owner: H,same: Bool) -> H & Outcome: 20 match same: 21 case False{}: (owner,StateMismatch{expected,actual}) 22 case True{}: move_written(~H,~Value,~WriteError,Cap.request(~H,~Value,~WriteStatus,~write,owner,target)) 23 def observed(~H: Type,~Value: Data,~WriteError: Data,~equal: Value -> Value -> Bool,~write: Cap.Request>,+expected: Value,+target: Value,pair: H & C.Access) -> H & Outcome: 24 match pair: 25 case (owner,C.Found{+actual}): apply(~H,~Value,~WriteError,~write,expected,target,actual,owner,equal(actual,expected)) 26 case (owner,C.ComponentAbsent{}): (owner,StateAccessRejected{C.ComponentAbsent{}}) 27 case (owner,C.MissingEntity{}): (owner,StateAccessRejected{C.MissingEntity{}}) 28 def compare_set(~H: Type,~Value: Data,~WriteError: Data,~equal: Value -> Value -> Bool,~read: Cap.Read,~write: Cap.Request>,owner: H,+expected: Value,+target: Value) -> H & Outcome: 29 observed(~H,~Value,~WriteError,~equal,~write,expected,target,Cap.read(~H,~Value,~read,owner)) 30 def with_endpoints(~H: Type,~Value: Data,~WriteError: Data,~equal: Value -> Value -> Bool,~read: Cap.Read,~write: Cap.Request>,owner: H,pair: Value & Value) -> H & Outcome: 31 (+expected,+target) = pair 32 compare_set(~H,~Value,~WriteError,~equal,~read,~write,owner,expected,target) 33 def transition(~H: Type,~Value: Data,~Move: Data,~WriteError: Data,~equal: Value -> Value -> Bool,~endpoints: Move -> Value & Value,~read: Cap.Read,~write: Cap.Request>,owner: H,move: Move) -> H & Outcome: 34 with_endpoints(~H,~Value,~WriteError,~equal,~read,~write,owner,endpoints(move)) 35 36 # Exact caller-error preservation; the caller's decoder validates its own Raw. 37 # Returning Raw on refusal retains the supplied finite input independently of 38 # whatever diagnostic representation the caller places inside Error. 39 type TypedRawOutcome is Data: 40 TypedRawWritten{} 41 TypedRawRejected{raw: Raw,error: Error} 42 TypedRawWriteRejected{raw: Raw,error: WriteError} 43 def written_result(~H: Type,~Raw: Data,~Error: Data,~WriteError: Data,raw: Raw,pair: H & WriteStatus) -> H & TypedRawOutcome: 44 match pair: 45 case (owner,WriteAccepted{}): (owner,TypedRawWritten{}) 46 case (owner,WriteRejected{error}): (owner,TypedRawWriteRejected{raw,error}) 47 def result_observed(~H: Type,~Value: Data,~Raw: Data,~Error: Data,~WriteError: Data,~write: Cap.Request>,owner: H,raw: Raw,decoded: Result<&2,&1,Error,Value>) -> H & TypedRawOutcome: 48 match decoded: 49 case Done{value}: written_result(~H,~Raw,~Error,~WriteError,raw,Cap.request(~H,~Value,~WriteStatus,~write,owner,value)) 50 case Fail{error}: (owner,TypedRawRejected{raw,error}) 51 def result_raw_inner(~H: Type,~Value: Data,~Raw: Data,~Error: Data,~WriteError: Data,~decode: Raw -> Result<&2,&1,Error,Value>,~write: Cap.Request>,owner: H,+raw: Raw) -> H & TypedRawOutcome: 52 result_observed(~H,~Value,~Raw,~Error,~WriteError,~write,owner,raw,decode(raw)) 53 def set_raw_result(~H: Type,~Value: Data,~Raw: Data,~Error: Data,~WriteError: Data,~decode: Raw -> Result<&2,&1,Error,Value>,~write: Cap.Request>,owner: H,raw: Raw) -> H & TypedRawOutcome: 54 match raw: 55 case +raw: result_raw_inner(~H,~Value,~Raw,~Error,~WriteError,~decode,~write,owner,raw)