# Copyright 2005-2007 Kevin Reid, under the terms of the MIT X license # found at http://www.opensource.org/licenses/mit-license.html ................ ? def makeCoercedSlot := > def mkBinding(g, v) { return makeCoercedSlot(g, v, null) } # value: --- Making scopes --- ? var x := 22 # value: 22 ? def makeScope := # value: ? makeScope.asType() # value: Scope ? makeScope.asType() == # value: true ? def aScope := makeScope("testScope$", [ > "false" => mkBinding(def aGuard extends any {}, &false), > "y" => mkBinding(any, &x), > ], [ > "anInner" => mkBinding(any, &true), > ]) # value: Wrong binding type ? makeScope("oops$", ["x" => &false], [].asMap()) # problem: the FinalSlot <& false> doesn't coerce to a CoercedSlot ? makeScope("oops$", [].asMap(), ["x" => &false]) # problem: the FinalSlot <& false> doesn't coerce to a CoercedSlot --- Methods --- getFQNPrefix/0 ? safeScope.getFQNPrefix() # value: "__safe$" ? aScope.getFQNPrefix() # value: "testScope$" get/1, checking fromState ? aScope["false"] == false # value: true getSlot/1, checking slot state ? [aScope["y"] == x, aScope.getSlot("y") == &x] # value: [true, true] ? [x *= x, aScope["y"]] # value: [484, 484] iterate/1 ? for k => v in aScope { println(`$v <= $k`) } # stdout: <& true> <= &anInner # <& false> <= &false # <= &y # maps/1 ? [aScope.maps("y"), aScope.maps("z")] # value: [true, false] fetch/2 ? aScope.fetch("y", fn {print("fail"); 11}) # value: 484 ? aScope.fetch("z", fn {print("fail"); 11}) # stdout: fail # value: 11 getState/0 ? aScope.getState() # value: ["&anInner" => <& true>, "&false" => <& false>, "&y" => ] put/2 ? [aScope["y"] //= 2, x] # value: [242, 242] or/1 XXX write regular tests - this is just because I found that a ref-shorten/coerce was missing ? def p; bind p := safeScope; safeScope | p # value: withPrefix/1 ? safeScope.withPrefix("the.quick.brown.fox$").getFQNPrefix() # value: "the.quick.brown.fox$" withBinding/2 ? aScope.withBinding("new", &false) # problem: the FinalSlot <& false> doesn't coerce to a CoercedSlot ? def ext := aScope.withBinding("new", mkBinding(any, &false)) # value: ? ext["new"] # value: false ? ext["y"] # value: 242 --- Slots facet --- ? for k => v in aScope.slots() { println(`$v <= $k`) } # stdout: <& true> <= anInner # <& false> <= false # <= y # ? aScope.slots().fetch("y", fn {print("fail"); 11}) # value: ? aScope.slots().fetch("z", fn {print("fail"); 11}) # stdout: fail # value: 11 --- Bindings facet --- ? for k => v in aScope.bindings() { println(`$v <= $k`) } # stdout: <& <& true> :any> <= anInner # <& <& false> :> <= false # <& :any> <= y # ? aScope.bindings().fetch("y", fn {print("fail"); 11}) # value: <& :any> ? aScope.bindings().fetch("z", fn {print("fail"); 11}) # stdout: fail # value: 11 --- Selflessness --- ? aScope :PassByCopy # value: ? aScope.__optUncall() # value: [, "run", ["testScope$", ["false" => <& <& false> :>, "y" => <& :any>], ["anInner" => <& <& true> :any>]]] ? aScope == E.call(E, "call", aScope.__optUncall()) # value: true XXX test that a scope with bindings overridden via with/or/eval only produces one map entry --- 'Nesting' --- In the E language, rebinding a noun (e.g. e`def x := 1; def x := 2; x`) is not allowed, unless there is an intervening scope box (e.g. e`def x := 1; {def x := 2; x}`). A scope object enforces this; scope boxes are represented by #nestOuter/0. ? def nestTest1 := makeScope.fromState([].asMap(), "nestTest$") # value: ? def nestTest2 := nestTest1.with("x", 1) # value: ? nestTest2["x"] # value: 1 ? def nestTest3 := nestTest2.with("x", 2) # problem: "x" already in scope XXX better-phrased error ? def nestTest3 := nestTest2.withSlot("x", __makeFinalSlot(2)) # problem: "x" already in scope ? def nestTest2boxed := nestTest2.nestOuter() # value: ? def nestTest3 := nestTest2boxed.with("x", 2) # value: ? nestTest3["x"] # value: 2 --- Making safe-scopes This is for creating a scope with the usual safeScope structure but with different underlying objects; for example in the new scope would always be based on in that scope. xxx does this truly belong in prim? ? def makeSafeScope := # value: ? def altImport := [ > "org.erights.e.elib.eio.EIO" => def altEIO {} > ] # value: ["org.erights.e.elib.eio.EIO" => ] ? def ss := makeSafeScope("altSafe$", makeScope.fromState([ > "import__uriGetter" => altImport > ], "")) # value: EIO is dependent on ? ss["EIO"] # value: --- Making IO-scopes ScopeSetup is an excessively ambient interface. I hope to deprecate it. ? def scopeSetup := # value: ? def anIOScope := scopeSetup.privileged("testiing$", stdout, stderr, [].asMap(), def anInterp {}, null) # value: ? anIOScope["interp"] == anInterp # value: true Checking for missing nestOuter ? anIOScope.withSlot("interp", &null) # value: XXX write tests for the e-on-cl makeIOScope which is what ScopeSetup is based on