@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.
- package/LICENSE.md +18 -0
- package/README.md +98 -0
- package/client/asset_bundle/bundle.ts +95 -0
- package/client/data/datastore.ts +85 -0
- package/client/data/kv_primitives.ts +25 -0
- package/client/markdown_parser/constants.ts +13 -0
- package/client/plugos/event.ts +36 -0
- package/client/plugos/eventhook.ts +8 -0
- package/client/plugos/hooks/code_widget.ts +59 -0
- package/client/plugos/hooks/command.ts +104 -0
- package/client/plugos/hooks/document_editor.ts +77 -0
- package/client/plugos/hooks/event.ts +187 -0
- package/client/plugos/hooks/mq.ts +154 -0
- package/client/plugos/hooks/plug_namespace.ts +85 -0
- package/client/plugos/hooks/slash_command.ts +192 -0
- package/client/plugos/hooks/syscall.ts +66 -0
- package/client/plugos/manifest_cache.ts +67 -0
- package/client/plugos/plug.ts +99 -0
- package/client/plugos/plug_compile.ts +202 -0
- package/client/plugos/protocol.ts +40 -0
- package/client/plugos/proxy_fetch.ts +53 -0
- package/client/plugos/sandboxes/deno_worker_sandbox.ts +6 -0
- package/client/plugos/sandboxes/sandbox.ts +14 -0
- package/client/plugos/sandboxes/web_worker_sandbox.ts +17 -0
- package/client/plugos/sandboxes/worker_sandbox.ts +132 -0
- package/client/plugos/syscalls/asset.ts +35 -0
- package/client/plugos/syscalls/clientStore.ts +21 -0
- package/client/plugos/syscalls/client_code_widget.ts +12 -0
- package/client/plugos/syscalls/code_widget.ts +24 -0
- package/client/plugos/syscalls/config.ts +46 -0
- package/client/plugos/syscalls/datastore.ts +89 -0
- package/client/plugos/syscalls/editor.ts +673 -0
- package/client/plugos/syscalls/event.ts +36 -0
- package/client/plugos/syscalls/fetch.ts +128 -0
- package/client/plugos/syscalls/index.ts +102 -0
- package/client/plugos/syscalls/jsonschema.ts +69 -0
- package/client/plugos/syscalls/language.ts +23 -0
- package/client/plugos/syscalls/lua.ts +58 -0
- package/client/plugos/syscalls/markdown.ts +84 -0
- package/client/plugos/syscalls/mq.ts +52 -0
- package/client/plugos/syscalls/service_registry.ts +43 -0
- package/client/plugos/syscalls/shell.ts +39 -0
- package/client/plugos/syscalls/space.ts +139 -0
- package/client/plugos/syscalls/sync.ts +77 -0
- package/client/plugos/syscalls/system.ts +150 -0
- package/client/plugos/system.ts +201 -0
- package/client/plugos/types.ts +60 -0
- package/client/plugos/util.ts +14 -0
- package/client/plugos/worker_runtime.ts +195 -0
- package/client/space_lua/ast.ts +328 -0
- package/client/space_lua/ast_narrow.ts +81 -0
- package/client/space_lua/eval.ts +2478 -0
- package/client/space_lua/labels.ts +416 -0
- package/client/space_lua/numeric.ts +240 -0
- package/client/space_lua/parse.ts +1522 -0
- package/client/space_lua/query_collection.ts +232 -0
- package/client/space_lua/rp.ts +27 -0
- package/client/space_lua/runtime.ts +1702 -0
- package/client/space_lua/stdlib/crypto.ts +10 -0
- package/client/space_lua/stdlib/encoding.ts +19 -0
- package/client/space_lua/stdlib/format.ts +770 -0
- package/client/space_lua/stdlib/js.ts +73 -0
- package/client/space_lua/stdlib/load.ts +52 -0
- package/client/space_lua/stdlib/math.ts +193 -0
- package/client/space_lua/stdlib/net.ts +113 -0
- package/client/space_lua/stdlib/os.ts +368 -0
- package/client/space_lua/stdlib/space_lua.ts +153 -0
- package/client/space_lua/stdlib/string.ts +286 -0
- package/client/space_lua/stdlib/table.ts +401 -0
- package/client/space_lua/stdlib.ts +489 -0
- package/client/space_lua/tonumber.ts +501 -0
- package/client/space_lua/util.ts +96 -0
- package/dist/plug-compile.js +1513 -0
- package/package.json +120 -0
- package/plug-api/constants.ts +42 -0
- package/plug-api/lib/async.ts +162 -0
- package/plug-api/lib/crypto.ts +202 -0
- package/plug-api/lib/dates.ts +13 -0
- package/plug-api/lib/json.ts +136 -0
- package/plug-api/lib/limited_map.ts +72 -0
- package/plug-api/lib/memory_cache.ts +21 -0
- package/plug-api/lib/native_fetch.ts +6 -0
- package/plug-api/lib/ref.ts +275 -0
- package/plug-api/lib/resolve.ts +90 -0
- package/plug-api/lib/tags.ts +15 -0
- package/plug-api/lib/transclusion.ts +122 -0
- package/plug-api/lib/tree.ts +232 -0
- package/plug-api/lib/yaml.ts +284 -0
- package/plug-api/syscall.ts +15 -0
- package/plug-api/syscalls/asset.ts +36 -0
- package/plug-api/syscalls/client_store.ts +33 -0
- package/plug-api/syscalls/code_widget.ts +8 -0
- package/plug-api/syscalls/config.ts +58 -0
- package/plug-api/syscalls/datastore.ts +96 -0
- package/plug-api/syscalls/editor.ts +517 -0
- package/plug-api/syscalls/event.ts +47 -0
- package/plug-api/syscalls/index.ts +77 -0
- package/plug-api/syscalls/jsonschema.ts +25 -0
- package/plug-api/syscalls/language.ts +23 -0
- package/plug-api/syscalls/lua.ts +20 -0
- package/plug-api/syscalls/markdown.ts +38 -0
- package/plug-api/syscalls/mq.ts +79 -0
- package/plug-api/syscalls/shell.ts +14 -0
- package/plug-api/syscalls/space.ts +212 -0
- package/plug-api/syscalls/sync.ts +28 -0
- package/plug-api/syscalls/system.ts +102 -0
- package/plug-api/syscalls/yaml.ts +28 -0
- package/plug-api/syscalls.ts +21 -0
- package/plug-api/system_mock.ts +89 -0
- package/plug-api/types/client.ts +116 -0
- package/plug-api/types/config.ts +22 -0
- package/plug-api/types/datastore.ts +28 -0
- package/plug-api/types/event.ts +27 -0
- package/plug-api/types/index.ts +56 -0
- package/plug-api/types/manifest.ts +98 -0
- package/plug-api/types/namespace.ts +6 -0
- package/plugs/builtin_plugs.ts +14 -0
|
@@ -0,0 +1,501 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Space Lua `tonumber` implementation
|
|
3
|
+
*
|
|
4
|
+
* Matches Lua 5.4 semantics:
|
|
5
|
+
* - parses decimal or hex numerals
|
|
6
|
+
* - if base is given parses signed integers in the given base (2..36)
|
|
7
|
+
* - leading and trailing Lua spaces are trimmed (`\t\r\n\h\v`)
|
|
8
|
+
* - returns null on failure
|
|
9
|
+
*
|
|
10
|
+
* Notes:
|
|
11
|
+
* - hex without exponent is an integer
|
|
12
|
+
* - hex float requires `p` or `P` exponent
|
|
13
|
+
* - decimal float allows '.' and `e` or `E` exponent
|
|
14
|
+
*/
|
|
15
|
+
import type { NumericType } from "./ast.ts";
|
|
16
|
+
|
|
17
|
+
function skipSpace(s: string, i: number): number {
|
|
18
|
+
const n = s.length;
|
|
19
|
+
while (i < n) {
|
|
20
|
+
const c = s.charCodeAt(i);
|
|
21
|
+
if (c === 32 || (c >= 9 && c <= 13)) { // SP, HT, LF, VT, FF, CR
|
|
22
|
+
i++;
|
|
23
|
+
} else {
|
|
24
|
+
break;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return i;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function charToDigitBase(c: number, base: number): number {
|
|
31
|
+
if (c >= 48 && c <= 57) { // '0'..'9'
|
|
32
|
+
const v = c - 48;
|
|
33
|
+
if (v < base) {
|
|
34
|
+
return v;
|
|
35
|
+
}
|
|
36
|
+
return -1;
|
|
37
|
+
}
|
|
38
|
+
if (c >= 65 && c <= 90) { // 'A'..'Z'
|
|
39
|
+
const v = 10 + (c - 65);
|
|
40
|
+
if (v < base) {
|
|
41
|
+
return v;
|
|
42
|
+
}
|
|
43
|
+
return -1;
|
|
44
|
+
}
|
|
45
|
+
if (c >= 97 && c <= 122) { // 'a'..'z'
|
|
46
|
+
const v = 10 + (c - 97);
|
|
47
|
+
if (v < base) {
|
|
48
|
+
return v;
|
|
49
|
+
}
|
|
50
|
+
return -1;
|
|
51
|
+
}
|
|
52
|
+
return -1;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function parseIntWithBase(
|
|
56
|
+
s: string,
|
|
57
|
+
base: number,
|
|
58
|
+
): { ok: boolean; end: number; value: number } {
|
|
59
|
+
const n = s.length;
|
|
60
|
+
let i = 0;
|
|
61
|
+
i = skipSpace(s, i);
|
|
62
|
+
if (i >= n) {
|
|
63
|
+
return { ok: false, end: i, value: 0 };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
let sign = 1;
|
|
67
|
+
if (s.charCodeAt(i) === 45) { // '-'
|
|
68
|
+
sign = -1;
|
|
69
|
+
i++;
|
|
70
|
+
} else if (s.charCodeAt(i) === 43) { // '+'
|
|
71
|
+
i++;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (i >= n) {
|
|
75
|
+
return { ok: false, end: i, value: 0 };
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
let acc = 0;
|
|
79
|
+
let any = false;
|
|
80
|
+
|
|
81
|
+
while (i < n) {
|
|
82
|
+
const c = s.charCodeAt(i);
|
|
83
|
+
const isAlnum = (c >= 48 && c <= 57) || // '0'..'9'
|
|
84
|
+
(c >= 65 && c <= 90) || // 'A'..'Z'
|
|
85
|
+
(c >= 97 && c <= 122); // 'a'..'z'
|
|
86
|
+
|
|
87
|
+
if (!isAlnum) {
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const d = charToDigitBase(c, base);
|
|
92
|
+
if (d < 0) {
|
|
93
|
+
return { ok: false, end: i, value: 0 };
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
acc = acc * base + d;
|
|
97
|
+
any = true;
|
|
98
|
+
i++;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (!any) {
|
|
102
|
+
return { ok: false, end: i, value: 0 };
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
i = skipSpace(s, i);
|
|
106
|
+
if (i !== n) {
|
|
107
|
+
return { ok: false, end: i, value: 0 };
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return { ok: true, end: i, value: sign * acc };
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function parseInt(s: string): { ok: boolean; value: number } {
|
|
114
|
+
const n = s.length;
|
|
115
|
+
let i = 0;
|
|
116
|
+
i = skipSpace(s, i);
|
|
117
|
+
if (i >= n) {
|
|
118
|
+
return { ok: false, value: 0 };
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
let neg = false;
|
|
122
|
+
if (s.charCodeAt(i) === 45) { // '-'
|
|
123
|
+
neg = true;
|
|
124
|
+
i++;
|
|
125
|
+
} else if (s.charCodeAt(i) === 43) { // '+'
|
|
126
|
+
i++;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (i >= n) {
|
|
130
|
+
return { ok: false, value: 0 };
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
let acc = 0;
|
|
134
|
+
let any = false;
|
|
135
|
+
|
|
136
|
+
// hex?
|
|
137
|
+
if (s.charCodeAt(i) === 48 && i + 1 < n) { // '0'
|
|
138
|
+
const x = s.charCodeAt(i + 1);
|
|
139
|
+
if (x === 120 || x === 88) { // 'x' or 'X'
|
|
140
|
+
i += 2;
|
|
141
|
+
while (i < n) {
|
|
142
|
+
const c = s.charCodeAt(i);
|
|
143
|
+
let d = -1;
|
|
144
|
+
if (c >= 48 && c <= 57) { // '0'..'9'
|
|
145
|
+
d = c - 48; // '0'
|
|
146
|
+
} else if (c >= 65 && c <= 70) { // 'A'..'F'
|
|
147
|
+
d = 10 + (c - 65);
|
|
148
|
+
} else if (c >= 97 && c <= 102) { // 'a'..'f'
|
|
149
|
+
d = 10 + (c - 97);
|
|
150
|
+
} else {
|
|
151
|
+
d = -1;
|
|
152
|
+
}
|
|
153
|
+
if (d < 0) {
|
|
154
|
+
break;
|
|
155
|
+
}
|
|
156
|
+
acc = acc * 16 + d;
|
|
157
|
+
any = true;
|
|
158
|
+
i++;
|
|
159
|
+
}
|
|
160
|
+
i = skipSpace(s, i);
|
|
161
|
+
if (!any || i !== n) {
|
|
162
|
+
return { ok: false, value: 0 };
|
|
163
|
+
}
|
|
164
|
+
return { ok: true, value: neg ? -acc : acc };
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// decimal integer
|
|
169
|
+
while (i < n) {
|
|
170
|
+
const c = s.charCodeAt(i);
|
|
171
|
+
if (c < 48 || c > 57) { // not '0'..'9'
|
|
172
|
+
break;
|
|
173
|
+
}
|
|
174
|
+
acc = acc * 10 + (c - 48);
|
|
175
|
+
any = true;
|
|
176
|
+
i++;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
i = skipSpace(s, i);
|
|
180
|
+
if (!any || i !== n) {
|
|
181
|
+
return { ok: false, value: 0 };
|
|
182
|
+
}
|
|
183
|
+
return { ok: true, value: neg ? -acc : acc };
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function parseDecFloat(s: string): { ok: boolean; value: number } {
|
|
187
|
+
const n = s.length;
|
|
188
|
+
let i = 0;
|
|
189
|
+
i = skipSpace(s, i);
|
|
190
|
+
if (i >= n) {
|
|
191
|
+
return { ok: false, value: 0 };
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
let sign = 1;
|
|
195
|
+
const c0 = s.charCodeAt(i);
|
|
196
|
+
if (c0 === 45) { // '-'
|
|
197
|
+
sign = -1;
|
|
198
|
+
i++;
|
|
199
|
+
} else if (c0 === 43) { // '+'
|
|
200
|
+
i++;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
let intAny = false;
|
|
204
|
+
let fracAny = false;
|
|
205
|
+
let val = 0;
|
|
206
|
+
|
|
207
|
+
// integer part
|
|
208
|
+
while (i < n) {
|
|
209
|
+
const c = s.charCodeAt(i);
|
|
210
|
+
if (c < 48 || c > 57) { // not '0'..'9'
|
|
211
|
+
break;
|
|
212
|
+
}
|
|
213
|
+
val = val * 10 + (c - 48);
|
|
214
|
+
intAny = true;
|
|
215
|
+
i++;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// fractional part
|
|
219
|
+
if (i < n) {
|
|
220
|
+
if (s.charCodeAt(i) === 46) { // '.'
|
|
221
|
+
i++;
|
|
222
|
+
let scale = 1;
|
|
223
|
+
while (i < n) {
|
|
224
|
+
const c = s.charCodeAt(i);
|
|
225
|
+
if (c < 48 || c > 57) { // not '0'..'9'
|
|
226
|
+
break;
|
|
227
|
+
}
|
|
228
|
+
scale *= 0.1;
|
|
229
|
+
val += (c - 48) * scale;
|
|
230
|
+
fracAny = true;
|
|
231
|
+
i++;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// exponent
|
|
237
|
+
let exp = 0;
|
|
238
|
+
let hasExp = false;
|
|
239
|
+
if (i < n) {
|
|
240
|
+
const ec = s.charCodeAt(i);
|
|
241
|
+
if (ec === 101 || ec === 69) { // 'e' or 'E'
|
|
242
|
+
hasExp = true;
|
|
243
|
+
i++;
|
|
244
|
+
if (i >= n) {
|
|
245
|
+
return { ok: false, value: 0 };
|
|
246
|
+
}
|
|
247
|
+
let expSign = 1;
|
|
248
|
+
if (i < n) {
|
|
249
|
+
const es = s.charCodeAt(i);
|
|
250
|
+
if (es === 45) { // '-'
|
|
251
|
+
expSign = -1;
|
|
252
|
+
i++;
|
|
253
|
+
} else if (es === 43) { // '+'
|
|
254
|
+
i++;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
if (i >= n) {
|
|
258
|
+
return { ok: false, value: 0 };
|
|
259
|
+
}
|
|
260
|
+
let anyExp = false;
|
|
261
|
+
while (i < n) {
|
|
262
|
+
const c = s.charCodeAt(i);
|
|
263
|
+
if (c < 48 || c > 57) { // not '0'..'9'
|
|
264
|
+
break;
|
|
265
|
+
}
|
|
266
|
+
exp = exp * 10 + (c - 48);
|
|
267
|
+
anyExp = true;
|
|
268
|
+
i++;
|
|
269
|
+
}
|
|
270
|
+
if (!anyExp) {
|
|
271
|
+
return { ok: false, value: 0 };
|
|
272
|
+
}
|
|
273
|
+
exp *= expSign;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
if (!intAny && !fracAny) {
|
|
278
|
+
return { ok: false, value: 0 };
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
i = skipSpace(s, i);
|
|
282
|
+
if (i !== n) {
|
|
283
|
+
return { ok: false, value: 0 };
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
const result = sign * (hasExp ? val * Math.pow(10, exp) : val);
|
|
287
|
+
return { ok: true, value: result };
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
function parseHexFloat(s: string): { ok: boolean; value: number } {
|
|
291
|
+
const n = s.length;
|
|
292
|
+
let i = 0;
|
|
293
|
+
i = skipSpace(s, i);
|
|
294
|
+
if (i >= n) {
|
|
295
|
+
return { ok: false, value: 0 };
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
let sign = 1;
|
|
299
|
+
const c0 = s.charCodeAt(i);
|
|
300
|
+
if (c0 === 45) { // '-'
|
|
301
|
+
sign = -1;
|
|
302
|
+
i++;
|
|
303
|
+
} else if (c0 === 43) { // '+'
|
|
304
|
+
i++;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
if (!(i + 1 < n && s.charCodeAt(i) === 48)) { // '0'
|
|
308
|
+
return { ok: false, value: 0 };
|
|
309
|
+
}
|
|
310
|
+
const x = s.charCodeAt(i + 1);
|
|
311
|
+
if (!(x === 120 || x === 88)) { // 'x' or 'X'
|
|
312
|
+
return { ok: false, value: 0 };
|
|
313
|
+
}
|
|
314
|
+
i += 2;
|
|
315
|
+
|
|
316
|
+
let intVal = 0;
|
|
317
|
+
let fracVal = 0;
|
|
318
|
+
let fracScale = 1;
|
|
319
|
+
let anyHex = false;
|
|
320
|
+
let sawDot = false;
|
|
321
|
+
|
|
322
|
+
// integer hex digits
|
|
323
|
+
while (i < n) {
|
|
324
|
+
const c = s.charCodeAt(i);
|
|
325
|
+
let d = -1;
|
|
326
|
+
if (c >= 48 && c <= 57) { // '0'..'9'
|
|
327
|
+
d = c - 48;
|
|
328
|
+
} else if (c >= 65 && c <= 70) { // 'A'..'F'
|
|
329
|
+
d = 10 + (c - 65);
|
|
330
|
+
} else if (c >= 97 && c <= 102) { // 'a'..'f'
|
|
331
|
+
d = 10 + (c - 97);
|
|
332
|
+
} else {
|
|
333
|
+
d = -1;
|
|
334
|
+
}
|
|
335
|
+
if (d < 0) {
|
|
336
|
+
break;
|
|
337
|
+
}
|
|
338
|
+
intVal = intVal * 16 + d;
|
|
339
|
+
anyHex = true;
|
|
340
|
+
i++;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// optional fractional part
|
|
344
|
+
if (i < n) {
|
|
345
|
+
if (s.charCodeAt(i) === 46) { // '.'
|
|
346
|
+
sawDot = true;
|
|
347
|
+
i++;
|
|
348
|
+
while (i < n) {
|
|
349
|
+
const c = s.charCodeAt(i);
|
|
350
|
+
let d = -1;
|
|
351
|
+
if (c >= 48 && c <= 57) { // '0'..'9'
|
|
352
|
+
d = c - 48;
|
|
353
|
+
} else if (c >= 65 && c <= 70) { // 'A'..'F'
|
|
354
|
+
d = 10 + (c - 65);
|
|
355
|
+
} else if (c >= 97 && c <= 102) { // 'a'..'f'
|
|
356
|
+
d = 10 + (c - 97);
|
|
357
|
+
} else {
|
|
358
|
+
d = -1;
|
|
359
|
+
}
|
|
360
|
+
if (d < 0) {
|
|
361
|
+
break;
|
|
362
|
+
}
|
|
363
|
+
fracScale *= 16;
|
|
364
|
+
fracVal = fracVal * 16 + d;
|
|
365
|
+
anyHex = true;
|
|
366
|
+
i++;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// exponent:
|
|
372
|
+
// - required if there is no dot (so `0x10` stays an integer),
|
|
373
|
+
// - optional if there was a dot (`0x1.2` means `0x1.2p0`).
|
|
374
|
+
let expSign = 1;
|
|
375
|
+
let exp = 0;
|
|
376
|
+
|
|
377
|
+
if (i < n) {
|
|
378
|
+
const ec = s.charCodeAt(i);
|
|
379
|
+
if (ec === 112 || ec === 80) { // 'p' or 'P'
|
|
380
|
+
i++;
|
|
381
|
+
if (i < n) {
|
|
382
|
+
const sc = s.charCodeAt(i);
|
|
383
|
+
if (sc === 45) { // '-'
|
|
384
|
+
expSign = -1;
|
|
385
|
+
i++;
|
|
386
|
+
} else if (sc === 43) { // '+'
|
|
387
|
+
i++;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
if (i >= n) {
|
|
391
|
+
return { ok: false, value: 0 };
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
let anyExp = false;
|
|
395
|
+
while (i < n) {
|
|
396
|
+
const c = s.charCodeAt(i);
|
|
397
|
+
if (c < 48 || c > 57) { // not '0'..'9'
|
|
398
|
+
break;
|
|
399
|
+
}
|
|
400
|
+
exp = exp * 10 + (c - 48);
|
|
401
|
+
anyExp = true;
|
|
402
|
+
i++;
|
|
403
|
+
}
|
|
404
|
+
if (!anyHex || !anyExp) {
|
|
405
|
+
return { ok: false, value: 0 };
|
|
406
|
+
}
|
|
407
|
+
} else {
|
|
408
|
+
// no exponent marker
|
|
409
|
+
if (!sawDot) {
|
|
410
|
+
// without dot we must reject so parseInt can claim it as integer
|
|
411
|
+
return { ok: false, value: 0 };
|
|
412
|
+
}
|
|
413
|
+
if (!anyHex) {
|
|
414
|
+
return { ok: false, value: 0 };
|
|
415
|
+
}
|
|
416
|
+
expSign = 1;
|
|
417
|
+
exp = 0; // implicit p0
|
|
418
|
+
}
|
|
419
|
+
} else {
|
|
420
|
+
// end of string
|
|
421
|
+
if (!sawDot) {
|
|
422
|
+
return { ok: false, value: 0 };
|
|
423
|
+
}
|
|
424
|
+
if (!anyHex) {
|
|
425
|
+
return { ok: false, value: 0 };
|
|
426
|
+
}
|
|
427
|
+
expSign = 1;
|
|
428
|
+
exp = 0;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
i = skipSpace(s, i);
|
|
432
|
+
if (i !== n) {
|
|
433
|
+
return { ok: false, value: 0 };
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
const frac = fracVal === 0 ? 0 : (fracVal / fracScale);
|
|
437
|
+
const result = sign * (intVal + frac) * Math.pow(2, expSign * exp);
|
|
438
|
+
return { ok: true, value: result };
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
// Detailed string conversion that returns numeric type, returns null
|
|
442
|
+
// on failure, integer -0 is canonicalized to +0
|
|
443
|
+
export function luaToNumberDetailed(
|
|
444
|
+
s: string,
|
|
445
|
+
base?: number,
|
|
446
|
+
): { value: number; numericType: NumericType } | null {
|
|
447
|
+
if (base !== undefined) {
|
|
448
|
+
// Base range errors are handled by the stdlib `tonumber` builtin,
|
|
449
|
+
// to match Lua's "bad argument #2 ..." error message.
|
|
450
|
+
if (!(typeof base === "number" && base >= 2 && base <= 36)) {
|
|
451
|
+
return null;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
const parsed = parseIntWithBase(s, base);
|
|
455
|
+
if (parsed.ok) {
|
|
456
|
+
const v = parsed.value;
|
|
457
|
+
return { value: v === 0 ? 0 : v, numericType: "int" };
|
|
458
|
+
}
|
|
459
|
+
return null;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
{
|
|
463
|
+
const parsed = parseInt(s);
|
|
464
|
+
if (parsed.ok) {
|
|
465
|
+
const v = parsed.value;
|
|
466
|
+
return { value: v === 0 ? 0 : v, numericType: "int" };
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
{
|
|
471
|
+
const parsed = parseHexFloat(s);
|
|
472
|
+
if (parsed.ok) {
|
|
473
|
+
return { value: parsed.value, numericType: "float" };
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
{
|
|
478
|
+
const parsed = parseDecFloat(s);
|
|
479
|
+
if (parsed.ok) {
|
|
480
|
+
return { value: parsed.value, numericType: "float" };
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
return null;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
// Space Lua `tonumber` returning only the numeric value or null
|
|
488
|
+
export function luaToNumber(s: unknown, base?: number): number | null {
|
|
489
|
+
if (typeof s === "number") {
|
|
490
|
+
return s;
|
|
491
|
+
}
|
|
492
|
+
// Tagged float: { value: number, isFloat: true }
|
|
493
|
+
if (s !== null && typeof s === "object" && (s as any).isFloat === true) {
|
|
494
|
+
return (s as any).value;
|
|
495
|
+
}
|
|
496
|
+
if (typeof s !== "string") {
|
|
497
|
+
return null;
|
|
498
|
+
}
|
|
499
|
+
const detailed = luaToNumberDetailed(s, base);
|
|
500
|
+
return detailed ? detailed.value : null;
|
|
501
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { isPromise } from "./rp.ts";
|
|
2
|
+
|
|
3
|
+
export function evalPromiseValues(vals: any[]): Promise<any[]> | any[] {
|
|
4
|
+
const promises = [];
|
|
5
|
+
const promiseResults = new Array(vals.length);
|
|
6
|
+
for (let i = 0; i < vals.length; i++) {
|
|
7
|
+
if (isPromise(vals[i])) {
|
|
8
|
+
promises.push(
|
|
9
|
+
(vals[i] as Promise<any>).then((v: any) => promiseResults[i] = v),
|
|
10
|
+
);
|
|
11
|
+
} else {
|
|
12
|
+
promiseResults[i] = vals[i];
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
if (promises.length === 0) {
|
|
16
|
+
return promiseResults;
|
|
17
|
+
} else {
|
|
18
|
+
return Promise.all(promises).then(() => promiseResults);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* return the mid value among x, y, and z
|
|
24
|
+
* @param x
|
|
25
|
+
* @param y
|
|
26
|
+
* @param z
|
|
27
|
+
* @param compare
|
|
28
|
+
* @returns {Promise.<*>}
|
|
29
|
+
*/
|
|
30
|
+
async function getPivot(
|
|
31
|
+
x: any,
|
|
32
|
+
y: any,
|
|
33
|
+
z: any,
|
|
34
|
+
compare: (a: any, b: any) => Promise<number>,
|
|
35
|
+
) {
|
|
36
|
+
if (await compare(x, y) < 0) {
|
|
37
|
+
if (await compare(y, z) < 0) {
|
|
38
|
+
return y;
|
|
39
|
+
} else if (await compare(z, x) < 0) {
|
|
40
|
+
return x;
|
|
41
|
+
} else {
|
|
42
|
+
return z;
|
|
43
|
+
}
|
|
44
|
+
} else if (await compare(y, z) > 0) {
|
|
45
|
+
return y;
|
|
46
|
+
} else if (await compare(z, x) > 0) {
|
|
47
|
+
return x;
|
|
48
|
+
} else {
|
|
49
|
+
return z;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* asynchronous quick sort
|
|
55
|
+
* @param arr array to sort
|
|
56
|
+
* @param compare asynchronous comparing function
|
|
57
|
+
* @param left index where the range of elements to be sorted starts
|
|
58
|
+
* @param right index where the range of elements to be sorted ends
|
|
59
|
+
* @returns {Promise.<*>}
|
|
60
|
+
*/
|
|
61
|
+
export async function asyncQuickSort(
|
|
62
|
+
arr: any[],
|
|
63
|
+
compare: (a: any, b: any) => Promise<number>,
|
|
64
|
+
left = 0,
|
|
65
|
+
right = arr.length - 1,
|
|
66
|
+
) {
|
|
67
|
+
if (left < right) {
|
|
68
|
+
let i = left, j = right, tmp;
|
|
69
|
+
const pivot = await getPivot(
|
|
70
|
+
arr[i],
|
|
71
|
+
arr[i + Math.floor((j - i) / 2)],
|
|
72
|
+
arr[j],
|
|
73
|
+
compare,
|
|
74
|
+
);
|
|
75
|
+
while (true) {
|
|
76
|
+
while (await compare(arr[i], pivot) < 0) {
|
|
77
|
+
i++;
|
|
78
|
+
}
|
|
79
|
+
while (await compare(pivot, arr[j]) < 0) {
|
|
80
|
+
j--;
|
|
81
|
+
}
|
|
82
|
+
if (i >= j) {
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
tmp = arr[i];
|
|
86
|
+
arr[i] = arr[j];
|
|
87
|
+
arr[j] = tmp;
|
|
88
|
+
|
|
89
|
+
i++;
|
|
90
|
+
j--;
|
|
91
|
+
}
|
|
92
|
+
await asyncQuickSort(arr, compare, left, i - 1);
|
|
93
|
+
await asyncQuickSort(arr, compare, j + 1, right);
|
|
94
|
+
}
|
|
95
|
+
return arr;
|
|
96
|
+
}
|