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"]}) | |
}) | |
deep_set(path, null)
mm... absence of an element is different than having it with null
value in NGS.
I guess it's time to try the "discussions" feature of GitHub. Did not have the chance yet.
Moving discussion to ngs-lang/ngs#550
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Somehow I think that anything with
get
should not have side effects. We can maybe adddeep_make()
ordeep_ensure()
or anything of that sort to act likedeep_set()
but without the final step of setting the leaf value.