zuzu-js 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +5 -0
- package/README.md +113 -0
- package/bin/zuzu +17 -0
- package/bin/zuzu-build-browser-bundle +57 -0
- package/bin/zuzu-generate-browser-stdlib +584 -0
- package/bin/zuzu-js +23 -0
- package/bin/zuzu-js-compile +152 -0
- package/bin/zuzu-js-electron +19 -0
- package/dist/zuzu-browser-worker.js +45574 -0
- package/dist/zuzu-browser.js +45362 -0
- package/lib/browser-bundle-entry.js +160 -0
- package/lib/browser-gui-renderer.js +387 -0
- package/lib/browser-runtime.js +167 -0
- package/lib/browser-worker-entry.js +413 -0
- package/lib/browser-ztests/runner.html +103 -0
- package/lib/browser-ztests/runner.js +369 -0
- package/lib/cli.js +350 -0
- package/lib/collections.js +367 -0
- package/lib/compiler.js +303 -0
- package/lib/electron/launcher.js +70 -0
- package/lib/electron/main.js +956 -0
- package/lib/electron/preload.js +80 -0
- package/lib/electron/renderer.html +122 -0
- package/lib/electron/renderer.js +24 -0
- package/lib/execution-metadata.js +18 -0
- package/lib/gui/dom-renderer.js +778 -0
- package/lib/host/browser-host.js +278 -0
- package/lib/host/capabilities.js +47 -0
- package/lib/host/electron-host.js +15 -0
- package/lib/host/node-host.js +74 -0
- package/lib/paths.js +150 -0
- package/lib/runtime-entrypoints.js +60 -0
- package/lib/runtime-helpers.js +886 -0
- package/lib/runtime.js +3529 -0
- package/lib/tap.js +37 -0
- package/lib/transpiler-new/ast.js +23 -0
- package/lib/transpiler-new/codegen.js +2455 -0
- package/lib/transpiler-new/errors.js +28 -0
- package/lib/transpiler-new/index.js +26 -0
- package/lib/transpiler-new/lexer.js +834 -0
- package/lib/transpiler-new/parser.js +2332 -0
- package/lib/transpiler-new/validate-bindings.js +326 -0
- package/lib/transpiler-utils.js +95 -0
- package/lib/transpiler.js +33 -0
- package/lib/zuzu.js +53 -0
- package/modules/javascript.js +193 -0
- package/modules/std/archive.js +603 -0
- package/modules/std/clib.js +338 -0
- package/modules/std/data/csv.js +1331 -0
- package/modules/std/data/json.js +531 -0
- package/modules/std/data/xml.js +441 -0
- package/modules/std/data/yaml.js +256 -0
- package/modules/std/db-worker.js +250 -0
- package/modules/std/db.js +664 -0
- package/modules/std/digest/_hash.js +443 -0
- package/modules/std/digest/md5.js +26 -0
- package/modules/std/digest/sha.js +72 -0
- package/modules/std/eval.js +10 -0
- package/modules/std/gui/objects.js +1519 -0
- package/modules/std/internals.js +571 -0
- package/modules/std/io/socks-worker.js +318 -0
- package/modules/std/io/socks.js +186 -0
- package/modules/std/io.js +475 -0
- package/modules/std/marshal/cbor.js +463 -0
- package/modules/std/marshal/graph.js +1624 -0
- package/modules/std/marshal.js +87 -0
- package/modules/std/math/bignum.js +91 -0
- package/modules/std/math.js +79 -0
- package/modules/std/net/dns.js +306 -0
- package/modules/std/net/http.js +820 -0
- package/modules/std/net/smtp.js +943 -0
- package/modules/std/net/url.js +109 -0
- package/modules/std/proc.js +602 -0
- package/modules/std/secure.js +3724 -0
- package/modules/std/string/base64.js +138 -0
- package/modules/std/string.js +299 -0
- package/modules/std/task.js +914 -0
- package/modules/std/time.js +579 -0
- package/modules/std/tui.js +188 -0
- package/modules/std/worker-thread.js +246 -0
- package/modules/std/worker.js +790 -0
- package/package.json +67 -0
- package/stdlib/modules/javascript.zzm +99 -0
- package/stdlib/modules/perl.zzm +105 -0
- package/stdlib/modules/std/archive.zzm +132 -0
- package/stdlib/modules/std/cache/lru.zzm +174 -0
- package/stdlib/modules/std/clib.zzm +112 -0
- package/stdlib/modules/std/colour.zzm +220 -0
- package/stdlib/modules/std/config.zzm +818 -0
- package/stdlib/modules/std/data/cbor.zzm +497 -0
- package/stdlib/modules/std/data/csv.zzm +285 -0
- package/stdlib/modules/std/data/ini.zzm +472 -0
- package/stdlib/modules/std/data/json/schema/core.zzm +573 -0
- package/stdlib/modules/std/data/json/schema/format.zzm +581 -0
- package/stdlib/modules/std/data/json/schema/model.zzm +255 -0
- package/stdlib/modules/std/data/json/schema/output.zzm +272 -0
- package/stdlib/modules/std/data/json/schema/relative_pointer.zzm +299 -0
- package/stdlib/modules/std/data/json/schema/validation.zzm +1503 -0
- package/stdlib/modules/std/data/json/schema.zzm +306 -0
- package/stdlib/modules/std/data/json.zzm +102 -0
- package/stdlib/modules/std/data/kdl/json.zzm +460 -0
- package/stdlib/modules/std/data/kdl/xml.zzm +387 -0
- package/stdlib/modules/std/data/kdl.zzm +1631 -0
- package/stdlib/modules/std/data/toml.zzm +756 -0
- package/stdlib/modules/std/data/toon.zzm +1017 -0
- package/stdlib/modules/std/data/xml/escape.zzm +156 -0
- package/stdlib/modules/std/data/xml.zzm +276 -0
- package/stdlib/modules/std/data/yaml.zzm +94 -0
- package/stdlib/modules/std/db.zzm +173 -0
- package/stdlib/modules/std/defer.zzm +75 -0
- package/stdlib/modules/std/digest/crc32.zzm +196 -0
- package/stdlib/modules/std/digest/md5.zzm +54 -0
- package/stdlib/modules/std/digest/sha.zzm +83 -0
- package/stdlib/modules/std/dump.zzm +317 -0
- package/stdlib/modules/std/eval.zzm +63 -0
- package/stdlib/modules/std/getopt.zzm +432 -0
- package/stdlib/modules/std/gui/dialogue.zzm +592 -0
- package/stdlib/modules/std/gui/objects.zzm +123 -0
- package/stdlib/modules/std/gui.zzm +1914 -0
- package/stdlib/modules/std/internals.zzm +139 -0
- package/stdlib/modules/std/io/socks.zzm +139 -0
- package/stdlib/modules/std/io.zzm +157 -0
- package/stdlib/modules/std/lingua/en.zzm +347 -0
- package/stdlib/modules/std/log.zzm +169 -0
- package/stdlib/modules/std/mail.zzm +2726 -0
- package/stdlib/modules/std/marshal.zzm +138 -0
- package/stdlib/modules/std/math/bignum.zzm +98 -0
- package/stdlib/modules/std/math/range.zzm +116 -0
- package/stdlib/modules/std/math/roman.zzm +156 -0
- package/stdlib/modules/std/math.zzm +141 -0
- package/stdlib/modules/std/net/dns.zzm +93 -0
- package/stdlib/modules/std/net/http.zzm +278 -0
- package/stdlib/modules/std/net/smtp.zzm +257 -0
- package/stdlib/modules/std/net/url.zzm +69 -0
- package/stdlib/modules/std/path/jsonpointer.zzm +526 -0
- package/stdlib/modules/std/path/kdl.zzm +1003 -0
- package/stdlib/modules/std/path/simple.zzm +520 -0
- package/stdlib/modules/std/path/z/context.zzm +147 -0
- package/stdlib/modules/std/path/z/evaluate.zzm +549 -0
- package/stdlib/modules/std/path/z/functions.zzm +874 -0
- package/stdlib/modules/std/path/z/lexer.zzm +490 -0
- package/stdlib/modules/std/path/z/node.zzm +1455 -0
- package/stdlib/modules/std/path/z/operators.zzm +445 -0
- package/stdlib/modules/std/path/z/parser.zzm +359 -0
- package/stdlib/modules/std/path/z.zzm +403 -0
- package/stdlib/modules/std/path/zz/functions.zzm +828 -0
- package/stdlib/modules/std/path/zz/operators.zzm +1036 -0
- package/stdlib/modules/std/path/zz.zzm +100 -0
- package/stdlib/modules/std/proc.zzm +155 -0
- package/stdlib/modules/std/result.zzm +149 -0
- package/stdlib/modules/std/secure.zzm +606 -0
- package/stdlib/modules/std/string/base64.zzm +66 -0
- package/stdlib/modules/std/string/quoted_printable.zzm +485 -0
- package/stdlib/modules/std/string.zzm +179 -0
- package/stdlib/modules/std/task.zzm +221 -0
- package/stdlib/modules/std/template/z.zzm +531 -0
- package/stdlib/modules/std/template/zz.zzm +62 -0
- package/stdlib/modules/std/time.zzm +188 -0
- package/stdlib/modules/std/tui.zzm +89 -0
- package/stdlib/modules/std/uuid.zzm +223 -0
- package/stdlib/modules/std/web/session.zzm +388 -0
- package/stdlib/modules/std/web/static.zzm +329 -0
- package/stdlib/modules/std/web.zzm +1942 -0
- package/stdlib/modules/std/worker.zzm +202 -0
- package/stdlib/modules/std/zuzuzoo.zzm +3960 -0
- package/stdlib/modules/test/more.zzm +528 -0
- package/stdlib/modules/test/parser.zzm +209 -0
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
=encoding utf8
|
|
2
|
+
|
|
3
|
+
=head1 NAME
|
|
4
|
+
|
|
5
|
+
std/path/z - Pure Zuzu implementation of ZPath selectors.
|
|
6
|
+
|
|
7
|
+
=head1 SYNOPSIS
|
|
8
|
+
|
|
9
|
+
from std/path/z import ZPath;
|
|
10
|
+
from std/time import Time;
|
|
11
|
+
|
|
12
|
+
let data := {
|
|
13
|
+
users: [
|
|
14
|
+
{ name: "Ada", age: 32, updated: new Time() },
|
|
15
|
+
{ name: "Bob", age: 27 },
|
|
16
|
+
],
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
let names := query( data, "/users/*/name" );
|
|
20
|
+
let zp := new ZPath( path: "/users/#0/name" );
|
|
21
|
+
say( zp.first( data, "n/a" ) );
|
|
22
|
+
say( exists( data, "/users/#9/name" ) );
|
|
23
|
+
say( first( data, "/users/#0/updated/@year" ) );
|
|
24
|
+
say( zp.assign_first( data, "Adele" ) );
|
|
25
|
+
|
|
26
|
+
=head1 IMPLEMENTATION SUPPORT
|
|
27
|
+
|
|
28
|
+
This module is supported by all implementations of ZuzuScript.
|
|
29
|
+
|
|
30
|
+
=head1 DESCRIPTION
|
|
31
|
+
|
|
32
|
+
Native (pure-Zuzu) path traversal for structured values.
|
|
33
|
+
|
|
34
|
+
=head1 EXPORTS
|
|
35
|
+
|
|
36
|
+
=head2 Classes
|
|
37
|
+
|
|
38
|
+
=over
|
|
39
|
+
|
|
40
|
+
=item C<< ZPath({ path: String, ast? }) >>
|
|
41
|
+
|
|
42
|
+
Constructs a compiled ZPath selector. Returns: C<ZPath>.
|
|
43
|
+
|
|
44
|
+
=over
|
|
45
|
+
|
|
46
|
+
=item C<< ZPath.use() >>
|
|
47
|
+
|
|
48
|
+
Parameters: none. Returns: C<null>. Makes this path class the lexical
|
|
49
|
+
implementation for C<@>, C<@@>, and C<@?>.
|
|
50
|
+
|
|
51
|
+
=item C<< path.get_evaluator() >>
|
|
52
|
+
|
|
53
|
+
Parameters: none. Returns: C<Evaluator>. Returns the evaluator used for
|
|
54
|
+
this path.
|
|
55
|
+
|
|
56
|
+
=item C<< path.evaluate(raw, meta := {}) >>
|
|
57
|
+
|
|
58
|
+
Parameters: C<raw> is the query root and C<meta> is optional evaluation
|
|
59
|
+
metadata. Returns: C<Array>. Evaluates the path and returns selected
|
|
60
|
+
nodes.
|
|
61
|
+
|
|
62
|
+
=item C<< path.get(raw) >>, C<< path.select(raw) >>, C<< path.query(raw) >>
|
|
63
|
+
|
|
64
|
+
Parameters: C<raw> is the query root. Returns: C<Array>. Evaluates the
|
|
65
|
+
path and returns selected primitive values.
|
|
66
|
+
|
|
67
|
+
=item C<< path.first(raw, fallback?) >>
|
|
68
|
+
|
|
69
|
+
Parameters: C<raw> is the query root and C<fallback> is optional.
|
|
70
|
+
Returns: value. Returns the first selected value or C<fallback>/C<null>.
|
|
71
|
+
|
|
72
|
+
=item C<< path.exists(raw) >>
|
|
73
|
+
|
|
74
|
+
Parameters: C<raw> is the query root. Returns: C<Boolean>. Returns true
|
|
75
|
+
when the path selects at least one value.
|
|
76
|
+
|
|
77
|
+
=item C<< path.assign_first(raw, value, op := ":=", weak := false) >>
|
|
78
|
+
|
|
79
|
+
Parameters: C<raw> is the query root, C<value> is the assignment value,
|
|
80
|
+
C<op> is an assignment operator, and C<weak> requests weak assignment.
|
|
81
|
+
Returns: value. Updates the first selected node or throws if none match.
|
|
82
|
+
|
|
83
|
+
=item C<< path.assign_all(raw, value, op := ":=", weak := false) >>
|
|
84
|
+
|
|
85
|
+
Parameters: same as C<assign_first>. Returns: value. Updates every
|
|
86
|
+
selected node.
|
|
87
|
+
|
|
88
|
+
=item C<< path.assign_maybe(raw, value, op := ":=", weak := false) >>
|
|
89
|
+
|
|
90
|
+
Parameters: same as C<assign_first>. Returns: C<Boolean>. Updates the
|
|
91
|
+
first selected node when one exists.
|
|
92
|
+
|
|
93
|
+
=item C<< path.ref_first(raw) >>
|
|
94
|
+
|
|
95
|
+
Parameters: C<raw> is the query root. Returns: C<Function>. Returns a
|
|
96
|
+
reference-like getter/setter for the first selected node.
|
|
97
|
+
|
|
98
|
+
=item C<< path.ref_all(raw) >>
|
|
99
|
+
|
|
100
|
+
Parameters: C<raw> is the query root. Returns: C<Array>. Returns
|
|
101
|
+
reference-like getter/setters for all selected nodes.
|
|
102
|
+
|
|
103
|
+
=item C<< path.ref_maybe(raw) >>
|
|
104
|
+
|
|
105
|
+
Parameters: C<raw> is the query root. Returns: C<Function> or C<null>.
|
|
106
|
+
Returns a reference-like getter/setter for the first selected node when
|
|
107
|
+
one exists.
|
|
108
|
+
|
|
109
|
+
=back
|
|
110
|
+
|
|
111
|
+
=back
|
|
112
|
+
|
|
113
|
+
=head1 USE WITH PATH OPERATORS
|
|
114
|
+
|
|
115
|
+
The path operators C<@>, C<@@>, and C<@?> can be set to use this module
|
|
116
|
+
in a lexical scope.
|
|
117
|
+
|
|
118
|
+
from std/path/z import ZPath;
|
|
119
|
+
|
|
120
|
+
function find_usernames (data) {
|
|
121
|
+
ZPath.use();
|
|
122
|
+
return data @@ "/users/*/name";
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
However, for repeatedly used paths it may be more efficient to compile the
|
|
126
|
+
path once and use many times:
|
|
127
|
+
|
|
128
|
+
let _usernames_zpath;
|
|
129
|
+
function find_usernames (data) {
|
|
130
|
+
from std/path/z import ZPath;
|
|
131
|
+
_usernames_zpath ?:= new ZPath( path: "/users/*/name" );
|
|
132
|
+
return data @@ _usernames_zpath;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
=head1 SUPPORTED TYPES
|
|
136
|
+
|
|
137
|
+
=over
|
|
138
|
+
|
|
139
|
+
=item B<Null>, B<Boolean>, B<Number>, B<String>, B<BinaryString>, B<Regexp>
|
|
140
|
+
|
|
141
|
+
Treated as terminal nodes. These objects cannot have child objects.
|
|
142
|
+
|
|
143
|
+
=item B<Array>
|
|
144
|
+
|
|
145
|
+
Array items can be indexed by number.
|
|
146
|
+
|
|
147
|
+
=item B<Bag>, B<Set>
|
|
148
|
+
|
|
149
|
+
Items cannot be indexed by number, but can be returned by "*".
|
|
150
|
+
|
|
151
|
+
=item B<Dict>
|
|
152
|
+
|
|
153
|
+
Values are named by their key.
|
|
154
|
+
|
|
155
|
+
=item B<PairList>
|
|
156
|
+
|
|
157
|
+
Pairs can be indexed by number, named by their key, or use a combination of
|
|
158
|
+
both.
|
|
159
|
+
|
|
160
|
+
{{ foo: 11, bar: -1, foo: 22, foo: 33 }}
|
|
161
|
+
|
|
162
|
+
C<< /#2 >> (0-based index) will retrieve C<< foo: 22 >>.
|
|
163
|
+
C<< /foo >> will retrieve C<< foo: 11 >>, C<< foo: 22 >>, and C<< foo: 33 >>.
|
|
164
|
+
C<< /foo#2 >> (0-based index on just values with key "foo") will retrieve C<< foo: 33 >>.
|
|
165
|
+
|
|
166
|
+
Note that rather than just retrieving the value, a Pair object is retrieved.
|
|
167
|
+
The selected Pair exposes C<< @key >> and C<< @value >> attributes. Path
|
|
168
|
+
assignment to a selected Pair, or to its C<< @value >> attribute, replaces
|
|
169
|
+
that pair entry's value while preserving pair order and duplicate keys.
|
|
170
|
+
|
|
171
|
+
=item B<< Pair >>
|
|
172
|
+
|
|
173
|
+
Pair objects do not have child objects but do have C<< @key >> and
|
|
174
|
+
C<< @value >> attributes.
|
|
175
|
+
|
|
176
|
+
let pairlist := {{ foo: 11, bar: -1, foo: 22, foo: 33 }};
|
|
177
|
+
say( first( pairlist, "/#2/@key" ) ); // "foo"
|
|
178
|
+
say( first( pairlist, "/#2/@value" ) ); // 22
|
|
179
|
+
|
|
180
|
+
=item B<< Time >>
|
|
181
|
+
|
|
182
|
+
Time is treated as a terminal node with attributes C<< @year >>,
|
|
183
|
+
C<< @month >>, C<< @day >>, C<< @hour >>, C<< @min >>, and C<< @sec >>.
|
|
184
|
+
|
|
185
|
+
See C<< std/time >>.
|
|
186
|
+
|
|
187
|
+
=item B<< Path >>
|
|
188
|
+
|
|
189
|
+
Paths representing files are treated as terminal nodes with attributes
|
|
190
|
+
corresponding to the values from the C<stat> system call: C<< @dev >>,
|
|
191
|
+
C<< @ino >>, C<< @mode >>, C<< @nlink >>, C<< @uid >>, C<< @gid >>,
|
|
192
|
+
C<< @rdev >>, C<< @size >>, C<< @atime >>, C<< @mtime >>, C<< @ctime >>,
|
|
193
|
+
C<< @blksize >>, and C<< @blocks >>.
|
|
194
|
+
|
|
195
|
+
See C<< std/io >>.
|
|
196
|
+
|
|
197
|
+
=item B<< XMLDocument >>, B<< XMLNode >>, etc.
|
|
198
|
+
|
|
199
|
+
Are treated roughly how the ZPath specification suggests.
|
|
200
|
+
|
|
201
|
+
/html/body/table/tbody/tr // all rows in the tbody
|
|
202
|
+
/html/body/table/tbody/tr#0 // the first row in the tbody
|
|
203
|
+
/html/body/table/tbody/#0 // the child element in the tbody
|
|
204
|
+
/html/body/table[@id] // all tables that have an id attribute
|
|
205
|
+
|
|
206
|
+
See C<< std/data/xml >>.
|
|
207
|
+
|
|
208
|
+
=back
|
|
209
|
+
|
|
210
|
+
=head1 SEE ALSO
|
|
211
|
+
|
|
212
|
+
Specification: L<https://zpath.me>.
|
|
213
|
+
|
|
214
|
+
ZPath specification: L<https://zpath.me>.
|
|
215
|
+
|
|
216
|
+
=head1 COPYRIGHT AND LICENCE
|
|
217
|
+
|
|
218
|
+
B<< std/path/z >> is copyright Toby Inkster.
|
|
219
|
+
|
|
220
|
+
It is free software; you may redistribute it and/or modify it under
|
|
221
|
+
the terms of either the Artistic License 1.0 or the GNU General Public
|
|
222
|
+
License version 2.
|
|
223
|
+
|
|
224
|
+
=cut
|
|
225
|
+
|
|
226
|
+
from std/path/z/parser import Parser;
|
|
227
|
+
from std/path/z/evaluate import Evaluator;
|
|
228
|
+
from std/path/z/context import Ctx;
|
|
229
|
+
|
|
230
|
+
let _cache;
|
|
231
|
+
do {
|
|
232
|
+
from std/cache/lru try import Cache;
|
|
233
|
+
if ( Cache ) {
|
|
234
|
+
_cache := new Cache( capacity: 16 );
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
class ZPath {
|
|
239
|
+
let String path;
|
|
240
|
+
let ast;
|
|
241
|
+
let ev;
|
|
242
|
+
|
|
243
|
+
static method use () {
|
|
244
|
+
from std/internals import setupperprop;
|
|
245
|
+
setupperprop( 1, "paths", self );
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
method __build__ () {
|
|
249
|
+
ev := self.get_evaluator;
|
|
250
|
+
const p := new Parser( allowed_operators: ev.operator_definitions() );
|
|
251
|
+
ast ?:= _cache
|
|
252
|
+
? _cache.get( path, fn x → p.parse_top_level_terms(x) )
|
|
253
|
+
: p.parse_top_level_terms(path);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
method get_evaluator () {
|
|
257
|
+
return new Evaluator();
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
method evaluate ( raw, meta := {} ) {
|
|
261
|
+
|
|
262
|
+
meta.set( "level", 0 ) unless meta.defined( "level" );
|
|
263
|
+
const ctx := new Ctx(
|
|
264
|
+
root: raw,
|
|
265
|
+
nodeset: meta.get( "nodeset", null ),
|
|
266
|
+
parentset: meta.get( "parentset", null ),
|
|
267
|
+
meta: meta,
|
|
268
|
+
);
|
|
269
|
+
|
|
270
|
+
const short_circuit := ( meta.get( "want", "all" ) in [ "first", "exists" ] );
|
|
271
|
+
|
|
272
|
+
let results := [];
|
|
273
|
+
for ( let term in ast ) {
|
|
274
|
+
for ( let node in ev.eval_expr( term, ctx ) ) {
|
|
275
|
+
let next_node := ev.maybe_apply_action( node, ctx );
|
|
276
|
+
results.push(next_node);
|
|
277
|
+
return results if short_circuit;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
return results;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
method get ( raw ) {
|
|
285
|
+
return self.evaluate(raw).map( fn r → r.primitive_value );
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
method select ( raw ) {
|
|
289
|
+
return self.evaluate(raw).map( fn r → r.primitive_value );
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
method query ( raw ) {
|
|
293
|
+
return self.evaluate(raw).map( fn r → r.primitive_value );
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
method first ( raw, fallback? ) {
|
|
297
|
+
let got := self.evaluate( raw, { want: "first" } );
|
|
298
|
+
return got.empty ? fallback : got[0].primitive_value;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
method exists ( raw ) {
|
|
302
|
+
let got := self.evaluate( raw, { want: "exists" } );
|
|
303
|
+
return not got.empty;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
method _apply_assignment_ref ( ref, value, op := ":=", weak := false ) {
|
|
307
|
+
if ( op ≡ ":=" ) {
|
|
308
|
+
return weak ? ref( value, true ) : ref(value);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
let current := ref();
|
|
312
|
+
|
|
313
|
+
if ( op ≡ "+=" ) {
|
|
314
|
+
current += value;
|
|
315
|
+
}
|
|
316
|
+
else if ( op ≡ "-=" ) {
|
|
317
|
+
current -= value;
|
|
318
|
+
}
|
|
319
|
+
else if ( op ≡ "*=" or op ≡ "×=" ) {
|
|
320
|
+
current *= value;
|
|
321
|
+
}
|
|
322
|
+
else if ( op ≡ "/=" or op ≡ "÷=" ) {
|
|
323
|
+
current /= value;
|
|
324
|
+
}
|
|
325
|
+
else if ( op ≡ "**=" ) {
|
|
326
|
+
current **= value;
|
|
327
|
+
}
|
|
328
|
+
else if ( op ≡ "_=" ) {
|
|
329
|
+
current _= value;
|
|
330
|
+
}
|
|
331
|
+
else if ( op ≡ "?:=" ) {
|
|
332
|
+
current ?:= value;
|
|
333
|
+
}
|
|
334
|
+
else if ( op ≡ "~=" ) {
|
|
335
|
+
current ~= value[0] -> value[1](m);
|
|
336
|
+
}
|
|
337
|
+
else {
|
|
338
|
+
die `Unsupported path assignment operator '${op}'`;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
ref(current);
|
|
342
|
+
return current;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
method _assign_all_result ( value, op, last_result ) {
|
|
346
|
+
return op ≡ "~=" ? last_result : value;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
method assign_first ( raw, value, op := ":=", weak := false ) {
|
|
350
|
+
let got := self.evaluate( raw, { want: "first" } );
|
|
351
|
+
die "Path assignment (@) found no matches" if got.empty;
|
|
352
|
+
return self._apply_assignment_ref(
|
|
353
|
+
got[0].ref(),
|
|
354
|
+
value,
|
|
355
|
+
op,
|
|
356
|
+
weak,
|
|
357
|
+
);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
method assign_all ( raw, value, op := ":=", weak := false ) {
|
|
361
|
+
let got := self.evaluate(raw);
|
|
362
|
+
if ( got.empty ) {
|
|
363
|
+
return self._assign_all_result( value, op, value );
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
let last_result := value;
|
|
367
|
+
for ( let node in got ) {
|
|
368
|
+
last_result := self._apply_assignment_ref(
|
|
369
|
+
node.ref(),
|
|
370
|
+
value,
|
|
371
|
+
op,
|
|
372
|
+
weak,
|
|
373
|
+
);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
return self._assign_all_result( value, op, last_result );
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
method assign_maybe ( raw, value, op := ":=", weak := false ) {
|
|
380
|
+
let got := self.evaluate( raw, { want: "first" } );
|
|
381
|
+
if ( got.empty ) {
|
|
382
|
+
return false;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
self._apply_assignment_ref( got[0].ref(), value, op, weak );
|
|
386
|
+
return true;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
method ref_first ( raw ) {
|
|
390
|
+
let got := self.evaluate( raw, { want: "first" } );
|
|
391
|
+
die "Path assignment (@) found no matches" if got.empty;
|
|
392
|
+
return got[0].ref();
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
method ref_all ( raw ) {
|
|
396
|
+
return self.evaluate(raw).map( fn n → n.ref );
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
method ref_maybe ( raw ) {
|
|
400
|
+
let got := self.evaluate( raw, { want: "first" } );
|
|
401
|
+
return got.empty ? null : got[0].ref();
|
|
402
|
+
}
|
|
403
|
+
}
|