@silverbulletmd/silverbullet 2.4.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.
Files changed (117) hide show
  1. package/LICENSE.md +18 -0
  2. package/README.md +98 -0
  3. package/client/asset_bundle/bundle.ts +95 -0
  4. package/client/data/datastore.ts +85 -0
  5. package/client/data/kv_primitives.ts +25 -0
  6. package/client/markdown_parser/constants.ts +13 -0
  7. package/client/plugos/event.ts +36 -0
  8. package/client/plugos/eventhook.ts +8 -0
  9. package/client/plugos/hooks/code_widget.ts +59 -0
  10. package/client/plugos/hooks/command.ts +104 -0
  11. package/client/plugos/hooks/document_editor.ts +77 -0
  12. package/client/plugos/hooks/event.ts +187 -0
  13. package/client/plugos/hooks/mq.ts +154 -0
  14. package/client/plugos/hooks/plug_namespace.ts +85 -0
  15. package/client/plugos/hooks/slash_command.ts +192 -0
  16. package/client/plugos/hooks/syscall.ts +66 -0
  17. package/client/plugos/manifest_cache.ts +67 -0
  18. package/client/plugos/plug.ts +99 -0
  19. package/client/plugos/plug_compile.ts +202 -0
  20. package/client/plugos/protocol.ts +40 -0
  21. package/client/plugos/proxy_fetch.ts +53 -0
  22. package/client/plugos/sandboxes/deno_worker_sandbox.ts +6 -0
  23. package/client/plugos/sandboxes/sandbox.ts +14 -0
  24. package/client/plugos/sandboxes/web_worker_sandbox.ts +17 -0
  25. package/client/plugos/sandboxes/worker_sandbox.ts +132 -0
  26. package/client/plugos/syscalls/asset.ts +35 -0
  27. package/client/plugos/syscalls/clientStore.ts +21 -0
  28. package/client/plugos/syscalls/client_code_widget.ts +12 -0
  29. package/client/plugos/syscalls/code_widget.ts +24 -0
  30. package/client/plugos/syscalls/config.ts +46 -0
  31. package/client/plugos/syscalls/datastore.ts +89 -0
  32. package/client/plugos/syscalls/editor.ts +673 -0
  33. package/client/plugos/syscalls/event.ts +36 -0
  34. package/client/plugos/syscalls/fetch.ts +128 -0
  35. package/client/plugos/syscalls/index.ts +102 -0
  36. package/client/plugos/syscalls/jsonschema.ts +69 -0
  37. package/client/plugos/syscalls/language.ts +23 -0
  38. package/client/plugos/syscalls/lua.ts +58 -0
  39. package/client/plugos/syscalls/markdown.ts +84 -0
  40. package/client/plugos/syscalls/mq.ts +52 -0
  41. package/client/plugos/syscalls/service_registry.ts +43 -0
  42. package/client/plugos/syscalls/shell.ts +39 -0
  43. package/client/plugos/syscalls/space.ts +139 -0
  44. package/client/plugos/syscalls/sync.ts +77 -0
  45. package/client/plugos/syscalls/system.ts +150 -0
  46. package/client/plugos/system.ts +201 -0
  47. package/client/plugos/types.ts +60 -0
  48. package/client/plugos/util.ts +14 -0
  49. package/client/plugos/worker_runtime.ts +195 -0
  50. package/client/space_lua/ast.ts +328 -0
  51. package/client/space_lua/ast_narrow.ts +81 -0
  52. package/client/space_lua/eval.ts +2478 -0
  53. package/client/space_lua/labels.ts +416 -0
  54. package/client/space_lua/numeric.ts +240 -0
  55. package/client/space_lua/parse.ts +1522 -0
  56. package/client/space_lua/query_collection.ts +232 -0
  57. package/client/space_lua/rp.ts +27 -0
  58. package/client/space_lua/runtime.ts +1702 -0
  59. package/client/space_lua/stdlib/crypto.ts +10 -0
  60. package/client/space_lua/stdlib/encoding.ts +19 -0
  61. package/client/space_lua/stdlib/format.ts +770 -0
  62. package/client/space_lua/stdlib/js.ts +73 -0
  63. package/client/space_lua/stdlib/load.ts +52 -0
  64. package/client/space_lua/stdlib/math.ts +193 -0
  65. package/client/space_lua/stdlib/net.ts +113 -0
  66. package/client/space_lua/stdlib/os.ts +368 -0
  67. package/client/space_lua/stdlib/space_lua.ts +153 -0
  68. package/client/space_lua/stdlib/string.ts +286 -0
  69. package/client/space_lua/stdlib/table.ts +401 -0
  70. package/client/space_lua/stdlib.ts +489 -0
  71. package/client/space_lua/tonumber.ts +501 -0
  72. package/client/space_lua/util.ts +96 -0
  73. package/dist/plug-compile.js +1513 -0
  74. package/package.json +120 -0
  75. package/plug-api/constants.ts +42 -0
  76. package/plug-api/lib/async.ts +162 -0
  77. package/plug-api/lib/crypto.ts +202 -0
  78. package/plug-api/lib/dates.ts +13 -0
  79. package/plug-api/lib/json.ts +136 -0
  80. package/plug-api/lib/limited_map.ts +72 -0
  81. package/plug-api/lib/memory_cache.ts +21 -0
  82. package/plug-api/lib/native_fetch.ts +6 -0
  83. package/plug-api/lib/ref.ts +275 -0
  84. package/plug-api/lib/resolve.ts +90 -0
  85. package/plug-api/lib/tags.ts +15 -0
  86. package/plug-api/lib/transclusion.ts +122 -0
  87. package/plug-api/lib/tree.ts +232 -0
  88. package/plug-api/lib/yaml.ts +284 -0
  89. package/plug-api/syscall.ts +15 -0
  90. package/plug-api/syscalls/asset.ts +36 -0
  91. package/plug-api/syscalls/client_store.ts +33 -0
  92. package/plug-api/syscalls/code_widget.ts +8 -0
  93. package/plug-api/syscalls/config.ts +58 -0
  94. package/plug-api/syscalls/datastore.ts +96 -0
  95. package/plug-api/syscalls/editor.ts +517 -0
  96. package/plug-api/syscalls/event.ts +47 -0
  97. package/plug-api/syscalls/index.ts +77 -0
  98. package/plug-api/syscalls/jsonschema.ts +25 -0
  99. package/plug-api/syscalls/language.ts +23 -0
  100. package/plug-api/syscalls/lua.ts +20 -0
  101. package/plug-api/syscalls/markdown.ts +38 -0
  102. package/plug-api/syscalls/mq.ts +79 -0
  103. package/plug-api/syscalls/shell.ts +14 -0
  104. package/plug-api/syscalls/space.ts +212 -0
  105. package/plug-api/syscalls/sync.ts +28 -0
  106. package/plug-api/syscalls/system.ts +102 -0
  107. package/plug-api/syscalls/yaml.ts +28 -0
  108. package/plug-api/syscalls.ts +21 -0
  109. package/plug-api/system_mock.ts +89 -0
  110. package/plug-api/types/client.ts +116 -0
  111. package/plug-api/types/config.ts +22 -0
  112. package/plug-api/types/datastore.ts +28 -0
  113. package/plug-api/types/event.ts +27 -0
  114. package/plug-api/types/index.ts +56 -0
  115. package/plug-api/types/manifest.ts +98 -0
  116. package/plug-api/types/namespace.ts +6 -0
  117. package/plugs/builtin_plugs.ts +14 -0
