@silverbulletmd/silverbullet 2.5.3 → 2.6.1
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/README.md +4 -5
- package/client/asset_bundle/bundle.ts +3 -9
- package/client/data/datastore.ts +4 -5
- package/client/markdown_parser/constants.ts +3 -2
- package/client/plugos/hooks/code_widget.ts +3 -5
- package/client/plugos/hooks/command.ts +8 -8
- package/client/plugos/hooks/document_editor.ts +10 -12
- package/client/plugos/hooks/event.ts +33 -36
- package/client/plugos/hooks/mq.ts +17 -17
- package/client/plugos/hooks/plug_namespace.ts +3 -5
- package/client/plugos/hooks/slash_command.ts +12 -27
- package/client/plugos/hooks/syscall.ts +3 -3
- package/client/plugos/manifest_cache.ts +22 -15
- package/client/plugos/plug.ts +2 -5
- package/client/plugos/plug_compile.ts +67 -65
- package/client/plugos/protocol.ts +28 -28
- package/client/plugos/proxy_fetch.ts +7 -6
- package/client/plugos/sandboxes/worker_sandbox.ts +16 -15
- package/client/plugos/syscalls/asset.ts +1 -3
- package/client/plugos/syscalls/code_widget.ts +1 -3
- package/client/plugos/syscalls/config.ts +1 -5
- package/client/plugos/syscalls/datastore.ts +1 -1
- package/client/plugos/syscalls/editor.ts +63 -60
- package/client/plugos/syscalls/event.ts +9 -12
- package/client/plugos/syscalls/fetch.ts +30 -22
- package/client/plugos/syscalls/index.ts +10 -1
- package/client/plugos/syscalls/jsonschema.ts +72 -32
- package/client/plugos/syscalls/language.ts +9 -5
- package/client/plugos/syscalls/markdown.ts +29 -7
- package/client/plugos/syscalls/mq.ts +3 -11
- package/client/plugos/syscalls/service_registry.ts +1 -4
- package/client/plugos/syscalls/shell.ts +2 -5
- package/client/plugos/syscalls/sync.ts +69 -60
- package/client/plugos/syscalls/system.ts +2 -3
- package/client/plugos/system.ts +4 -10
- package/client/plugos/worker_runtime.ts +4 -3
- package/client/space_lua/aggregates.ts +632 -59
- package/client/space_lua/ast.ts +21 -9
- package/client/space_lua/ast_narrow.ts +4 -2
- package/client/space_lua/eval.ts +842 -536
- package/client/space_lua/labels.ts +6 -11
- package/client/space_lua/liq_null.ts +6 -0
- package/client/space_lua/numeric.ts +5 -8
- package/client/space_lua/parse.ts +290 -169
- package/client/space_lua/query_collection.ts +213 -149
- package/client/space_lua/render_lua_markdown.ts +369 -0
- package/client/space_lua/rp.ts +5 -4
- package/client/space_lua/runtime.ts +245 -142
- package/client/space_lua/stdlib/format.ts +34 -20
- package/client/space_lua/stdlib/js.ts +3 -7
- package/client/space_lua/stdlib/load.ts +1 -3
- package/client/space_lua/stdlib/math.ts +15 -14
- package/client/space_lua/stdlib/net.ts +25 -15
- package/client/space_lua/stdlib/os.ts +76 -85
- package/client/space_lua/stdlib/pattern.ts +28 -35
- package/client/space_lua/stdlib/prng.ts +15 -12
- package/client/space_lua/stdlib/space_lua.ts +16 -17
- package/client/space_lua/stdlib/string.ts +7 -17
- package/client/space_lua/stdlib/string_pack.ts +23 -19
- package/client/space_lua/stdlib/table.ts +5 -9
- package/client/space_lua/stdlib.ts +20 -30
- package/client/space_lua/tonumber.ts +79 -40
- package/client/space_lua/util.ts +14 -10
- package/dist/plug-compile.js +44 -41
- package/package.json +24 -22
- package/plug-api/lib/async.ts +19 -6
- package/plug-api/lib/crypto.ts +5 -6
- package/plug-api/lib/dates.ts +15 -7
- package/plug-api/lib/json.ts +10 -4
- package/plug-api/lib/ref.ts +18 -18
- package/plug-api/lib/resolve.ts +7 -11
- package/plug-api/lib/tags.ts +13 -4
- package/plug-api/lib/transclusion.ts +6 -17
- package/plug-api/lib/tree.ts +115 -43
- package/plug-api/lib/yaml.ts +25 -15
- package/plug-api/syscalls/asset.ts +1 -1
- package/plug-api/syscalls/config.ts +1 -4
- package/plug-api/syscalls/editor.ts +14 -14
- package/plug-api/syscalls/jsonschema.ts +1 -3
- package/plug-api/syscalls/lua.ts +3 -9
- package/plug-api/syscalls/mq.ts +1 -4
- package/plug-api/syscalls/shell.ts +4 -1
- package/plug-api/syscalls/space.ts +3 -10
- package/plug-api/syscalls/system.ts +1 -4
- package/plug-api/syscalls/yaml.ts +2 -6
- package/plug-api/types/client.ts +16 -1
- package/plug-api/types/event.ts +6 -4
- package/plug-api/types/manifest.ts +8 -9
- package/plugs/builtin_plugs.ts +2 -2
- package/dist/worker_runtime_bundle.js +0 -233
|
@@ -36,7 +36,7 @@ const luaStyleTags = styleTags({
|
|
|
36
36
|
CompareOp: t.operator,
|
|
37
37
|
"true false": t.bool,
|
|
38
38
|
Comment: t.lineComment,
|
|
39
|
-
"return break goto do end while repeat until function local if then else elseif in for nil or and not query from where limit select order by desc asc nulls first last group having filter using":
|
|
39
|
+
"return break goto do end while repeat until function local if then else elseif in for nil or and not query from where limit offset select order by desc asc nulls first last group having filter using":
|
|
40
40
|
t.keyword,
|
|
41
41
|
});
|
|
42
42
|
|
|
@@ -52,10 +52,7 @@ const customIndent = indentNodeProp.add({
|
|
|
52
52
|
export const luaLanguage = LRLanguage.define({
|
|
53
53
|
name: "space-lua",
|
|
54
54
|
parser: parser.configure({
|
|
55
|
-
props: [
|
|
56
|
-
luaStyleTags,
|
|
57
|
-
customIndent,
|
|
58
|
-
],
|
|
55
|
+
props: [luaStyleTags, customIndent],
|
|
59
56
|
}),
|
|
60
57
|
languageData: {
|
|
61
58
|
commentTokens: { line: "--", block: { open: "--[[", close: "--]]" } },
|
|
@@ -97,8 +94,9 @@ function expressionHasFunctionDef(e: LuaExpression): boolean {
|
|
|
97
94
|
}
|
|
98
95
|
return false;
|
|
99
96
|
case "Binary":
|
|
100
|
-
return
|
|
101
|
-
expressionHasFunctionDef(e.right)
|
|
97
|
+
return (
|
|
98
|
+
expressionHasFunctionDef(e.left) || expressionHasFunctionDef(e.right)
|
|
99
|
+
);
|
|
102
100
|
case "Unary":
|
|
103
101
|
return expressionHasFunctionDef(e.argument);
|
|
104
102
|
case "Parenthesized":
|
|
@@ -119,8 +117,9 @@ function expressionHasFunctionDef(e: LuaExpression): boolean {
|
|
|
119
117
|
}
|
|
120
118
|
return false;
|
|
121
119
|
case "TableAccess":
|
|
122
|
-
return
|
|
123
|
-
expressionHasFunctionDef(e.key)
|
|
120
|
+
return (
|
|
121
|
+
expressionHasFunctionDef(e.object) || expressionHasFunctionDef(e.key)
|
|
122
|
+
);
|
|
124
123
|
case "PropertyAccess":
|
|
125
124
|
return expressionHasFunctionDef(e.object);
|
|
126
125
|
case "Query":
|
|
@@ -128,10 +127,22 @@ function expressionHasFunctionDef(e: LuaExpression): boolean {
|
|
|
128
127
|
const c = e.clauses[i];
|
|
129
128
|
switch (c.type) {
|
|
130
129
|
case "From":
|
|
131
|
-
|
|
130
|
+
case "Select":
|
|
131
|
+
case "GroupBy":
|
|
132
|
+
for (const f of c.fields) {
|
|
133
|
+
switch (f.type) {
|
|
134
|
+
case "DynamicField":
|
|
135
|
+
if (expressionHasFunctionDef(f.key)) return true;
|
|
136
|
+
if (expressionHasFunctionDef(f.value)) return true;
|
|
137
|
+
break;
|
|
138
|
+
case "PropField":
|
|
139
|
+
case "ExpressionField":
|
|
140
|
+
if (expressionHasFunctionDef(f.value)) return true;
|
|
141
|
+
break;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
132
144
|
break;
|
|
133
145
|
case "Where":
|
|
134
|
-
case "Select":
|
|
135
146
|
case "Having":
|
|
136
147
|
if (expressionHasFunctionDef(c.expression)) return true;
|
|
137
148
|
break;
|
|
@@ -145,24 +156,28 @@ function expressionHasFunctionDef(e: LuaExpression): boolean {
|
|
|
145
156
|
return true;
|
|
146
157
|
}
|
|
147
158
|
if (
|
|
148
|
-
c.orderBy[j].using &&
|
|
159
|
+
c.orderBy[j].using &&
|
|
160
|
+
typeof c.orderBy[j].using !== "string"
|
|
149
161
|
) {
|
|
150
162
|
return true;
|
|
151
163
|
}
|
|
152
164
|
}
|
|
153
165
|
break;
|
|
154
|
-
case "GroupBy":
|
|
155
|
-
for (let j = 0; j < c.expressions.length; j++) {
|
|
156
|
-
if (expressionHasFunctionDef(c.expressions[j])) return true;
|
|
157
|
-
}
|
|
158
|
-
break;
|
|
159
166
|
}
|
|
160
167
|
}
|
|
161
168
|
return false;
|
|
162
169
|
case "FilteredCall":
|
|
163
170
|
return (
|
|
164
|
-
expressionHasFunctionDef(e.call) ||
|
|
165
|
-
|
|
171
|
+
expressionHasFunctionDef(e.call) || expressionHasFunctionDef(e.filter)
|
|
172
|
+
);
|
|
173
|
+
case "AggregateCall":
|
|
174
|
+
return (
|
|
175
|
+
expressionHasFunctionDef((e as any).call) ||
|
|
176
|
+
((e as any).orderBy as LuaOrderBy[]).some(
|
|
177
|
+
(ob) =>
|
|
178
|
+
expressionHasFunctionDef(ob.expression) ||
|
|
179
|
+
(ob.using && typeof ob.using !== "string"),
|
|
180
|
+
)
|
|
166
181
|
);
|
|
167
182
|
default:
|
|
168
183
|
return false;
|
|
@@ -187,8 +202,10 @@ function exprReferencesNames(e: LuaExpression, names: Set<string>): boolean {
|
|
|
187
202
|
case "Variable":
|
|
188
203
|
return names.has(e.name);
|
|
189
204
|
case "Binary":
|
|
190
|
-
return
|
|
191
|
-
exprReferencesNames(e.
|
|
205
|
+
return (
|
|
206
|
+
exprReferencesNames(e.left, names) ||
|
|
207
|
+
exprReferencesNames(e.right, names)
|
|
208
|
+
);
|
|
192
209
|
case "Unary":
|
|
193
210
|
return exprReferencesNames(e.argument, names);
|
|
194
211
|
case "Parenthesized":
|
|
@@ -200,8 +217,10 @@ function exprReferencesNames(e: LuaExpression, names: Set<string>): boolean {
|
|
|
200
217
|
}
|
|
201
218
|
return false;
|
|
202
219
|
case "TableAccess":
|
|
203
|
-
return
|
|
204
|
-
exprReferencesNames(e.
|
|
220
|
+
return (
|
|
221
|
+
exprReferencesNames(e.object, names) ||
|
|
222
|
+
exprReferencesNames(e.key, names)
|
|
223
|
+
);
|
|
205
224
|
case "PropertyAccess":
|
|
206
225
|
return exprReferencesNames(e.object, names);
|
|
207
226
|
case "TableConstructor":
|
|
@@ -226,10 +245,22 @@ function exprReferencesNames(e: LuaExpression, names: Set<string>): boolean {
|
|
|
226
245
|
const c = e.clauses[i];
|
|
227
246
|
switch (c.type) {
|
|
228
247
|
case "From":
|
|
229
|
-
|
|
248
|
+
case "Select":
|
|
249
|
+
case "GroupBy":
|
|
250
|
+
for (const f of c.fields) {
|
|
251
|
+
switch (f.type) {
|
|
252
|
+
case "DynamicField":
|
|
253
|
+
if (exprReferencesNames(f.key, names)) return true;
|
|
254
|
+
if (exprReferencesNames(f.value, names)) return true;
|
|
255
|
+
break;
|
|
256
|
+
case "PropField":
|
|
257
|
+
case "ExpressionField":
|
|
258
|
+
if (exprReferencesNames(f.value, names)) return true;
|
|
259
|
+
break;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
230
262
|
break;
|
|
231
263
|
case "Where":
|
|
232
|
-
case "Select":
|
|
233
264
|
case "Having":
|
|
234
265
|
if (exprReferencesNames(c.expression, names)) return true;
|
|
235
266
|
break;
|
|
@@ -250,11 +281,6 @@ function exprReferencesNames(e: LuaExpression, names: Set<string>): boolean {
|
|
|
250
281
|
}
|
|
251
282
|
}
|
|
252
283
|
break;
|
|
253
|
-
case "GroupBy":
|
|
254
|
-
for (let j = 0; j < c.expressions.length; j++) {
|
|
255
|
-
if (exprReferencesNames(c.expressions[j], names)) return true;
|
|
256
|
-
}
|
|
257
|
-
break;
|
|
258
284
|
}
|
|
259
285
|
}
|
|
260
286
|
return false;
|
|
@@ -263,6 +289,15 @@ function exprReferencesNames(e: LuaExpression, names: Set<string>): boolean {
|
|
|
263
289
|
exprReferencesNames(e.call, names) ||
|
|
264
290
|
exprReferencesNames(e.filter, names)
|
|
265
291
|
);
|
|
292
|
+
case "AggregateCall": {
|
|
293
|
+
const ac = e as any;
|
|
294
|
+
if (exprReferencesNames(ac.call, names)) return true;
|
|
295
|
+
for (const ob of ac.orderBy as LuaOrderBy[]) {
|
|
296
|
+
if (exprReferencesNames(ob.expression, names)) return true;
|
|
297
|
+
if (typeof ob.using === "string" && names.has(ob.using)) return true;
|
|
298
|
+
}
|
|
299
|
+
return false;
|
|
300
|
+
}
|
|
266
301
|
default:
|
|
267
302
|
return false;
|
|
268
303
|
}
|
|
@@ -275,8 +310,10 @@ function lvalueReferencesNames(lv: LuaLValue, names: Set<string>): boolean {
|
|
|
275
310
|
case "PropertyAccess":
|
|
276
311
|
return exprReferencesNames(lv.object as LuaExpression, names);
|
|
277
312
|
case "TableAccess":
|
|
278
|
-
return
|
|
279
|
-
exprReferencesNames(lv.
|
|
313
|
+
return (
|
|
314
|
+
exprReferencesNames(lv.object as LuaExpression, names) ||
|
|
315
|
+
exprReferencesNames(lv.key, names)
|
|
316
|
+
);
|
|
280
317
|
}
|
|
281
318
|
}
|
|
282
319
|
|
|
@@ -409,10 +446,7 @@ function blockCapturesNames(block: LuaBlock, names: Set<string>): boolean {
|
|
|
409
446
|
return false;
|
|
410
447
|
}
|
|
411
448
|
|
|
412
|
-
function statementCapturesNames(
|
|
413
|
-
s: LuaStatement,
|
|
414
|
-
names: Set<string>,
|
|
415
|
-
): boolean {
|
|
449
|
+
function statementCapturesNames(s: LuaStatement, names: Set<string>): boolean {
|
|
416
450
|
switch (s.type) {
|
|
417
451
|
case "Local": {
|
|
418
452
|
const exprs = (s as any).expressions as LuaExpression[] | undefined;
|
|
@@ -505,8 +539,9 @@ function exprCapturesNames(e: LuaExpression, names: Set<string>): boolean {
|
|
|
505
539
|
case "FunctionDefinition":
|
|
506
540
|
return functionBodyCapturesNames(e.body, names);
|
|
507
541
|
case "Binary":
|
|
508
|
-
return
|
|
509
|
-
exprCapturesNames(e.right, names)
|
|
542
|
+
return (
|
|
543
|
+
exprCapturesNames(e.left, names) || exprCapturesNames(e.right, names)
|
|
544
|
+
);
|
|
510
545
|
case "Unary":
|
|
511
546
|
return exprCapturesNames(e.argument, names);
|
|
512
547
|
case "Parenthesized":
|
|
@@ -518,8 +553,9 @@ function exprCapturesNames(e: LuaExpression, names: Set<string>): boolean {
|
|
|
518
553
|
}
|
|
519
554
|
return false;
|
|
520
555
|
case "TableAccess":
|
|
521
|
-
return
|
|
522
|
-
exprCapturesNames(e.key, names)
|
|
556
|
+
return (
|
|
557
|
+
exprCapturesNames(e.object, names) || exprCapturesNames(e.key, names)
|
|
558
|
+
);
|
|
523
559
|
case "PropertyAccess":
|
|
524
560
|
return exprCapturesNames(e.object, names);
|
|
525
561
|
case "TableConstructor":
|
|
@@ -542,10 +578,22 @@ function exprCapturesNames(e: LuaExpression, names: Set<string>): boolean {
|
|
|
542
578
|
const c = e.clauses[i];
|
|
543
579
|
switch (c.type) {
|
|
544
580
|
case "From":
|
|
545
|
-
|
|
581
|
+
case "Select":
|
|
582
|
+
case "GroupBy":
|
|
583
|
+
for (const f of c.fields) {
|
|
584
|
+
switch (f.type) {
|
|
585
|
+
case "DynamicField":
|
|
586
|
+
if (exprCapturesNames(f.key, names)) return true;
|
|
587
|
+
if (exprCapturesNames(f.value, names)) return true;
|
|
588
|
+
break;
|
|
589
|
+
case "PropField":
|
|
590
|
+
case "ExpressionField":
|
|
591
|
+
if (exprCapturesNames(f.value, names)) return true;
|
|
592
|
+
break;
|
|
593
|
+
}
|
|
594
|
+
}
|
|
546
595
|
break;
|
|
547
596
|
case "Where":
|
|
548
|
-
case "Select":
|
|
549
597
|
case "Having":
|
|
550
598
|
if (exprCapturesNames(c.expression, names)) return true;
|
|
551
599
|
break;
|
|
@@ -564,19 +612,25 @@ function exprCapturesNames(e: LuaExpression, names: Set<string>): boolean {
|
|
|
564
612
|
}
|
|
565
613
|
}
|
|
566
614
|
break;
|
|
567
|
-
case "GroupBy":
|
|
568
|
-
for (let j = 0; j < c.expressions.length; j++) {
|
|
569
|
-
if (exprCapturesNames(c.expressions[j], names)) return true;
|
|
570
|
-
}
|
|
571
|
-
break;
|
|
572
615
|
}
|
|
573
616
|
}
|
|
574
617
|
return false;
|
|
575
618
|
case "FilteredCall":
|
|
576
619
|
return (
|
|
577
|
-
exprCapturesNames(e.call, names) ||
|
|
578
|
-
exprCapturesNames(e.filter, names)
|
|
620
|
+
exprCapturesNames(e.call, names) || exprCapturesNames(e.filter, names)
|
|
579
621
|
);
|
|
622
|
+
case "AggregateCall": {
|
|
623
|
+
const ac = e as any;
|
|
624
|
+
if (exprCapturesNames(ac.call, names)) return true;
|
|
625
|
+
for (const ob of ac.orderBy as LuaOrderBy[]) {
|
|
626
|
+
if (exprCapturesNames(ob.expression, names)) return true;
|
|
627
|
+
const u = ob.using;
|
|
628
|
+
if (u && typeof u !== "string") {
|
|
629
|
+
if (functionBodyCapturesNames(u, names)) return true;
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
return false;
|
|
633
|
+
}
|
|
580
634
|
default:
|
|
581
635
|
return false;
|
|
582
636
|
}
|
|
@@ -644,7 +698,8 @@ function parseBlock(t: ParseTree, ctx: ASTCtx): LuaBlock {
|
|
|
644
698
|
case "FunctionCallStatement": {
|
|
645
699
|
if (!hasFunctionDef) {
|
|
646
700
|
const call = (s as any).call as LuaFunctionCallExpression;
|
|
647
|
-
hasFunctionDef =
|
|
701
|
+
hasFunctionDef =
|
|
702
|
+
expressionHasFunctionDef(call.prefix) ||
|
|
648
703
|
expressionsHaveFunctionDef(call.args);
|
|
649
704
|
}
|
|
650
705
|
break;
|
|
@@ -711,7 +766,8 @@ function parseBlock(t: ParseTree, ctx: ASTCtx): LuaBlock {
|
|
|
711
766
|
hasCloseHere = hasCloseHere || !!child.hasCloseHere;
|
|
712
767
|
hasFunctionDef = hasFunctionDef || !!child.hasFunctionDef;
|
|
713
768
|
if (!hasFunctionDef) {
|
|
714
|
-
hasFunctionDef =
|
|
769
|
+
hasFunctionDef =
|
|
770
|
+
expressionHasFunctionDef((s as any).start) ||
|
|
715
771
|
expressionHasFunctionDef((s as any).end) ||
|
|
716
772
|
((s as any).step
|
|
717
773
|
? expressionHasFunctionDef((s as any).step)
|
|
@@ -814,7 +870,7 @@ function parseStatement(t: ParseTree, ctx: ASTCtx): LuaStatement {
|
|
|
814
870
|
from?: number;
|
|
815
871
|
to?: number;
|
|
816
872
|
}[] = [];
|
|
817
|
-
let elseBlock: LuaBlock | undefined
|
|
873
|
+
let elseBlock: LuaBlock | undefined;
|
|
818
874
|
for (let i = 0; i < t.children!.length; i += 4) {
|
|
819
875
|
const child = t.children![i];
|
|
820
876
|
if (!child || !child.children || !child.children[0]) {
|
|
@@ -904,8 +960,8 @@ function parseStatement(t: ParseTree, ctx: ASTCtx): LuaStatement {
|
|
|
904
960
|
case "Assign":
|
|
905
961
|
return {
|
|
906
962
|
type: "Assignment",
|
|
907
|
-
variables: t
|
|
908
|
-
.filter((c) => c.type && c.type !== ",")
|
|
963
|
+
variables: t
|
|
964
|
+
.children![0].children!.filter((c) => c.type && c.type !== ",")
|
|
909
965
|
.map((lvalue) => parseLValue(lvalue, ctx)),
|
|
910
966
|
expressions: parseExpList(t.children![2], ctx),
|
|
911
967
|
ctx: context(t, ctx),
|
|
@@ -949,9 +1005,7 @@ function parseStatement(t: ParseTree, ctx: ASTCtx): LuaStatement {
|
|
|
949
1005
|
console.error(t);
|
|
950
1006
|
throw new Error(
|
|
951
1007
|
`Unknown statement type: ${
|
|
952
|
-
t.children![0]?.text
|
|
953
|
-
? t.children![0].text
|
|
954
|
-
: String(t.type)
|
|
1008
|
+
t.children![0]?.text ? t.children![0].text : String(t.type)
|
|
955
1009
|
}`,
|
|
956
1010
|
);
|
|
957
1011
|
}
|
|
@@ -962,28 +1016,44 @@ function parseFunctionCall(
|
|
|
962
1016
|
ctx: ASTCtx,
|
|
963
1017
|
): LuaFunctionCallExpression {
|
|
964
1018
|
if (t.children![1] && t.children![1].type === ":") {
|
|
965
|
-
|
|
1019
|
+
const { args, aggOrderBy } = parseFunctionArgsWithOrderBy(
|
|
1020
|
+
t.children!.slice(3),
|
|
1021
|
+
ctx,
|
|
1022
|
+
);
|
|
1023
|
+
const result: LuaFunctionCallExpression = {
|
|
966
1024
|
type: "FunctionCall",
|
|
967
1025
|
prefix: parsePrefixExpression(t.children![0], ctx),
|
|
968
1026
|
name: t.children![2].children![0].text!,
|
|
969
|
-
args
|
|
1027
|
+
args,
|
|
970
1028
|
ctx: context(t, ctx),
|
|
971
1029
|
};
|
|
1030
|
+
if (aggOrderBy) {
|
|
1031
|
+
(result as any).orderBy = aggOrderBy;
|
|
1032
|
+
}
|
|
1033
|
+
return result;
|
|
972
1034
|
}
|
|
973
|
-
|
|
1035
|
+
const { args, aggOrderBy } = parseFunctionArgsWithOrderBy(
|
|
1036
|
+
t.children!.slice(1),
|
|
1037
|
+
ctx,
|
|
1038
|
+
);
|
|
1039
|
+
const result: LuaFunctionCallExpression = {
|
|
974
1040
|
type: "FunctionCall",
|
|
975
1041
|
prefix: parsePrefixExpression(t.children![0], ctx),
|
|
976
|
-
args
|
|
1042
|
+
args,
|
|
977
1043
|
ctx: context(t, ctx),
|
|
978
1044
|
};
|
|
1045
|
+
if (aggOrderBy) {
|
|
1046
|
+
(result as any).orderBy = aggOrderBy;
|
|
1047
|
+
}
|
|
1048
|
+
return result;
|
|
979
1049
|
}
|
|
980
1050
|
|
|
981
1051
|
function parseAttNames(t: ParseTree, ctx: ASTCtx): LuaAttName[] {
|
|
982
1052
|
if (t.type !== "AttNameList") {
|
|
983
1053
|
throw new Error(`Expected AttNameList, got ${t.type}`);
|
|
984
1054
|
}
|
|
985
|
-
return t
|
|
986
|
-
.filter((c) => c.type && c.type !== ",")
|
|
1055
|
+
return t
|
|
1056
|
+
.children!.filter((c) => c.type && c.type !== ",")
|
|
987
1057
|
.map((att) => parseAttName(att, ctx));
|
|
988
1058
|
}
|
|
989
1059
|
|
|
@@ -1044,7 +1114,7 @@ function parseFunctionName(t: ParseTree, ctx: ASTCtx): LuaFunctionName {
|
|
|
1044
1114
|
throw new Error(`Expected FunctionName, got ${t.type}`);
|
|
1045
1115
|
}
|
|
1046
1116
|
const propNames: string[] = [];
|
|
1047
|
-
let colonName: string | undefined
|
|
1117
|
+
let colonName: string | undefined;
|
|
1048
1118
|
for (let i = 0; i < t.children!.length; i += 2) {
|
|
1049
1119
|
const prop = t.children![i];
|
|
1050
1120
|
propNames.push(prop.children![0].text!);
|
|
@@ -1065,8 +1135,8 @@ function parseNameList(t: ParseTree): string[] {
|
|
|
1065
1135
|
if (t.type !== "NameList") {
|
|
1066
1136
|
throw new Error(`Expected NameList, got ${t.type}`);
|
|
1067
1137
|
}
|
|
1068
|
-
return t
|
|
1069
|
-
.filter((c) => c.type === "Name")
|
|
1138
|
+
return t
|
|
1139
|
+
.children!.filter((c) => c.type === "Name")
|
|
1070
1140
|
.map((c) => c.children![0].text!);
|
|
1071
1141
|
}
|
|
1072
1142
|
|
|
@@ -1074,8 +1144,8 @@ function parseExpList(t: ParseTree, ctx: ASTCtx): LuaExpression[] {
|
|
|
1074
1144
|
if (t.type !== "ExpList") {
|
|
1075
1145
|
throw new Error(`Expected ExpList, got ${t.type}`);
|
|
1076
1146
|
}
|
|
1077
|
-
return t
|
|
1078
|
-
.filter((c) => c.type && c.type !== ",")
|
|
1147
|
+
return t
|
|
1148
|
+
.children!.filter((c) => c.type && c.type !== ",")
|
|
1079
1149
|
.map((e) => parseExpression(e, ctx));
|
|
1080
1150
|
}
|
|
1081
1151
|
|
|
@@ -1094,44 +1164,46 @@ function parseString(s: string): string {
|
|
|
1094
1164
|
}
|
|
1095
1165
|
return text;
|
|
1096
1166
|
}
|
|
1097
|
-
return s
|
|
1098
|
-
|
|
1099
|
-
(
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1167
|
+
return s
|
|
1168
|
+
.slice(1, -1)
|
|
1169
|
+
.replace(
|
|
1170
|
+
/\\(x[0-9a-fA-F]{2}|u\{[0-9a-fA-F]+\}|[abfnrtv\\'"n])/g,
|
|
1171
|
+
(match, capture) => {
|
|
1172
|
+
switch (capture) {
|
|
1173
|
+
case "a":
|
|
1174
|
+
return "\x07"; // Bell
|
|
1175
|
+
case "b":
|
|
1176
|
+
return "\b"; // Backspace
|
|
1177
|
+
case "f":
|
|
1178
|
+
return "\f"; // Form feed
|
|
1179
|
+
case "n":
|
|
1180
|
+
return "\n"; // Newline
|
|
1181
|
+
case "r":
|
|
1182
|
+
return "\r"; // Carriage return
|
|
1183
|
+
case "t":
|
|
1184
|
+
return "\t"; // Horizontal tab
|
|
1185
|
+
case "v":
|
|
1186
|
+
return "\v"; // Vertical tab
|
|
1187
|
+
case "\\":
|
|
1188
|
+
return "\\"; // Backslash
|
|
1189
|
+
case '"':
|
|
1190
|
+
return '"'; // Double quote
|
|
1191
|
+
case "'":
|
|
1192
|
+
return "'"; // Single quote
|
|
1193
|
+
default:
|
|
1194
|
+
// Handle hexadecimal \x00
|
|
1195
|
+
if (capture.startsWith("x")) {
|
|
1196
|
+
return String.fromCharCode(parseInt(capture.slice(1), 16));
|
|
1197
|
+
}
|
|
1198
|
+
// Handle unicode \u{XXXX}
|
|
1199
|
+
if (capture.startsWith("u{")) {
|
|
1200
|
+
const codePoint = parseInt(capture.slice(2, -1), 16);
|
|
1201
|
+
return String.fromCodePoint(codePoint);
|
|
1202
|
+
}
|
|
1203
|
+
return match; // return the original match if nothing fits
|
|
1204
|
+
}
|
|
1205
|
+
},
|
|
1206
|
+
);
|
|
1135
1207
|
}
|
|
1136
1208
|
|
|
1137
1209
|
function parseExpression(t: ParseTree, ctx: ASTCtx): LuaExpression {
|
|
@@ -1224,10 +1296,10 @@ function parseExpression(t: ParseTree, ctx: ASTCtx): LuaExpression {
|
|
|
1224
1296
|
case "TableConstructor":
|
|
1225
1297
|
return {
|
|
1226
1298
|
type: "TableConstructor",
|
|
1227
|
-
fields: t
|
|
1228
|
-
.slice(1, -1)
|
|
1299
|
+
fields: t
|
|
1300
|
+
.children!.slice(1, -1)
|
|
1229
1301
|
.filter((c) =>
|
|
1230
|
-
["FieldExp", "FieldProp", "FieldDynamic"].includes(c.type!)
|
|
1302
|
+
["FieldExp", "FieldProp", "FieldDynamic"].includes(c.type!),
|
|
1231
1303
|
)
|
|
1232
1304
|
.map((tf) => parseTableField(tf, ctx)),
|
|
1233
1305
|
ctx: context(t, ctx),
|
|
@@ -1256,6 +1328,20 @@ function parseExpression(t: ParseTree, ctx: ASTCtx): LuaExpression {
|
|
|
1256
1328
|
}
|
|
1257
1329
|
}
|
|
1258
1330
|
|
|
1331
|
+
function parseFieldList(t: ParseTree, ctx: ASTCtx): LuaTableField[] {
|
|
1332
|
+
if (t.type !== "FieldList") {
|
|
1333
|
+
throw new Error(`Expected FieldList, got ${t.type}`);
|
|
1334
|
+
}
|
|
1335
|
+
return t
|
|
1336
|
+
.children!.filter(
|
|
1337
|
+
(c) =>
|
|
1338
|
+
c.type === "FieldExp" ||
|
|
1339
|
+
c.type === "FieldProp" ||
|
|
1340
|
+
c.type === "FieldDynamic",
|
|
1341
|
+
)
|
|
1342
|
+
.map((c) => parseTableField(c, ctx));
|
|
1343
|
+
}
|
|
1344
|
+
|
|
1259
1345
|
function parseQueryClause(t: ParseTree, ctx: ASTCtx): LuaQueryClause {
|
|
1260
1346
|
if (t.type !== "QueryClause") {
|
|
1261
1347
|
throw new Error(`Expected QueryClause, got ${t.type}`);
|
|
@@ -1263,18 +1349,14 @@ function parseQueryClause(t: ParseTree, ctx: ASTCtx): LuaQueryClause {
|
|
|
1263
1349
|
t = t.children![0];
|
|
1264
1350
|
switch (t.type) {
|
|
1265
1351
|
case "FromClause": {
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
name: t.children![1].children![0].text!,
|
|
1271
|
-
expression: parseExpression(t.children![3], ctx),
|
|
1272
|
-
ctx: context(t, ctx),
|
|
1273
|
-
};
|
|
1352
|
+
// children: ckw<"from">, FieldList
|
|
1353
|
+
const fieldListNode = t.children!.find((c) => c.type === "FieldList");
|
|
1354
|
+
if (!fieldListNode) {
|
|
1355
|
+
throw new Error("FromClause missing FieldList");
|
|
1274
1356
|
}
|
|
1275
1357
|
return {
|
|
1276
1358
|
type: "From",
|
|
1277
|
-
|
|
1359
|
+
fields: parseFieldList(fieldListNode, ctx),
|
|
1278
1360
|
ctx: context(t, ctx),
|
|
1279
1361
|
};
|
|
1280
1362
|
}
|
|
@@ -1296,40 +1378,18 @@ function parseQueryClause(t: ParseTree, ctx: ASTCtx): LuaQueryClause {
|
|
|
1296
1378
|
ctx: context(t, ctx),
|
|
1297
1379
|
};
|
|
1298
1380
|
}
|
|
1381
|
+
case "OffsetClause": {
|
|
1382
|
+
return {
|
|
1383
|
+
type: "Offset",
|
|
1384
|
+
offset: parseExpression(t.children![1], ctx),
|
|
1385
|
+
ctx: context(t, ctx),
|
|
1386
|
+
};
|
|
1387
|
+
}
|
|
1299
1388
|
case "OrderByClause": {
|
|
1300
1389
|
const orderBy: LuaOrderBy[] = [];
|
|
1301
1390
|
for (const child of t.children!) {
|
|
1302
1391
|
if (child.type === "OrderBy") {
|
|
1303
|
-
|
|
1304
|
-
let direction: "asc" | "desc" = "asc";
|
|
1305
|
-
let nulls: "first" | "last" | undefined;
|
|
1306
|
-
let usingVal: string | LuaFunctionBody | undefined;
|
|
1307
|
-
for (let i = 1; i < kids.length; i++) {
|
|
1308
|
-
const typ = kids[i].type;
|
|
1309
|
-
if (typ === "desc") direction = "desc";
|
|
1310
|
-
else if (typ === "asc") direction = "asc";
|
|
1311
|
-
else if (typ === "first") nulls = "first";
|
|
1312
|
-
else if (typ === "last") nulls = "last";
|
|
1313
|
-
else if (typ === "using") {
|
|
1314
|
-
const next = kids[i + 1];
|
|
1315
|
-
if (next.type === "function") {
|
|
1316
|
-
usingVal = parseFunctionBody(kids[i + 2], ctx);
|
|
1317
|
-
i += 2;
|
|
1318
|
-
} else {
|
|
1319
|
-
usingVal = next.children![0].text!;
|
|
1320
|
-
i++;
|
|
1321
|
-
}
|
|
1322
|
-
}
|
|
1323
|
-
}
|
|
1324
|
-
const ob: LuaOrderBy = {
|
|
1325
|
-
type: "Order",
|
|
1326
|
-
expression: parseExpression(kids[0], ctx),
|
|
1327
|
-
direction,
|
|
1328
|
-
ctx: context(child, ctx),
|
|
1329
|
-
};
|
|
1330
|
-
if (nulls) ob.nulls = nulls;
|
|
1331
|
-
if (usingVal !== undefined) ob.using = usingVal;
|
|
1332
|
-
orderBy.push(ob);
|
|
1392
|
+
orderBy.push(parseOrderByNode(child, ctx));
|
|
1333
1393
|
}
|
|
1334
1394
|
}
|
|
1335
1395
|
return {
|
|
@@ -1339,23 +1399,26 @@ function parseQueryClause(t: ParseTree, ctx: ASTCtx): LuaQueryClause {
|
|
|
1339
1399
|
};
|
|
1340
1400
|
}
|
|
1341
1401
|
case "SelectClause": {
|
|
1402
|
+
// children: ckw<"select">, FieldList
|
|
1403
|
+
const fieldListNode = t.children!.find((c) => c.type === "FieldList");
|
|
1404
|
+
if (!fieldListNode) {
|
|
1405
|
+
throw new Error("SelectClause missing FieldList");
|
|
1406
|
+
}
|
|
1342
1407
|
return {
|
|
1343
1408
|
type: "Select",
|
|
1344
|
-
|
|
1409
|
+
fields: parseFieldList(fieldListNode, ctx),
|
|
1345
1410
|
ctx: context(t, ctx),
|
|
1346
1411
|
};
|
|
1347
1412
|
}
|
|
1348
1413
|
case "GroupByClause": {
|
|
1349
|
-
// children: ckw<"group">, ckw<"by">,
|
|
1350
|
-
const
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
)
|
|
1355
|
-
.map((c) => parseExpression(c, ctx));
|
|
1414
|
+
// children: ckw<"group">, ckw<"by">, FieldList
|
|
1415
|
+
const fieldListNode = t.children!.find((c) => c.type === "FieldList");
|
|
1416
|
+
if (!fieldListNode) {
|
|
1417
|
+
throw new Error("GroupByClause missing FieldList");
|
|
1418
|
+
}
|
|
1356
1419
|
return {
|
|
1357
1420
|
type: "GroupBy",
|
|
1358
|
-
|
|
1421
|
+
fields: parseFieldList(fieldListNode, ctx),
|
|
1359
1422
|
ctx: context(t, ctx),
|
|
1360
1423
|
};
|
|
1361
1424
|
}
|
|
@@ -1372,10 +1435,70 @@ function parseQueryClause(t: ParseTree, ctx: ASTCtx): LuaQueryClause {
|
|
|
1372
1435
|
}
|
|
1373
1436
|
}
|
|
1374
1437
|
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1438
|
+
// Parse a single OrderBy node (shared by query OrderByClause and AggOrderBy)
|
|
1439
|
+
function parseOrderByNode(child: ParseTree, ctx: ASTCtx): LuaOrderBy {
|
|
1440
|
+
const kids = child.children!;
|
|
1441
|
+
let direction: "asc" | "desc" = "asc";
|
|
1442
|
+
let nulls: "first" | "last" | undefined;
|
|
1443
|
+
let usingVal: string | LuaFunctionBody | undefined;
|
|
1444
|
+
for (let i = 1; i < kids.length; i++) {
|
|
1445
|
+
const typ = kids[i].type;
|
|
1446
|
+
if (typ === "desc") direction = "desc";
|
|
1447
|
+
else if (typ === "asc") direction = "asc";
|
|
1448
|
+
else if (typ === "first") nulls = "first";
|
|
1449
|
+
else if (typ === "last") nulls = "last";
|
|
1450
|
+
else if (typ === "using") {
|
|
1451
|
+
const next = kids[i + 1];
|
|
1452
|
+
if (next.type === "function") {
|
|
1453
|
+
usingVal = parseFunctionBody(kids[i + 2], ctx);
|
|
1454
|
+
i += 2;
|
|
1455
|
+
} else {
|
|
1456
|
+
usingVal = next.children![0].text!;
|
|
1457
|
+
i++;
|
|
1458
|
+
}
|
|
1459
|
+
}
|
|
1460
|
+
}
|
|
1461
|
+
const ob: LuaOrderBy = {
|
|
1462
|
+
type: "Order",
|
|
1463
|
+
expression: parseExpression(kids[0], ctx),
|
|
1464
|
+
direction,
|
|
1465
|
+
ctx: context(child, ctx),
|
|
1466
|
+
};
|
|
1467
|
+
if (nulls) ob.nulls = nulls;
|
|
1468
|
+
if (usingVal !== undefined) ob.using = usingVal;
|
|
1469
|
+
return ob;
|
|
1470
|
+
}
|
|
1471
|
+
|
|
1472
|
+
// Parse an AggOrderBy node into LuaOrderBy[]
|
|
1473
|
+
function parseAggOrderBy(t: ParseTree, ctx: ASTCtx): LuaOrderBy[] {
|
|
1474
|
+
if (t.type !== "AggOrderBy") {
|
|
1475
|
+
throw new Error(`Expected AggOrderBy, got ${t.type}`);
|
|
1476
|
+
}
|
|
1477
|
+
const orderBy: LuaOrderBy[] = [];
|
|
1478
|
+
for (const child of t.children!) {
|
|
1479
|
+
if (child.type === "OrderBy") {
|
|
1480
|
+
orderBy.push(parseOrderByNode(child, ctx));
|
|
1481
|
+
}
|
|
1482
|
+
}
|
|
1483
|
+
return orderBy;
|
|
1484
|
+
}
|
|
1485
|
+
|
|
1486
|
+
// Parse function args, extracting AggOrderBy if present inside funcParams
|
|
1487
|
+
function parseFunctionArgsWithOrderBy(
|
|
1488
|
+
ts: ParseTree[],
|
|
1489
|
+
ctx: ASTCtx,
|
|
1490
|
+
): { args: LuaExpression[]; aggOrderBy?: LuaOrderBy[] } {
|
|
1491
|
+
let aggOrderBy: LuaOrderBy[] | undefined;
|
|
1492
|
+
const args: LuaExpression[] = [];
|
|
1493
|
+
for (const t of ts) {
|
|
1494
|
+
if (!t.type || [",", "(", ")"].includes(t.type)) continue;
|
|
1495
|
+
if (t.type === "AggOrderBy") {
|
|
1496
|
+
aggOrderBy = parseAggOrderBy(t, ctx);
|
|
1497
|
+
} else {
|
|
1498
|
+
args.push(parseExpression(t, ctx));
|
|
1499
|
+
}
|
|
1500
|
+
}
|
|
1501
|
+
return { args, aggOrderBy };
|
|
1379
1502
|
}
|
|
1380
1503
|
|
|
1381
1504
|
function parseFunctionBody(t: ParseTree, ctx: ASTCtx): LuaFunctionBody {
|
|
@@ -1384,8 +1507,10 @@ function parseFunctionBody(t: ParseTree, ctx: ASTCtx): LuaFunctionBody {
|
|
|
1384
1507
|
}
|
|
1385
1508
|
return {
|
|
1386
1509
|
type: "FunctionBody",
|
|
1387
|
-
parameters: t
|
|
1388
|
-
.
|
|
1510
|
+
parameters: t
|
|
1511
|
+
.children![1].children!.filter(
|
|
1512
|
+
(c) => c.type && ["Name", "Ellipsis"].includes(c.type),
|
|
1513
|
+
)
|
|
1389
1514
|
.map((c) => c.children![0].text!),
|
|
1390
1515
|
block: parseBlock(t.children![3], ctx),
|
|
1391
1516
|
ctx: context(t, ctx),
|
|
@@ -1573,9 +1698,7 @@ export function parse(s: string, ctx: ASTCtx = {}): LuaBlock {
|
|
|
1573
1698
|
if (e && typeof e === "object" && "astCtx" in e) {
|
|
1574
1699
|
throw new LuaRuntimeError(
|
|
1575
1700
|
e.message,
|
|
1576
|
-
LuaStackFrame.lostFrame.withCtx(
|
|
1577
|
-
(e as any).astCtx as ASTCtx,
|
|
1578
|
-
),
|
|
1701
|
+
LuaStackFrame.lostFrame.withCtx((e as any).astCtx as ASTCtx),
|
|
1579
1702
|
);
|
|
1580
1703
|
}
|
|
1581
1704
|
throw e;
|
|
@@ -1619,9 +1742,7 @@ function luaUnexpectedSymbolMessage(src: string, from: number): string {
|
|
|
1619
1742
|
/**
|
|
1620
1743
|
* Helper function to parse a Lua expression string
|
|
1621
1744
|
*/
|
|
1622
|
-
export function parseExpressionString(
|
|
1623
|
-
expr: string,
|
|
1624
|
-
): LuaExpression {
|
|
1745
|
+
export function parseExpressionString(expr: string): LuaExpression {
|
|
1625
1746
|
const parsedLua = parse(`_(${expr})`) as LuaBlock;
|
|
1626
1747
|
return (parsedLua.statements[0] as LuaFunctionCallStatement).call.args[0];
|
|
1627
1748
|
}
|