? pragma.syntax("0.9") This version is like the basic simplified Horton, but modified to use only eventual-sends ("<-") and promises between principals, in order to avoid any additional liveness hazards between principals. In this version we use the otherwise-absent return path to indicate when we're done, for testing purposes. ? def c { > to hi(_) { > println("hi") > } > } # value: <c> ? c.hi(c) # stdout: hi # ? def b { > to foo(c_) { > return c_ <- hi(c_) > } > } # value: <b> ? interp.waitAtTop(b.foo(c)) # stdout: hi # ? def makeA(b_, c_) { > def a { > to start() { > return b_ <- foo(c_) > } > } > return a > } # value: <makeA> ? def directA := makeA(b, c) # value: <a> ? interp.waitAtTop(directA.start()) # stdout: hi # Note that makeProxy below has been modified to return a promise for the proxy. This promise is only resolved to the proxy once its stub instance variable is itself resolved, since, until then, the sender of a message to the proxy doesn't yet know that whoBlame should actually be held responsible for servicing these messages. Most places in the original where we were passing a Who around, since these are now possibly-eventual references, we are instead passing around (by copy when remote) a pair of a Who and a String name for logging. As with the base version, the logged names are not yet securely interpretable designators. This security issue is repaired later when we introduce petnames. # E sample def makeQuoteln := <elang:interp.makeQuoteln> def makeProxy([whoBlame_, nameBlame :String], stub_, reportln) { return when (stub_) -> { def log := makeQuoteln(reportln, `I ask $nameBlame to:`, 75) def proxy { # as P2 to getGuts() { return [stub_, [whoBlame_, nameBlame]] } # as P1 match [verb, [p2]] { log(`$verb/1`) def [s2_, [whoCarol_, nameCarol :String]] := p2.getGuts() def gs3_ := s2_ <- intro([whoBlame_, nameBlame]) def p3Desc := [gs3_, [whoCarol_, nameCarol]] stub_ <- deliver(verb, [p3Desc]) } } } } # as S2 def wrap(s3_, whoBob_, beCarol) { def provide(resolverBox) { def resolver_ := beCarol.unseal(resolverBox) resolver_ <- resolve(s3_) } return whoBob_ <- seal(provide) } # as S1 def unwrap(gs3_, whoCarol_, beBob) { def provide_ := when (gs3_) -> { beBob.unseal(gs3_) } def [result, resolver] := Ref.promise() def resolverBox := whoCarol_ <- seal(resolver) provide_ <- run(resolverBox) return result } def makeStub(beMe, [whoBlame_, nameBlame :String], targ, reportln) { def log := makeQuoteln(reportln, `$nameBlame asks me to:`, 75) def stub { # as S2 to intro([whoBob_, nameBob :String]) { log(`meet $nameBob`) def s3_ := makeStub(beMe, [whoBob_, nameBob], targ, reportln) return wrap(s3_, whoBob_, beMe) } # as S1 to deliver(verb, [p3Desc]) { log(`$verb/1`) def [gs3_, [whoCarol_, nameCarol :String]] := p3Desc def s3_ := unwrap(gs3_, whoCarol_, beMe) def p3_ := makeProxy([whoCarol_, nameCarol], s3_, reportln) return E.call(targ, verb, [p3_]) } } return stub } The makePrincipal code is changed only to add the names to blame, since all other needed changes were already in the code above. # E sample def makeBrand := <elib:sealing.makeBrand> def makePrincipal(label :String) { def reportln := makeQuoteln(println, `$label said:`, 77) def [whoMe, beMe] := makeBrand(label) def principal { to __printOn(out :TextWriter) { out.print(label) } to who() { return whoMe } to encodeFor(targ, [whoBlame, nameBlame :String]) { def stub := makeStub(beMe, [whoBlame, nameBlame], targ, reportln) return wrap(stub, whoBlame, beMe)} to decodeFrom(gift, [whoBlame, nameBlame :String]) { def stub := unwrap(gift, whoBlame, beMe) return makeProxy([whoBlame, nameBlame], stub, reportln) } } return principal } The players: ? def alice := makePrincipal("Alice") # value: Alice ? def bob := makePrincipal("Bob") # value: Bob ? def carol := makePrincipal("Carol") # value: Carol Initial connectiivity: ? def gs1 := bob.encodeFor(b, [alice.who(), "Alice"]) ? def gs2 := carol.encodeFor(c, [alice.who(), "Alice"]) ? def p1 := alice.decodeFrom(gs1, [bob.who(), "Bob"]) ? def p2 := alice.decodeFrom(gs2, [carol.who(), "Carol"]) ? def a := makeA(p1, p2) The resulting transcript is identical to the previous, although it now takes place over multiple turns. ? interp.waitAtTop(a.start()) # stdout: Alice said: # > I ask Bob to: # > > foo/1 # Carol said: # > Alice asks me to: # > > meet Bob # Bob said: # > Alice asks me to: # > > foo/1 # Bob said: # > I ask Carol to: # > > hi/1 # Carol said: # > Bob asks me to: # > > meet Carol # Carol said: # > Bob asks me to: # > > hi/1 # hi # |
||||||||||||
Unless stated otherwise, all text on this page which is either unattributed or by Mark S. Miller is hereby placed in the public domain.
|