3 def childEnv(binds; exprs):
7 dirty_atoms: .dirty_atoms,
8 environment: [binds, exprs] | transpose | (
9 . as $dot | reduce .[] as $item (
10 { value: [], seen: false, name: null, idx: 0 };
11 if $item[1] != null then
14 value: (.value[1:-1] + (.value|last[1].value += [$item[1]])),
19 if $item[0] == "&" then
20 $dot[.idx+1][0] as $name | {
21 value: (.value + [[$name, {kind:"list", value: [$item[1]]}]]),
27 value: (.value + [$item]),
32 end | (.idx |= .idx + 1)
34 if $item[0] == "&" then
35 $dot[.idx+1][0] as $name | {
36 value: (.value + [[$name, {kind:"list", value: []}]]),
43 ) | .value | map({(.[0]): .[1]}) | add
51 dirty_atoms: .dirty_atoms
62 def inform_function(name):
63 (.names += [name]) | (.names |= unique);
65 def inform_function_multi(names):
66 . as $dot | reduce names[] as $name(
68 inform_function($name)
71 def env_multiset(keys; value):
72 (if value.kind == "function" then # multiset not allowed on atoms
73 value | inform_function_multi(keys)
79 .environment + (reduce keys[] as $key(.environment; .[$key] |= value))
82 dirty_atoms: .dirty_atoms
85 def env_multiset(env; keys; value):
86 env | env_multiset(keys; value);
88 def env_set($key; $value):
89 (if $value.kind == "function" or $value.kind == "atom" then
90 # inform the function/atom of its names
92 if $value.kind == "atom" then
93 # check if the one we have is newer
94 env_req(env; key) as $ours |
95 if $ours.last_modified > $value.last_modified then
98 # update modification timestamp
99 $value | .last_modified |= now
103 end) | inform_function($key)
108 environment: (.environment + (.environment | .[$key] |= $value)), # merge together, as .environment[key] |= value does not work
110 dirty_atoms: .dirty_atoms
115 .environment // {} | keys;
116 if . == null then [] else
117 if .parent == null then
120 (.fallback | env_dump_keys)
125 (.parent | env_dump_keys) +
126 (.fallback | env_dump_keys)
132 if env.environment[.] == null then
134 env_find(env.parent) // if env.fallback then env_find(env.fallback) else null end
143 . as $key | $key | env_find(env).environment[$key] as $value |
144 if $value == null then
145 jqmal_error("'\($key)' not found")
147 if $value.kind == "atom" then
148 $value.identity as $id |
149 $key | env_find(env.parent).environment[$key] as $possibly_newer |
150 if $possibly_newer.identity == $id and $possibly_newer.last_modified > $value.last_modified then
160 def env_get(env; key):
163 def env_req(env; key):
164 key as $key | key | env_find(env).environment[$key] as $value |
165 if $value == null then
168 if $value.kind == "atom" then
169 $value.identity as $id |
170 $key | env_find(env.parent).environment[$key] as $possibly_newer |
171 if $possibly_newer.identity == $id and $possibly_newer.last_modified > $value.last_modified then
181 def env_set(env; $key; $value):
182 (if $value.kind == "function" or $value.kind == "atom" then
183 # inform the function/atom of its names
184 $value | (.names += [$key]) | (.names |= unique) |
185 if $value.kind == "atom" then
186 # check if the one we have is newer
187 env_req(env; $key) as $ours |
188 if $ours.last_modified > $value.last_modified then
191 # update modification timestamp
192 $value | .last_modified |= now
201 environment: ((env.environment // jqmal_error("Environment empty in \(env | keys)")) + (env.environment | .[$key] |= $value)), # merge together, as env.environment[key] |= value does not work
202 fallback: env.fallback,
203 dirty_atoms: env.dirty_atoms
206 def env_setfallback(env; fallback):
210 environment: env.environment,
211 dirty_atoms: env.dirty_atoms
220 def addToEnv(env; name; expr):
223 env: env_set(env; name; expr)
234 def wrapEnv(replEnv):
238 isReplEnv: (replEnv == .) # should we allow separate copies?
244 def unwrapCurrentEnv:
247 def env_set6(env; key; value):
248 if env.isReplEnv then
249 env_set(env.currentEnv; key; value) | wrapEnv
251 env_set(env.currentEnv; key; value) | wrapEnv(env.replEnv)
254 def env_set_(env; key; value):
255 if env.currentEnv != null then
256 env_set6(env; key; value)
258 env_set(env; key; value)
261 def addToEnv6(envexp; name):
262 envexp.expr as $value
263 | envexp.env as $rawEnv
264 | (if $rawEnv.isReplEnv then
265 env_set_($rawEnv.currentEnv; name; $value) | wrapEnv
267 env_set_($rawEnv.currentEnv; name; $value) | wrapEnv($rawEnv.replEnv)
274 def addToEnv(envexp; name):
275 if envexp.env.replEnv != null then
276 addToEnv6(envexp; name)
279 env: env_set_(envexp.env; name; envexp.expr)
282 def _env_remove_references(refs):
285 environment: (.environment | to_entries | map(select(.key as $key | refs | contains([$key]) | not)) | from_entries),
286 parent: (.parent | _env_remove_references(refs)),
287 fallback: (.fallback | _env_remove_references(refs)),
288 dirty_atoms: (.dirty_atoms | map(select(. as $dot | refs | contains([$dot]) | not)))
292 def env_remove_references(refs):
294 | if has("replEnv") then
295 .currentEnv |= _env_remove_references(refs)
297 _env_remove_references(refs)
302 env.environment[.] //
306 jqmal_error("'\(.)' not found")