Created
February 9, 2022 11:02
-
-
Save ilyash-b/fd87050fd55e5d0de65a19cbee4b3ceb to your computer and use it in GitHub Desktop.
Autovivification for Next Generation Shell - experiment
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Following line will be needed when files will be auto-wrapped in "ns { ... }" | |
{ global deep_get, deep_set, deep_get_step, deep_set_step, deep_index_to_container_type } | |
doc %STATUS - experimental | |
F deep_get_step(node, _) { | |
throw LookupFail().set(container=node) | |
} | |
doc %STATUS - experimental | |
F deep_set_step(container, idx_or_key, next_idx_or_key) throw NotImplemented() | |
doc %STATUS - experimental | |
F deep_get_step(node, key) { | |
guard node =~ AnyOf(Hash, HashLike) | |
node[key] | |
} | |
doc %STATUS - experimental | |
F deep_set_step(node, key, val) { | |
guard node =~ AnyOf(Hash, HashLike) | |
node[key] = val | |
} | |
doc %STATUS - experimental | |
F deep_index_to_container_type(key) Hash | |
doc %STATUS - experimental | |
F deep_get_step(node:NormalTypeInstance, field:Str) { | |
node.(field) | |
} | |
doc %STATUS - experimental | |
F deep_set_step(node:NormalTypeInstance, field:Str, val) { | |
node.(field) = val | |
} | |
doc %STATUS - experimental | |
F deep_get_step(node, idx:Int) { | |
guard node =~ AnyOf(Arr, ArrLike) | |
node[idx] | |
} | |
doc %STATUS - experimental | |
F deep_set_step(node, idx:Int, val) { | |
guard node =~ AnyOf(Arr, ArrLike) | |
section "Ensure array is long enough" for(i=len(node);i<=idx;i+=1) { | |
node.push(null) | |
} | |
node[idx] = val | |
} | |
doc %STATUS - experimental | |
F deep_index_to_container_type(idx:Int) Arr | |
doc %STATUS - experimental | |
F deep_get(root, path, default=null) block b { | |
node = root | |
for p in path { | |
try { | |
node = deep_get_step(node, p) | |
} catch(lf:LookupFail) { | |
guard lf.container === node | |
b.return(default) | |
} | |
} | |
node | |
} | |
doc %STATUS - experimental | |
F deep_set(root, path:Arr, val) { | |
assert(path, 'path is expected to have at least one element, deep_set can not set the root') | |
path_iter = Iter(path) | |
container = null | |
idx_or_key = null | |
node = section "Navigate to last present element" block b { | |
node = root | |
while path_iter { | |
try { | |
container = node | |
idx_or_key = path_iter.next() | |
node = deep_get_step(node, idx_or_key) | |
} catch(lf:LookupFail) { | |
guard lf.container === node | |
b.return(node) | |
} | |
} | |
node | |
} | |
# echo("P $path_iter") | |
for p in path_iter { | |
# echo("P $path_iter $p") | |
next_container = deep_index_to_container_type(p)() | |
node = deep_set_step(container, idx_or_key, next_container) | |
container = next_container | |
idx_or_key = p | |
# echo("for end: container $container idx_or_key $idx_or_key") | |
} | |
deep_set_step(container, idx_or_key, val) | |
root | |
} | |
test("get existing hash->hash", { | |
h = {"a": {"b": 1}} | |
deep_get(h, ['a', 'b']).assert(1) | |
}) | |
test("get non-existing hash->hash", { | |
h = {"a": {"b": 1}} | |
deep_get(h, ['a', 'bx']).assert(null) | |
deep_get(h, ['a', 'b', 'c']).assert(null) | |
}) | |
test("set first level on custom type", { | |
type T | |
t = T() | |
t.deep_set(['field1'], 'val1').assert(T, 'deep_set should return object of type T') | |
t.assert({"field1": "val1"}) | |
}) | |
test("set two levels on custom type (hash)", { | |
type T | |
t = T() | |
t.deep_set(['field1', 'key1'], 'val1').assert(T, 'deep_set should return object of type T') | |
t.assert({"field1": {"key1": "val1"}}) | |
}) | |
test("set two levels on custom type (arr)", { | |
type T | |
t = T() | |
t.deep_set(['field1', 2], 'val1').assert(T, 'deep_set should return object of type T') | |
t.assert({"field1": [null, null, "val1"]}) | |
}) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I guess it's time to try the "discussions" feature of GitHub. Did not have the chance yet.