@@ -0,0 +1,195 @@
1
+ // This is the runtime imported from the compiled plug worker code
2
+ import type { ControllerMessage, WorkerMessage } from "./protocol.ts";
3
+ import type {
4
+ ProxyFetchRequest64,
5
+ ProxyFetchResponse64,
6
+ } from "./proxy_fetch.ts";
7
+ import { base64Decode, base64Encode } from "../../plug-api/lib/crypto.ts";
8
+ import { initLogger } from "../lib/logger.ts";
9
+
10
+ declare global {
11
+ function syscall(name: string, ...args: any[]): Promise<any>;
12
+ }
13
+
14
+ let workerPostMessage = (_msg: ControllerMessage): void => {
15
+ throw new Error("Not initialized yet");
16
+ };
17
+
18
+ // Are we running in a (web) worker?
19
+
20
+ // Determines if we're running in a web worker environment (Deno or browser)
21
+ // - in a browser's main threads, typeof window is "object"
22
+ // - in a browser's worker threads, typeof window === "undefined"
23
+ // - in Deno's main thread typeof window === "object"
24
+ // - in Deno's workers typeof window === "undefined
25
+ // - in Cloudflare workers typeof window === "undefined", but typeof globalThis.WebSocketPair is defined
26
+ const runningAsWebWorker = typeof window === "undefined" &&
27
+ // @ts-ignore: globalThis
28
+ typeof globalThis.WebSocketPair === "undefined";
29
+
30
+ if (typeof Deno === "undefined") {
31
+ // @ts-ignore: Deno hack
32
+ self.Deno = {
33
+ args: [],
34
+ // @ts-ignore: Deno hack
35
+ build: {
36
+ arch: "x86_64",
37
+ },
38
+ env: {
39
+ // @ts-ignore: Deno hack
40
+ get() {
41
+ },
42
+ },
43
+ };
44
+ }
45
+
46
+ const pendingRequests = new Map<
47
+ number,
48
+ {
49
+ resolve: (result: unknown) => void;
50
+ reject: (e: any) => void;
51
+ }
52
+ >();
53
+
54
+ let syscallReqId = 0;
55
+
56
+ if (runningAsWebWorker) {
57
+ globalThis.syscall = async (name: string, ...args: any[]) => {
58
+ return await new Promise((resolve, reject) => {
59
+ syscallReqId++;
60
+ pendingRequests.set(syscallReqId, { resolve, reject });
61
+ workerPostMessage({
62
+ type: "sys",
63
+ id: syscallReqId,
64
+ name,
65
+ args,
66
+ });
67
+ });
68
+ };
69
+ }
70
+
71
+ export function setupMessageListener(
72
+ // deno-lint-ignore ban-types
73
+ functionMapping: Record<string, Function>,
74
+ manifest: any,
75
+ postMessageFn: (msg: ControllerMessage) => void,
76
+ ) {
77
+ if (!runningAsWebWorker) {
78
+ // Don't do any of this stuff if this is not a web worker
79
+ // This caters to the NoSandbox run mode
80
+ return;
81
+ }
82
+ workerPostMessage = postMessageFn;
83
+ self.addEventListener("message", (event: { data: WorkerMessage }) => {
84
+ (async () => {
85
+ const data = event.data;
86
+ switch (data.type) {
87
+ case "inv":
88
+ {
89
+ const fn = functionMapping[data.name!];
90
+ if (!fn) {
91
+ throw new Error(`Function not loaded: ${data.name}`);
92
+ }
93
+ try {
94
+ const result = await Promise.resolve(fn(...(data.args || [])));
95
+ workerPostMessage({
96
+ type: "invr",
97
+ id: data.id,
98
+ result: result,
99
+ } as ControllerMessage);
100
+ } catch (e: any) {
101
+ console.error(
102
+ "An exception was thrown as a result of invoking function",
103
+ data.name,
104
+ "error:",
105
+ e.message,
106
+ );
107
+ workerPostMessage({
108
+ type: "invr",
109
+ id: data.id!,
110
+ error: e.message,
111
+ });
112
+ }
113
+ }
114
+ break;
115
+ case "sysr":
116
+ {
117
+ const syscallId = data.id;
118
+ const lookup = pendingRequests.get(syscallId);
119
+ if (!lookup) {
120
+ throw Error("Invalid request id");
121
+ }
122
+ pendingRequests.delete(syscallId);
123
+ if (data.error) {
124
+ lookup.reject(new Error(data.error));
125
+ } else {
126
+ lookup.resolve(data.result);
127
+ }
128
+ }
129
+
130
+ break;
131
+ }
132
+ })().catch(console.error);
133
+ });
134
+ // Signal initialization with manifest
135
+ workerPostMessage({
136
+ type: "manifest",
137
+ manifest,
138
+ });
139
+ initLogger(`[${manifest.name} plug]`);
140
+ }
141
+
142
+ export async function sandboxFetch(
143
+ reqInfo: RequestInfo,
144
+ options?: ProxyFetchRequest64,
145
+ ): Promise<ProxyFetchResponse64> {
146
+ if (typeof reqInfo !== "string") {
147
+ const body = new Uint8Array(await reqInfo.arrayBuffer());
148
+ const encodedBody = body.length > 0 ? base64Encode(body) : undefined;
149
+ options = {
150
+ method: reqInfo.method,
151
+ headers: Object.fromEntries(reqInfo.headers.entries()),
152
+ base64Body: encodedBody,
153
+ };
154
+ reqInfo = reqInfo.url;
155
+ }
156
+ return syscall("sandboxFetch.fetch", reqInfo, options);
157
+ }
158
+
159
+ // @ts-ignore: monkey patching fetch
160
+ globalThis.nativeFetch = globalThis.fetch;
161
+
162
+ // Monkey patch fetch()
163
+ export function monkeyPatchFetch() {
164
+ // @ts-ignore: monkey patching fetch
165
+ globalThis.fetch = async function (
166
+ reqInfo: RequestInfo,
167
+ init?: RequestInit,
168
+ ): Promise<Response> {
169
+ const encodedBody = init && init.body
170
+ ? base64Encode(
171
+ new Uint8Array(await (new Response(init.body)).arrayBuffer()),
172
+ )
173
+ : undefined;
174
+ const r = await sandboxFetch(
175
+ reqInfo,
176
+ init && {
177
+ method: init.method,
178
+ headers: init.headers as Record<string, string>,
179
+ base64Body: encodedBody,
180
+ },
181
+ );
182
+ // Casting the response to "any" for now, since of weird Deno typing
183
+ return new Response(
184
+ (r.base64Body ? base64Decode(r.base64Body) : null) as any,
185
+ {
186
+ status: r.status,
187
+ headers: r.headers,
188
+ },
189
+ );
190
+ };
191
+ }
192
+
193
+ if (runningAsWebWorker) {
194
+ monkeyPatchFetch();
195
+ }
@@ -0,0 +1,328 @@
1
+ type ASTContext = {
2
+ ctx: ASTCtx;
3
+ };
4
+
5
+ export type NumericType = "int" | "float";
6
+
7
+ export type ASTCtx = {
8
+ from?: number;
9
+ to?: number;
10
+ } & Record<string, any>;
11
+
12
+ export type LuaBlock = {
13
+ type: "Block";
14
+ statements: LuaStatement[];
15
+ hasLabel?: boolean;
16
+ hasGoto?: boolean;
17
+ // the first duplicated label is recorded here for later eval
18
+ dupLabelError?: { name: string; ctx: ASTCtx };
19
+ // this block declares top-level locals and therefore needs a new env
20
+ needsEnv?: boolean;
21
+ // true if this block itself (not nested ones) defines at least one label
22
+ hasLabelHere?: boolean;
23
+ // true if this block itself (not nested ones) may create to-be-closed values
24
+ hasCloseHere?: boolean;
25
+ // true if this block's subtree contains any function definition
26
+ hasFunctionDef?: boolean;
27
+ } & ASTContext;
28
+
29
+ // STATEMENTS
30
+ export type LuaReturnStatement = {
31
+ type: "Return";
32
+ expressions: LuaExpression[];
33
+ } & ASTContext;
34
+
35
+ export type LuaStatement =
36
+ | LuaSemicolonStatement
37
+ | LuaLabelStatement
38
+ | LuaBreakStatement
39
+ | LuaGotoStatement
40
+ | LuaReturnStatement
41
+ | LuaBlock
42
+ | LuaWhileStatement
43
+ | LuaRepeatStatement
44
+ | LuaIfStatement
45
+ | LuaForStatement
46
+ | LuaForInStatement
47
+ | LuaFunctionStatement
48
+ | LuaLocalFunctionStatement
49
+ | LuaAssignmentStatement
50
+ | LuaLocalStatement
51
+ | LuaFunctionCallStatement;
52
+
53
+ export type LuaSemicolonStatement = {
54
+ type: "Semicolon";
55
+ } & ASTContext;
56
+
57
+ export type LuaLabelStatement = {
58
+ type: "Label";
59
+ name: string;
60
+ } & ASTContext;
61
+
62
+ export type LuaBreakStatement = {
63
+ type: "Break";
64
+ } & ASTContext;
65
+
66
+ export type LuaGotoStatement = {
67
+ type: "Goto";
68
+ name: string;
69
+ } & ASTContext;
70
+
71
+ export type LuaWhileStatement = {
72
+ type: "While";
73
+ condition: LuaExpression;
74
+ block: LuaBlock;
75
+ } & ASTContext;
76
+
77
+ export type LuaRepeatStatement = {
78
+ type: "Repeat";
79
+ block: LuaBlock;
80
+ condition: LuaExpression;
81
+ } & ASTContext;
82
+
83
+ export type LuaIfStatement = {
84
+ type: "If";
85
+ conditions: { condition: LuaExpression; block: LuaBlock }[];
86
+ elseBlock?: LuaBlock;
87
+ } & ASTContext;
88
+
89
+ export type LuaForStatement = {
90
+ type: "For";
91
+ name: string;
92
+ start: LuaExpression;
93
+ end: LuaExpression;
94
+ step?: LuaExpression;
95
+ block: LuaBlock;
96
+ // function definition in the block captures the loop variable
97
+ capturesLoopVar?: boolean;
98
+ } & ASTContext;
99
+
100
+ export type LuaForInStatement = {
101
+ type: "ForIn";
102
+ names: string[];
103
+ expressions: LuaExpression[];
104
+ block: LuaBlock;
105
+ // function definition in the block captures any loop variable
106
+ capturesLoopVar?: boolean;
107
+ } & ASTContext;
108
+
109
+ export type LuaFunctionStatement = {
110
+ type: "Function";
111
+ name: LuaFunctionName;
112
+ body: LuaFunctionBody;
113
+ } & ASTContext;
114
+
115
+ export type LuaLocalFunctionStatement = {
116
+ type: "LocalFunction";
117
+ name: string;
118
+ body: LuaFunctionBody;
119
+ } & ASTContext;
120
+
121
+ export type LuaFunctionName = {
122
+ type: "FunctionName";
123
+ propNames: string[];
124
+ colonName?: string;
125
+ } & ASTContext;
126
+
127
+ export type LuaFunctionBody = {
128
+ type: "FunctionBody";
129
+ parameters: string[];
130
+ block: LuaBlock;
131
+ } & ASTContext;
132
+
133
+ export type LuaAssignmentStatement = {
134
+ type: "Assignment";
135
+ variables: LuaLValue[];
136
+ expressions: LuaExpression[];
137
+ } & ASTContext;
138
+
139
+ export type LuaLValue =
140
+ | LuaVariable
141
+ | LuaPropertyAccessExpression
142
+ | LuaTableAccessExpression;
143
+
144
+ export type LuaLocalStatement = {
145
+ type: "Local";
146
+ names: LuaAttName[];
147
+ expressions?: LuaExpression[];
148
+ } & ASTContext;
149
+
150
+ export enum LuaAttribute {
151
+ Const = "const",
152
+ Close = "close",
153
+ }
154
+
155
+ export type LuaAttName = {
156
+ type: "AttName";
157
+ name: string;
158
+ attribute?: string;
159
+ attributes?: LuaAttribute[];
160
+ } & ASTContext;
161
+
162
+ export type LuaFunctionCallStatement = {
163
+ type: "FunctionCallStatement";
164
+ call: LuaFunctionCallExpression;
165
+ } & ASTContext;
166
+
167
+ // EXPRESSIONS
168
+ export type LuaExpression =
169
+ | LuaNilLiteral
170
+ | LuaBooleanLiteral
171
+ | LuaNumberLiteral
172
+ | LuaStringLiteral
173
+ | LuaPrefixExpression
174
+ | LuaBinaryExpression
175
+ | LuaUnaryExpression
176
+ | LuaTableConstructor
177
+ | LuaFunctionDefinition
178
+ | LuaQueryExpression;
179
+
180
+ export type LuaNilLiteral = {
181
+ type: "Nil";
182
+ } & ASTContext;
183
+
184
+ export type LuaBooleanLiteral = {
185
+ type: "Boolean";
186
+ value: boolean;
187
+ } & ASTContext;
188
+
189
+ export type LuaNumberLiteral = {
190
+ type: "Number";
191
+ value: number;
192
+ numericType: NumericType;
193
+ } & ASTContext;
194
+
195
+ export type LuaStringLiteral = {
196
+ type: "String";
197
+ value: string;
198
+ } & ASTContext;
199
+
200
+ export type LuaPrefixExpression =
201
+ | LuaVariableExpression
202
+ | LuaParenthesizedExpression
203
+ | LuaFunctionCallExpression;
204
+
205
+ export type LuaParenthesizedExpression = {
206
+ type: "Parenthesized";
207
+ expression: LuaExpression;
208
+ } & ASTContext;
209
+
210
+ export type LuaVariableExpression =
211
+ | LuaVariable
212
+ | LuaPropertyAccessExpression
213
+ | LuaTableAccessExpression;
214
+
215
+ export type LuaVariable = {
216
+ type: "Variable";
217
+ name: string;
218
+ } & ASTContext;
219
+
220
+ export type LuaPropertyAccessExpression = {
221
+ type: "PropertyAccess";
222
+ object: LuaPrefixExpression;
223
+ property: string;
224
+ } & ASTContext;
225
+
226
+ export type LuaTableAccessExpression = {
227
+ type: "TableAccess";
228
+ object: LuaPrefixExpression;
229
+ key: LuaExpression;
230
+ } & ASTContext;
231
+
232
+ export type LuaFunctionCallExpression = {
233
+ type: "FunctionCall";
234
+ prefix: LuaPrefixExpression;
235
+ name?: string;
236
+ args: LuaExpression[];
237
+ } & ASTContext;
238
+
239
+ export type LuaBinaryExpression = {
240
+ type: "Binary";
241
+ operator: string;
242
+ left: LuaExpression;
243
+ right: LuaExpression;
244
+ } & ASTContext;
245
+
246
+ export type LuaUnaryExpression = {
247
+ type: "Unary";
248
+ operator: string;
249
+ argument: LuaExpression;
250
+ } & ASTContext;
251
+
252
+ export type LuaTableConstructor = {
253
+ type: "TableConstructor";
254
+ fields: LuaTableField[];
255
+ } & ASTContext;
256
+
257
+ export type LuaTableField =
258
+ | LuaDynamicField
259
+ | LuaPropField
260
+ | LuaExpressionField;
261
+
262
+ export type LuaDynamicField = {
263
+ type: "DynamicField";
264
+ key: LuaExpression;
265
+ value: LuaExpression;
266
+ } & ASTContext;
267
+
268
+ export type LuaPropField = {
269
+ type: "PropField";
270
+ key: string;
271
+ value: LuaExpression;
272
+ } & ASTContext;
273
+
274
+ export type LuaExpressionField = {
275
+ type: "ExpressionField";
276
+ value: LuaExpression;
277
+ } & ASTContext;
278
+
279
+ export type LuaFunctionDefinition = {
280
+ type: "FunctionDefinition";
281
+ body: LuaFunctionBody;
282
+ } & ASTContext;
283
+
284
+ // Query stuff
285
+ export type LuaQueryExpression = {
286
+ type: "Query";
287
+ clauses: LuaQueryClause[];
288
+ } & ASTContext;
289
+
290
+ export type LuaQueryClause =
291
+ | LuaFromClause
292
+ | LuaWhereClause
293
+ | LuaLimitClause
294
+ | LuaOrderByClause
295
+ | LuaSelectClause;
296
+
297
+ export type LuaFromClause = {
298
+ type: "From";
299
+ name?: string;
300
+ expression: LuaExpression;
301
+ } & ASTContext;
302
+
303
+ export type LuaWhereClause = {
304
+ type: "Where";
305
+ expression: LuaExpression;
306
+ } & ASTContext;
307
+
308
+ export type LuaLimitClause = {
309
+ type: "Limit";
310
+ limit: LuaExpression;
311
+ offset?: LuaExpression;
312
+ } & ASTContext;
313
+
314
+ export type LuaOrderByClause = {
315
+ type: "OrderBy";
316
+ orderBy: LuaOrderBy[];
317
+ } & ASTContext;
318
+
319
+ export type LuaOrderBy = {
320
+ type: "Order";
321
+ expression: LuaExpression;
322
+ direction: "asc" | "desc";
323
+ } & ASTContext;
324
+
325
+ export type LuaSelectClause = {
326
+ type: "Select";
327
+ expression: LuaExpression;
328
+ } & ASTContext;
@@ -0,0 +1,81 @@
1
+ // Typed narrowers for AST nodes to avoid `(node as any)` in consumers.
2
+
3
+ import type { ASTCtx, LuaExpression, LuaLValue, LuaStatement } from "./ast.ts";
4
+
5
+ // Extract by `type` discriminant
6
+ type NarrowByType<U, K extends U extends { type: infer T } ? T : never> =
7
+ Extract<U, { type: K }>;
8
+
9
+ // Expressions
10
+ export const asStringExpr = (e: LuaExpression) =>
11
+ e as NarrowByType<LuaExpression, "String">;
12
+ export const asNumberExpr = (e: LuaExpression) =>
13
+ e as NarrowByType<LuaExpression, "Number">;
14
+ export const asBooleanExpr = (e: LuaExpression) =>
15
+ e as NarrowByType<LuaExpression, "Boolean">;
16
+ export const asNilExpr = (e: LuaExpression) =>
17
+ e as NarrowByType<LuaExpression, "Nil">;
18
+ export const asUnary = (e: LuaExpression) =>
19
+ e as NarrowByType<LuaExpression, "Unary">;
20
+ export const asBinary = (e: LuaExpression) =>
21
+ e as NarrowByType<LuaExpression, "Binary">;
22
+ export const asVariable = (e: LuaExpression) =>
23
+ e as NarrowByType<LuaExpression, "Variable">;
24
+ export const asFunctionCall = (e: LuaExpression) =>
25
+ e as NarrowByType<LuaExpression, "FunctionCall">;
26
+ export const asTableAccess = (e: LuaExpression) =>
27
+ e as NarrowByType<LuaExpression, "TableAccess">;
28
+ export const asPropertyAccess = (e: LuaExpression) =>
29
+ e as NarrowByType<LuaExpression, "PropertyAccess">;
30
+ export const asParenthesized = (e: LuaExpression) =>
31
+ e as NarrowByType<LuaExpression, "Parenthesized">;
32
+ export const asTableConstructor = (e: LuaExpression) =>
33
+ e as NarrowByType<LuaExpression, "TableConstructor">;
34
+ export const asFunctionDef = (e: LuaExpression) =>
35
+ e as NarrowByType<LuaExpression, "FunctionDefinition">;
36
+ export const asQueryExpr = (e: LuaExpression) =>
37
+ e as NarrowByType<LuaExpression, "Query">;
38
+
39
+ // L-values
40
+ export const asLValueVariable = (l: LuaLValue) =>
41
+ l as Extract<LuaLValue, { type: "Variable" }>;
42
+ export const asLValueTableAccess = (l: LuaLValue) =>
43
+ l as Extract<LuaLValue, { type: "TableAccess" }>;
44
+ export const asLValuePropertyAccess = (l: LuaLValue) =>
45
+ l as Extract<LuaLValue, { type: "PropertyAccess" }>;
46
+
47
+ // Statements
48
+ export const asAssignment = (s: LuaStatement) =>
49
+ s as NarrowByType<LuaStatement, "Assignment">;
50
+ export const asLocal = (s: LuaStatement) =>
51
+ s as NarrowByType<LuaStatement, "Local">;
52
+ export const asBlock = (s: LuaStatement) =>
53
+ s as NarrowByType<LuaStatement, "Block">;
54
+ export const asIf = (s: LuaStatement) => s as NarrowByType<LuaStatement, "If">;
55
+ export const asWhile = (s: LuaStatement) =>
56
+ s as NarrowByType<LuaStatement, "While">;
57
+ export const asRepeat = (s: LuaStatement) =>
58
+ s as NarrowByType<LuaStatement, "Repeat">;
59
+ export const asBreak = (s: LuaStatement) =>
60
+ s as NarrowByType<LuaStatement, "Break">;
61
+ export const asFunctionStmt = (s: LuaStatement) =>
62
+ s as NarrowByType<LuaStatement, "Function">;
63
+ export const asLocalFunction = (s: LuaStatement) =>
64
+ s as NarrowByType<LuaStatement, "LocalFunction">;
65
+ export const asFunctionCallStmt = (s: LuaStatement) =>
66
+ s as NarrowByType<LuaStatement, "FunctionCallStatement">;
67
+ export const asReturn = (s: LuaStatement) =>
68
+ s as NarrowByType<LuaStatement, "Return">;
69
+ export const asFor = (s: LuaStatement) =>
70
+ s as NarrowByType<LuaStatement, "For">;
71
+ export const asForIn = (s: LuaStatement) =>
72
+ s as NarrowByType<LuaStatement, "ForIn">;
73
+ export const asLabel = (s: LuaStatement) =>
74
+ s as NarrowByType<LuaStatement, "Label">;
75
+ export const asGoto = (s: LuaStatement) =>
76
+ s as NarrowByType<LuaStatement, "Goto">;
77
+ export const asSemicolon = (s: LuaStatement) =>
78
+ s as NarrowByType<LuaStatement, "Semicolon">;
79
+
80
+ // Pull ctx with a single shape
81
+ export const ctxOf = (node: { ctx: ASTCtx }): ASTCtx => node.ctx;