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,460 @@
|
|
|
1
|
+
=encoding utf8
|
|
2
|
+
|
|
3
|
+
=head1 NAME
|
|
4
|
+
|
|
5
|
+
std/data/kdl/json - JSON-in-KDL structure conversion.
|
|
6
|
+
|
|
7
|
+
=head1 SYNOPSIS
|
|
8
|
+
|
|
9
|
+
from std/data/kdl import KDL;
|
|
10
|
+
from std/data/kdl/json import kdl_to_json, json_to_kdl;
|
|
11
|
+
|
|
12
|
+
let kdl_doc := ( new KDL() ).decode( """- foo=1 bar=#true""" );
|
|
13
|
+
let data := kdl_to_json(kdl_doc);
|
|
14
|
+
let roundtrip := json_to_kdl(data);
|
|
15
|
+
|
|
16
|
+
=head1 IMPLEMENTATION SUPPORT
|
|
17
|
+
|
|
18
|
+
This module is supported by all implementations of ZuzuScript.
|
|
19
|
+
|
|
20
|
+
=head1 DESCRIPTION
|
|
21
|
+
|
|
22
|
+
This module implements the JSON-in-KDL (JiK) mapping for parsed Zuzu
|
|
23
|
+
objects. C<kdl_to_json> accepts a C<KDLDocument> or C<KDLNode> and
|
|
24
|
+
returns native Zuzu data structures. C<json_to_kdl> accepts native
|
|
25
|
+
JSON-like data structures and returns a C<KDLDocument>.
|
|
26
|
+
|
|
27
|
+
C<kdl_to_json(value, pairlists: true)> maps object-like JiK nodes to
|
|
28
|
+
C<PairList> values instead of C<Dict> values, preserving key order and
|
|
29
|
+
duplicate keys.
|
|
30
|
+
|
|
31
|
+
=head1 EXPORTS
|
|
32
|
+
|
|
33
|
+
=head2 Functions
|
|
34
|
+
|
|
35
|
+
=over
|
|
36
|
+
|
|
37
|
+
=item C<< kdl_to_json(value, ... PairList opts) >>
|
|
38
|
+
|
|
39
|
+
Parameters: C<value> is a C<KDLDocument>, C<KDLNode>, or compatible KDL
|
|
40
|
+
value and C<opts> may include C<pairlists>. Returns: value. Converts
|
|
41
|
+
JSON-in-KDL structures into native JSON-like ZuzuScript data.
|
|
42
|
+
|
|
43
|
+
=item C<< json_to_kdl(value) >>
|
|
44
|
+
|
|
45
|
+
Parameters: C<value> is a JSON-like ZuzuScript value. Returns:
|
|
46
|
+
C<KDLDocument>. Converts native JSON-like data into JSON-in-KDL nodes.
|
|
47
|
+
|
|
48
|
+
=back
|
|
49
|
+
|
|
50
|
+
=head1 COPYRIGHT AND LICENCE
|
|
51
|
+
|
|
52
|
+
B<< std/data/kdl/json >> is copyright Toby Inkster.
|
|
53
|
+
|
|
54
|
+
It is free software; you may redistribute it and/or modify it under
|
|
55
|
+
the terms of either the Artistic License 1.0 or the GNU General Public
|
|
56
|
+
License version 2.
|
|
57
|
+
|
|
58
|
+
=cut
|
|
59
|
+
|
|
60
|
+
from std/data/kdl import KDLDocument, KDLNode, KDLValue;
|
|
61
|
+
from std/data/kdl/xml import xml_to_kdl;
|
|
62
|
+
from std/time import Time;
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
function _jik_has_props ( KDLNode node ) {
|
|
66
|
+
return node.props().to_Array().length() > 0;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function _jik_literal_value ( value ) {
|
|
70
|
+
die "JSON-in-KDL literal must be a KDLValue"
|
|
71
|
+
if not( value instanceof KDLValue );
|
|
72
|
+
if ( value.is_number() and value.kind() ≡ "string" ) {
|
|
73
|
+
die "JSON-in-KDL does not support non-finite KDL number keywords";
|
|
74
|
+
}
|
|
75
|
+
return value.native_value();
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function _jik_is_time_native ( value ) {
|
|
79
|
+
return value instanceof Time;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function _jik_pad2 ( value ) {
|
|
83
|
+
let text := "" _ value;
|
|
84
|
+
return length text < 2 ? "0" _ text : text;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function _jik_pad4 ( value ) {
|
|
88
|
+
let text := "" _ value;
|
|
89
|
+
while ( length text < 4 ) {
|
|
90
|
+
text := "0" _ text;
|
|
91
|
+
}
|
|
92
|
+
return text;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function _jik_time_text ( value ) {
|
|
96
|
+
return _jik_pad4( value.year() )
|
|
97
|
+
_ "-" _ _jik_pad2( value.mon() )
|
|
98
|
+
_ "-" _ _jik_pad2( value.day_of_month() )
|
|
99
|
+
_ "T" _ _jik_pad2( value.hour() )
|
|
100
|
+
_ ":" _ _jik_pad2( value.min() )
|
|
101
|
+
_ ":" _ _jik_pad2( value.sec() );
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function _jik_value ( value ) {
|
|
105
|
+
if ( value instanceof KDLValue ) {
|
|
106
|
+
return value;
|
|
107
|
+
}
|
|
108
|
+
if ( value ≡ null ) {
|
|
109
|
+
return new KDLValue( type: "null", value: null );
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if ( value instanceof Boolean ) {
|
|
113
|
+
return new KDLValue( type: "boolean", value: value );
|
|
114
|
+
}
|
|
115
|
+
if ( value instanceof Number ) {
|
|
116
|
+
return new KDLValue( type: "number", kind: "float", value: value );
|
|
117
|
+
}
|
|
118
|
+
if ( value instanceof String or value instanceof BinaryString ) {
|
|
119
|
+
return new KDLValue( type: "string", value: "" _ value );
|
|
120
|
+
}
|
|
121
|
+
if ( _jik_is_time_native(value) ) {
|
|
122
|
+
return new KDLValue(
|
|
123
|
+
type: "string",
|
|
124
|
+
value: _jik_time_text(value),
|
|
125
|
+
type_annotation: "date-time",
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return new KDLValue( type: typeof value, value: value );
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function _jik_is_array_native ( value ) {
|
|
133
|
+
return value instanceof Array or value instanceof Set or value instanceof Bag;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function _jik_is_object_native ( value ) {
|
|
137
|
+
return value instanceof Dict or value instanceof PairList;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function _jik_is_kdl_native ( value ) {
|
|
141
|
+
return value instanceof KDLDocument or value instanceof KDLNode;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function _jik_is_xml_native ( value ) {
|
|
145
|
+
try {
|
|
146
|
+
if ( value can nodeType ) {
|
|
147
|
+
return true if value.nodeType() ≢ null;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
try {
|
|
154
|
+
return false if not( value can documentElement );
|
|
155
|
+
value.documentElement();
|
|
156
|
+
return true;
|
|
157
|
+
}
|
|
158
|
+
catch {
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function _jik_is_opaque_literal_native ( value ) {
|
|
165
|
+
return not _jik_is_array_native(value)
|
|
166
|
+
and not _jik_is_object_native(value)
|
|
167
|
+
and not _jik_is_kdl_native(value)
|
|
168
|
+
and not _jik_is_xml_native(value);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function _jik_is_literal_native ( value ) {
|
|
172
|
+
return value ≡ null
|
|
173
|
+
or value instanceof Boolean
|
|
174
|
+
or value instanceof Number
|
|
175
|
+
or value instanceof String
|
|
176
|
+
or value instanceof BinaryString
|
|
177
|
+
or _jik_is_time_native(value)
|
|
178
|
+
or value instanceof KDLValue
|
|
179
|
+
or _jik_is_opaque_literal_native(value);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function _jik_sorted_array ( value ) {
|
|
183
|
+
if ( value instanceof Set or value instanceof Bag ) {
|
|
184
|
+
return value.sortstr();
|
|
185
|
+
}
|
|
186
|
+
return value;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function _jik_pairs ( obj ) {
|
|
190
|
+
let out := [];
|
|
191
|
+
if ( obj instanceof PairList ) {
|
|
192
|
+
for ( let p in obj.to_Array() ) {
|
|
193
|
+
out.push( p{pair} );
|
|
194
|
+
}
|
|
195
|
+
return out;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
for ( let key in obj.sorted_keys() ) {
|
|
199
|
+
out.push( [ key, obj.get(key) ] );
|
|
200
|
+
}
|
|
201
|
+
return out;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function _jik_native_to_node;
|
|
205
|
+
function _jik_native_to_nodes;
|
|
206
|
+
|
|
207
|
+
function _jik_xml_nodes ( value ) {
|
|
208
|
+
return xml_to_kdl(value).nodes();
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function _jik_kdl_nodes ( value ) {
|
|
212
|
+
if ( value instanceof KDLDocument ) {
|
|
213
|
+
return value.nodes();
|
|
214
|
+
}
|
|
215
|
+
return [ value ];
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function _jik_structural_nodes ( value, String name := "-" ) {
|
|
219
|
+
let nodes := _jik_is_kdl_native(value)
|
|
220
|
+
? _jik_kdl_nodes(value)
|
|
221
|
+
: _jik_xml_nodes(value);
|
|
222
|
+
|
|
223
|
+
if ( name ≡ "-" ) {
|
|
224
|
+
return nodes.length() = 0 ? [ new KDLNode( name: name ) ] : nodes;
|
|
225
|
+
}
|
|
226
|
+
return [ new KDLNode( name: name, children: nodes ) ];
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function _jik_make_array_node ( value, String name := "-" ) {
|
|
230
|
+
let items := _jik_sorted_array(value);
|
|
231
|
+
let all_literals := true;
|
|
232
|
+
for ( let item in items ) {
|
|
233
|
+
all_literals := false unless _jik_is_literal_native(item);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
let annotate := items.length() < 2;
|
|
237
|
+
if ( all_literals ) {
|
|
238
|
+
return new KDLNode(
|
|
239
|
+
name: name,
|
|
240
|
+
type_annotation: annotate ? "array" : null,
|
|
241
|
+
args: items.map( fn item -> _jik_value(item) ),
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
let children := [];
|
|
246
|
+
for ( let item in items ) {
|
|
247
|
+
for ( let child in _jik_native_to_nodes( item, "-" ) ) {
|
|
248
|
+
children.push(child);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
return new KDLNode(
|
|
253
|
+
name: name,
|
|
254
|
+
type_annotation: annotate ? "array" : null,
|
|
255
|
+
children: children,
|
|
256
|
+
);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
function _jik_object_needs_annotation ( Array pairs, Boolean pairlist ) {
|
|
260
|
+
if ( pairs.length() = 0 ) {
|
|
261
|
+
return true;
|
|
262
|
+
}
|
|
263
|
+
if ( pairlist ) {
|
|
264
|
+
return pairs.all( fn pair -> pair[0] ≡ "-" );
|
|
265
|
+
}
|
|
266
|
+
return pairs.length() = 1 and pairs[0][0] ≡ "-"
|
|
267
|
+
and not _jik_is_literal_native( pairs[0][1] );
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
function _jik_make_object_node ( value, String name := "-" ) {
|
|
271
|
+
let pairs := _jik_pairs(value);
|
|
272
|
+
let pairlist := value instanceof PairList;
|
|
273
|
+
let props := new PairList();
|
|
274
|
+
let children := [];
|
|
275
|
+
|
|
276
|
+
if ( pairlist ) {
|
|
277
|
+
for ( let pair in pairs ) {
|
|
278
|
+
for ( let child in _jik_native_to_nodes( pair[1], pair[0] ) ) {
|
|
279
|
+
children.push(child);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
else {
|
|
284
|
+
for ( let pair in pairs ) {
|
|
285
|
+
if ( _jik_is_literal_native( pair[1] ) ) {
|
|
286
|
+
props.add( pair[0], _jik_value( pair[1] ) );
|
|
287
|
+
}
|
|
288
|
+
else {
|
|
289
|
+
for ( let child in _jik_native_to_nodes( pair[1], pair[0] ) ) {
|
|
290
|
+
children.push(child);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
return new KDLNode(
|
|
297
|
+
name: name,
|
|
298
|
+
type_annotation: _jik_object_needs_annotation( pairs, pairlist )
|
|
299
|
+
? "object"
|
|
300
|
+
: null,
|
|
301
|
+
props: props,
|
|
302
|
+
children: children,
|
|
303
|
+
);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
function _jik_native_to_node ( value, String name := "-" ) {
|
|
307
|
+
if ( _jik_is_literal_native(value) ) {
|
|
308
|
+
return new KDLNode( name: name, args: [ _jik_value(value) ] );
|
|
309
|
+
}
|
|
310
|
+
if ( _jik_is_array_native(value) ) {
|
|
311
|
+
return _jik_make_array_node( value, name );
|
|
312
|
+
}
|
|
313
|
+
if ( _jik_is_object_native(value) ) {
|
|
314
|
+
return _jik_make_object_node( value, name );
|
|
315
|
+
}
|
|
316
|
+
if ( _jik_is_kdl_native(value) or _jik_is_xml_native(value) ) {
|
|
317
|
+
let nodes := _jik_structural_nodes( value, name );
|
|
318
|
+
return nodes.length() = 1 ? nodes[0] : new KDLNode(
|
|
319
|
+
name: name,
|
|
320
|
+
children: nodes,
|
|
321
|
+
);
|
|
322
|
+
}
|
|
323
|
+
die `Cannot convert ${typeof value} to JSON-in-KDL`;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
function _jik_native_to_nodes ( value, String name := "-" ) {
|
|
327
|
+
if ( _jik_is_kdl_native(value) or _jik_is_xml_native(value) ) {
|
|
328
|
+
return _jik_structural_nodes( value, name );
|
|
329
|
+
}
|
|
330
|
+
return [ _jik_native_to_node( value, name ) ];
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
function _jik_node_has_only_dash_children ( KDLNode node ) {
|
|
334
|
+
return node.children().all( fn child -> child.name() ≡ "-" );
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
function _jik_node_kind ( KDLNode node ) {
|
|
338
|
+
let annotation := node.type_annotation();
|
|
339
|
+
if ( annotation ≡ "array" or annotation ≡ "object" ) {
|
|
340
|
+
return annotation;
|
|
341
|
+
}
|
|
342
|
+
if ( _jik_has_props(node) ) {
|
|
343
|
+
return "object";
|
|
344
|
+
}
|
|
345
|
+
if ( node.children().length() > 0 ) {
|
|
346
|
+
if ( _jik_node_has_only_dash_children(node) ) {
|
|
347
|
+
return "array";
|
|
348
|
+
}
|
|
349
|
+
return "object";
|
|
350
|
+
}
|
|
351
|
+
if ( node.args().length() = 1 ) {
|
|
352
|
+
return "literal";
|
|
353
|
+
}
|
|
354
|
+
if ( node.args().length() > 1 ) {
|
|
355
|
+
return "array";
|
|
356
|
+
}
|
|
357
|
+
die "Empty JSON-in-KDL node must be annotated as array or object";
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
function _jik_node_to_native;
|
|
361
|
+
|
|
362
|
+
function _jik_array_from_node ( KDLNode node, PairList opts ) {
|
|
363
|
+
die "JSON-in-KDL array node cannot contain properties"
|
|
364
|
+
if _jik_has_props(node);
|
|
365
|
+
die "Empty JSON-in-KDL array node must be annotated as array"
|
|
366
|
+
if node.args().length() = 0
|
|
367
|
+
and node.children().length() = 0
|
|
368
|
+
and node.type_annotation() ≢ "array";
|
|
369
|
+
die "JSON-in-KDL array child nodes must be named '-'"
|
|
370
|
+
unless _jik_node_has_only_dash_children(node);
|
|
371
|
+
|
|
372
|
+
let out := [];
|
|
373
|
+
for ( let arg in node.args() ) {
|
|
374
|
+
out.push( _jik_literal_value(arg) );
|
|
375
|
+
}
|
|
376
|
+
for ( let child in node.children() ) {
|
|
377
|
+
out.push( _jik_node_to_native( child, opts ) );
|
|
378
|
+
}
|
|
379
|
+
return out;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
function _jik_store_object_item ( obj, String key, value, Boolean pairlists ) {
|
|
383
|
+
if ( pairlists ) {
|
|
384
|
+
obj.add( key, value );
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
die `Duplicate JSON-in-KDL object key '${key}'` if obj.exists(key);
|
|
388
|
+
obj.set( key, value );
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
function _jik_object_from_node ( KDLNode node, PairList opts ) {
|
|
392
|
+
die "JSON-in-KDL object node cannot contain unnamed arguments"
|
|
393
|
+
if node.args().length() > 0;
|
|
394
|
+
die "Empty JSON-in-KDL object node must be annotated as object"
|
|
395
|
+
if not _jik_has_props(node)
|
|
396
|
+
and node.children().length() = 0
|
|
397
|
+
and node.type_annotation() ≢ "object";
|
|
398
|
+
|
|
399
|
+
let pairlists := opts.get( "pairlists", false );
|
|
400
|
+
let out := pairlists ? new PairList() : {};
|
|
401
|
+
|
|
402
|
+
for ( let pair in node.props().to_Array() ) {
|
|
403
|
+
let kv := pair{pair};
|
|
404
|
+
_jik_store_object_item(
|
|
405
|
+
out,
|
|
406
|
+
kv[0],
|
|
407
|
+
_jik_literal_value( kv[1] ),
|
|
408
|
+
pairlists,
|
|
409
|
+
);
|
|
410
|
+
}
|
|
411
|
+
for ( let child in node.children() ) {
|
|
412
|
+
_jik_store_object_item(
|
|
413
|
+
out,
|
|
414
|
+
child.name(),
|
|
415
|
+
_jik_node_to_native( child, opts ),
|
|
416
|
+
pairlists,
|
|
417
|
+
);
|
|
418
|
+
}
|
|
419
|
+
return out;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
function _jik_node_to_native ( KDLNode node, PairList opts ) {
|
|
423
|
+
let kind := _jik_node_kind(node);
|
|
424
|
+
if ( kind ≡ "literal" ) {
|
|
425
|
+
die "JSON-in-KDL literal node must contain one argument only"
|
|
426
|
+
if node.args().length() ≢ 1
|
|
427
|
+
or _jik_has_props(node)
|
|
428
|
+
or node.children().length() > 0;
|
|
429
|
+
return _jik_literal_value( node.args()[0] );
|
|
430
|
+
}
|
|
431
|
+
if ( kind ≡ "array" ) {
|
|
432
|
+
return _jik_array_from_node( node, opts );
|
|
433
|
+
}
|
|
434
|
+
if ( kind ≡ "object" ) {
|
|
435
|
+
return _jik_object_from_node( node, opts );
|
|
436
|
+
}
|
|
437
|
+
die `Unknown JSON-in-KDL node kind '${kind}'`;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
function kdl_to_json ( value, ... PairList opts ) {
|
|
441
|
+
if ( value instanceof KDLNode ) {
|
|
442
|
+
return _jik_node_to_native( value, opts );
|
|
443
|
+
}
|
|
444
|
+
if ( value instanceof KDLDocument ) {
|
|
445
|
+
die "JSON-in-KDL document must contain exactly one top-level node"
|
|
446
|
+
if value.nodes().length() ≢ 1;
|
|
447
|
+
return _jik_node_to_native( value.nodes()[0], opts );
|
|
448
|
+
}
|
|
449
|
+
die "kdl_to_json expects a KDLDocument or KDLNode";
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
function json_to_kdl ( value ) {
|
|
453
|
+
if ( value instanceof KDLDocument ) {
|
|
454
|
+
return value;
|
|
455
|
+
}
|
|
456
|
+
if ( value instanceof KDLNode ) {
|
|
457
|
+
return value;
|
|
458
|
+
}
|
|
459
|
+
return new KDLDocument( nodes: [ _jik_native_to_node(value) ] );
|
|
460
|
+
}
|