/* * point of the deferred_adapter is that normal adapter_preCH ( CH ) can not be initialized like: * adapter_preCH ( some_preCH_instance.CH ) * without immediately triggering instantiation of the CH and the whole chain of events that might trigger * -- before the constructor even runs * ( as far as i'm aware, there is no syntax to assign an accessor backing function to a delegate -- X.prop is always transated to a call ) */ public static LL <preCH> checkClosureTripwires(CH_deltaScope ch_dScope) { var R = (LL <preCH>)null; foreach (var _ref in ch_dScope.refs().Reverse()) { R = R.chain(_ref.name, new deferred_adapter_preCH(() => _ref.CH)); // yup proper _ref is captured here -- there were some subtle tripwires in c# closure building semantics, not unlike those of javascript, but i forgot which } return(R); }
public static void Test2_basic_scoping() { var closA = new TypedSingleCH <int>(); var closB = new TypedMultiCH <string>(); // types and kinds don't matter var closedSC = new CH_closedScope() .decl("cA", closA) .decl("cB", closB); var D1 = new TypedSingleCH <int>(); var D2 = new TypedMultiCH <string>(); // types and kinds don't matter TypedCH dummy1; TypedCH dummy2; var deltaCH = new CH_deltaScope(closedSC) .decl("new name", D1) .addRef("cA", out dummy1) .addRef("new name", out dummy2); D.Assert(object.ReferenceEquals(dummy1, closA)); D.Assert(object.ReferenceEquals(dummy2, D1)); D.Assert( deltaCH.external_refs().Select(_ref => _ref.name). SequenceEqual(new [] { "cA" }) // ref for "new name" is not external ); // ---------------------------- var deltaCH2 = new CH_deltaScope(closedSC) .decl("cA", D1) .decl("cA", D1) .decl("cA", D1) .decl("cB", D1) // shadow both, multiple "cA"s are compressed to one in LIFO_shadowed .decl("cA", D2) // shadow cA again with a different target .addRef("cA", out dummy1); var expected_names = new [] { "cA", "cB" }; // in reverse of insertion order var expected_chs = new TypedCH[] { D2, D1 }; // for cA , cB resp. D.Assert(deltaCH2.refs().Select(r => r.name).SequenceEqual(expected_names)); D.Assert(deltaCH2.refs().Select(r => r.CH).SequenceEqual(expected_chs)); // ------------------------------------- var closFunky = new TypedSingleCH <object>(); var origSC = new CH_closedScope() .decl("cA", closFunky) // never see this guy .decl("cA", closA) .decl("cB", closB); var sh1 = new TypedMultiCH <float>(); TypedCH sh_dummy1 = null; TypedCH sh_dummy2 = null; var shadowDelta1 = new CH_deltaScope(origSC) .decl("sh1", sh1) .addRef("cA", out sh_dummy1) // external ref .decl("cA", sh1) .addRef("cA", out sh_dummy2) // now cA is both an external and internal ref ; // cB is not touched , thus : // refs in order : [ "cA" -> sh_dummy2 == sh1 | "sh1" -> sh1 | "cB" -> closB ] // ["cA" -> closA == sh_dummy1] is preserved in external_refs D.Assert(ReferenceEquals(sh_dummy1, closA)); D.Assert(ReferenceEquals(sh_dummy2, sh1)); expected_names = new [] { "cA", "sh1", "cB" }; expected_chs = new TypedCH[] { sh1, sh1, closB }; D.Assert(shadowDelta1.refs().Select(r => r.name).SequenceEqual(expected_names)); D.Assert(shadowDelta1.refs().Select(r => r.CH).SequenceEqual(expected_chs)); D.Assert(shadowDelta1.external_refs().Select(r => r.name).SequenceEqual(new [] { "cA" })); D.Assert(shadowDelta1.external_refs().Select(r => r.CH).SequenceEqual(new TypedCH[] { closA })); // heheh :) two chaining deltaScopes need no extra testing new DeltaScope ( fromDeltaScope ) is identical to its original in all fields - there is no point to this Console.WriteLine("================= basicScoping ok ============= "); }