numbl 0.1.2 → 0.1.3

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/dist-cli/cli.js CHANGED
@@ -195,6 +195,179 @@ var kstr = (value) => {
195
195
  return "unknown";
196
196
  };
197
197
 
198
+ // src/numbl-core/native/lapack-bridge.ts
199
+ var NATIVE_ADDON_EXPECTED_VERSION = 1;
200
+ var _bridge = null;
201
+ function setLapackBridge(bridge) {
202
+ _bridge = bridge;
203
+ }
204
+ function getLapackBridge() {
205
+ return _bridge;
206
+ }
207
+
208
+ // src/numbl-core/runtime/constructors.ts
209
+ var RTV = {
210
+ num(value) {
211
+ return value;
212
+ },
213
+ tensor(data, shape, imag) {
214
+ const d = data instanceof FloatXArray ? data : new FloatXArray(data);
215
+ const im2 = imag ? imag instanceof FloatXArray ? imag : new FloatXArray(imag) : void 0;
216
+ const s = [...shape];
217
+ while (s.length > 2 && s[s.length - 1] === 1) s.pop();
218
+ return { kind: "tensor", data: d, imag: im2, shape: s, _rc: 1 };
219
+ },
220
+ /** Fast tensor constructor — data must be FloatXArray, shape already normalized (no trailing singletons). */
221
+ tensorRaw(data, shape) {
222
+ return { kind: "tensor", data, imag: void 0, shape, _rc: 1 };
223
+ },
224
+ /** Create a scalar tensor (1x1) */
225
+ scalar(value) {
226
+ return value;
227
+ },
228
+ /** Create a row vector [1 x n] */
229
+ row(data, imag) {
230
+ const im2 = imag ? new FloatXArray(imag) : void 0;
231
+ return {
232
+ kind: "tensor",
233
+ data: new FloatXArray(data),
234
+ imag: im2,
235
+ shape: [1, data.length],
236
+ _rc: 1
237
+ };
238
+ },
239
+ /** Create a column vector [n x 1] */
240
+ col(data, imag) {
241
+ const im2 = imag ? new FloatXArray(imag) : void 0;
242
+ return {
243
+ kind: "tensor",
244
+ data: new FloatXArray(data),
245
+ imag: im2,
246
+ shape: [data.length, 1],
247
+ _rc: 1
248
+ };
249
+ },
250
+ /** Create a matrix from row-major data */
251
+ matrix(rows, cols, data, imag) {
252
+ const d = data instanceof FloatXArray ? data : new FloatXArray(data);
253
+ const im2 = imag ? imag instanceof FloatXArray ? imag : new FloatXArray(imag) : void 0;
254
+ return { kind: "tensor", data: d, imag: im2, shape: [rows, cols], _rc: 1 };
255
+ },
256
+ string(value) {
257
+ return value;
258
+ },
259
+ char(value) {
260
+ return { kind: "char", value };
261
+ },
262
+ logical(value) {
263
+ return value;
264
+ },
265
+ cell(data, shape) {
266
+ return { kind: "cell", data, shape: [...shape], _rc: 1 };
267
+ },
268
+ struct(fields) {
269
+ const map = fields instanceof Map ? fields : new Map(Object.entries(fields));
270
+ return { kind: "struct", fields: map };
271
+ },
272
+ func(name, impl, captures = []) {
273
+ return { kind: "function", name, impl, captures };
274
+ },
275
+ classInstance(className, propertyNames, isHandleClass2 = false, defaults) {
276
+ const fields = /* @__PURE__ */ new Map();
277
+ for (const name of propertyNames) {
278
+ fields.set(
279
+ name,
280
+ defaults?.get(name) ?? RTV.tensor(new FloatXArray(0), [0, 0])
281
+ );
282
+ }
283
+ return {
284
+ kind: "class_instance",
285
+ className,
286
+ fields,
287
+ isHandleClass: isHandleClass2
288
+ };
289
+ },
290
+ complex(re2, im2) {
291
+ return { kind: "complex_number", re: re2, im: im2 };
292
+ },
293
+ dummyHandle() {
294
+ return { kind: "dummy_handle" };
295
+ },
296
+ structArray(fieldNames, elements) {
297
+ return { kind: "struct_array", fieldNames, elements };
298
+ },
299
+ sparseMatrix(m, n, ir, jc, pr, pi) {
300
+ return { kind: "sparse_matrix", m, n, ir, jc, pr, pi, _rc: 1 };
301
+ },
302
+ dictionary(entries, keyType, valueType) {
303
+ return {
304
+ kind: "dictionary",
305
+ entries: entries ?? /* @__PURE__ */ new Map(),
306
+ keyType,
307
+ valueType
308
+ };
309
+ }
310
+ };
311
+ var getItemTypeFromRuntimeValue = (value) => {
312
+ if (isRuntimeNumber(value)) {
313
+ return { kind: "Number" };
314
+ }
315
+ if (isRuntimeLogical(value)) {
316
+ return { kind: "Boolean" };
317
+ }
318
+ if (isRuntimeString(value)) {
319
+ return { kind: "String" };
320
+ }
321
+ switch (value.kind) {
322
+ case "complex_number":
323
+ return { kind: "ComplexNumber" };
324
+ case "char":
325
+ return { kind: "Char" };
326
+ case "tensor":
327
+ return {
328
+ kind: "Tensor",
329
+ isComplex: value.imag !== void 0,
330
+ isLogical: value._isLogical || void 0
331
+ };
332
+ case "cell":
333
+ return {
334
+ kind: "Cell",
335
+ elementType: value.data.length > 0 ? getItemTypeFromRuntimeValue(value.data[0]) : { kind: "Unknown" },
336
+ // length: value.shape.reduce((a, b) => a * b, 1),
337
+ length: "unknown"
338
+ // do not include length or we get too many jits
339
+ };
340
+ case "struct": {
341
+ const knownFields = {};
342
+ for (const [k, v] of value.fields) {
343
+ knownFields[k] = getItemTypeFromRuntimeValue(v);
344
+ }
345
+ return { kind: "Struct", knownFields };
346
+ }
347
+ case "function":
348
+ return {
349
+ kind: "Function",
350
+ params: [],
351
+ returns: { kind: "Unknown" }
352
+ };
353
+ case "class_instance":
354
+ return {
355
+ kind: "ClassInstance",
356
+ className: value.className
357
+ };
358
+ case "dummy_handle":
359
+ return { kind: "DummyHandle" };
360
+ case "struct_array":
361
+ return { kind: "Unknown" };
362
+ case "sparse_matrix":
363
+ return { kind: "SparseMatrix", isComplex: value.pi !== void 0 };
364
+ case "dictionary":
365
+ return { kind: "Dictionary" };
366
+ default:
367
+ return { kind: "Unknown" };
368
+ }
369
+ };
370
+
198
371
  // src/numbl-core/interpreter/jit/jitTypes.ts
199
372
  function signFromNumber(v) {
200
373
  if (v > 0) return "positive";
@@ -637,169 +810,6 @@ function extractSnippet(source, offset, contextLines = 2) {
637
810
  return snippetLines.join("\n");
638
811
  }
639
812
 
640
- // src/numbl-core/runtime/constructors.ts
641
- var RTV = {
642
- num(value) {
643
- return value;
644
- },
645
- tensor(data, shape, imag) {
646
- const d = data instanceof FloatXArray ? data : new FloatXArray(data);
647
- const im2 = imag ? imag instanceof FloatXArray ? imag : new FloatXArray(imag) : void 0;
648
- const s = [...shape];
649
- while (s.length > 2 && s[s.length - 1] === 1) s.pop();
650
- return { kind: "tensor", data: d, imag: im2, shape: s, _rc: 1 };
651
- },
652
- /** Fast tensor constructor — data must be FloatXArray, shape already normalized (no trailing singletons). */
653
- tensorRaw(data, shape) {
654
- return { kind: "tensor", data, imag: void 0, shape, _rc: 1 };
655
- },
656
- /** Create a scalar tensor (1x1) */
657
- scalar(value) {
658
- return value;
659
- },
660
- /** Create a row vector [1 x n] */
661
- row(data, imag) {
662
- const im2 = imag ? new FloatXArray(imag) : void 0;
663
- return {
664
- kind: "tensor",
665
- data: new FloatXArray(data),
666
- imag: im2,
667
- shape: [1, data.length],
668
- _rc: 1
669
- };
670
- },
671
- /** Create a column vector [n x 1] */
672
- col(data, imag) {
673
- const im2 = imag ? new FloatXArray(imag) : void 0;
674
- return {
675
- kind: "tensor",
676
- data: new FloatXArray(data),
677
- imag: im2,
678
- shape: [data.length, 1],
679
- _rc: 1
680
- };
681
- },
682
- /** Create a matrix from row-major data */
683
- matrix(rows, cols, data, imag) {
684
- const d = data instanceof FloatXArray ? data : new FloatXArray(data);
685
- const im2 = imag ? imag instanceof FloatXArray ? imag : new FloatXArray(imag) : void 0;
686
- return { kind: "tensor", data: d, imag: im2, shape: [rows, cols], _rc: 1 };
687
- },
688
- string(value) {
689
- return value;
690
- },
691
- char(value) {
692
- return { kind: "char", value };
693
- },
694
- logical(value) {
695
- return value;
696
- },
697
- cell(data, shape) {
698
- return { kind: "cell", data, shape: [...shape], _rc: 1 };
699
- },
700
- struct(fields) {
701
- const map = fields instanceof Map ? fields : new Map(Object.entries(fields));
702
- return { kind: "struct", fields: map };
703
- },
704
- func(name, impl, captures = []) {
705
- return { kind: "function", name, impl, captures };
706
- },
707
- classInstance(className, propertyNames, isHandleClass2 = false, defaults) {
708
- const fields = /* @__PURE__ */ new Map();
709
- for (const name of propertyNames) {
710
- fields.set(
711
- name,
712
- defaults?.get(name) ?? RTV.tensor(new FloatXArray(0), [0, 0])
713
- );
714
- }
715
- return {
716
- kind: "class_instance",
717
- className,
718
- fields,
719
- isHandleClass: isHandleClass2
720
- };
721
- },
722
- complex(re2, im2) {
723
- return { kind: "complex_number", re: re2, im: im2 };
724
- },
725
- dummyHandle() {
726
- return { kind: "dummy_handle" };
727
- },
728
- structArray(fieldNames, elements) {
729
- return { kind: "struct_array", fieldNames, elements };
730
- },
731
- sparseMatrix(m, n, ir, jc, pr, pi) {
732
- return { kind: "sparse_matrix", m, n, ir, jc, pr, pi, _rc: 1 };
733
- },
734
- dictionary(entries, keyType, valueType) {
735
- return {
736
- kind: "dictionary",
737
- entries: entries ?? /* @__PURE__ */ new Map(),
738
- keyType,
739
- valueType
740
- };
741
- }
742
- };
743
- var getItemTypeFromRuntimeValue = (value) => {
744
- if (isRuntimeNumber(value)) {
745
- return { kind: "Number" };
746
- }
747
- if (isRuntimeLogical(value)) {
748
- return { kind: "Boolean" };
749
- }
750
- if (isRuntimeString(value)) {
751
- return { kind: "String" };
752
- }
753
- switch (value.kind) {
754
- case "complex_number":
755
- return { kind: "ComplexNumber" };
756
- case "char":
757
- return { kind: "Char" };
758
- case "tensor":
759
- return {
760
- kind: "Tensor",
761
- isComplex: value.imag !== void 0,
762
- isLogical: value._isLogical || void 0
763
- };
764
- case "cell":
765
- return {
766
- kind: "Cell",
767
- elementType: value.data.length > 0 ? getItemTypeFromRuntimeValue(value.data[0]) : { kind: "Unknown" },
768
- // length: value.shape.reduce((a, b) => a * b, 1),
769
- length: "unknown"
770
- // do not include length or we get too many jits
771
- };
772
- case "struct": {
773
- const knownFields = {};
774
- for (const [k, v] of value.fields) {
775
- knownFields[k] = getItemTypeFromRuntimeValue(v);
776
- }
777
- return { kind: "Struct", knownFields };
778
- }
779
- case "function":
780
- return {
781
- kind: "Function",
782
- params: [],
783
- returns: { kind: "Unknown" }
784
- };
785
- case "class_instance":
786
- return {
787
- kind: "ClassInstance",
788
- className: value.className
789
- };
790
- case "dummy_handle":
791
- return { kind: "DummyHandle" };
792
- case "struct_array":
793
- return { kind: "Unknown" };
794
- case "sparse_matrix":
795
- return { kind: "SparseMatrix", isComplex: value.pi !== void 0 };
796
- case "dictionary":
797
- return { kind: "Dictionary" };
798
- default:
799
- return { kind: "Unknown" };
800
- }
801
- };
802
-
803
813
  // src/numbl-core/runtime/utils.ts
804
814
  function tensorSize2D(t) {
805
815
  const s = t.shape;
@@ -1718,6 +1728,28 @@ function binaryNumberOnly(argTypes) {
1718
1728
  return null;
1719
1729
  return [{ kind: "number" }];
1720
1730
  }
1731
+ var nativeUnaryOpCode = /* @__PURE__ */ new Map([
1732
+ [Math.exp, 0],
1733
+ [Math.log, 1],
1734
+ [Math.log2, 2],
1735
+ [Math.log10, 3],
1736
+ [Math.sqrt, 4],
1737
+ [Math.abs, 5],
1738
+ [Math.floor, 6],
1739
+ [Math.ceil, 7],
1740
+ [Math.round, 8],
1741
+ [Math.trunc, 9],
1742
+ [Math.sin, 10],
1743
+ [Math.cos, 11],
1744
+ [Math.tan, 12],
1745
+ [Math.asin, 13],
1746
+ [Math.acos, 14],
1747
+ [Math.atan, 15],
1748
+ [Math.sinh, 16],
1749
+ [Math.cosh, 17],
1750
+ [Math.tanh, 18],
1751
+ [Math.sign, 19]
1752
+ ]);
1721
1753
  function applyUnaryElemwise(v, realFn, complexFn, name) {
1722
1754
  if (isRuntimeSparseMatrix(v))
1723
1755
  return applyUnaryElemwise(sparseToDense(v), realFn, complexFn, name);
@@ -1730,6 +1762,14 @@ function applyUnaryElemwise(v, realFn, complexFn, name) {
1730
1762
  if (isRuntimeTensor(v)) {
1731
1763
  const n = v.data.length;
1732
1764
  if (!v.imag) {
1765
+ const opCode = nativeUnaryOpCode.get(realFn);
1766
+ if (opCode !== void 0) {
1767
+ const bridge = getLapackBridge();
1768
+ if (bridge?.unaryElemwise && v.data instanceof Float64Array) {
1769
+ const result = bridge.unaryElemwise(v.data, opCode);
1770
+ return RTV.tensorRaw(result, v.shape.slice());
1771
+ }
1772
+ }
1733
1773
  const out = new FloatXArray(n);
1734
1774
  for (let i = 0; i < n; i++) out[i] = realFn(v.data[i]);
1735
1775
  return makeTensor(out, void 0, v.shape.slice());
@@ -3618,16 +3658,6 @@ function toString(v) {
3618
3658
  }
3619
3659
  }
3620
3660
 
3621
- // src/numbl-core/native/lapack-bridge.ts
3622
- var NATIVE_ADDON_EXPECTED_VERSION = 1;
3623
- var _bridge = null;
3624
- function setLapackBridge(bridge) {
3625
- _bridge = bridge;
3626
- }
3627
- function getLapackBridge() {
3628
- return _bridge;
3629
- }
3630
-
3631
3661
  // src/ts-lapack/src/utils/xerbla.ts
3632
3662
  function xerbla(srname, info) {
3633
3663
  throw new Error(
@@ -22461,6 +22491,18 @@ function tryNativeElemwiseReal(at, bt, opCode) {
22461
22491
  );
22462
22492
  return RTV.tensorRaw(result, at.shape);
22463
22493
  }
22494
+ function tryNativeElemwiseScalar(scalar, tensor, opCode, scalarOnLeft) {
22495
+ if (tensor.imag) return null;
22496
+ const bridge = getLapackBridge();
22497
+ if (!bridge?.elemwiseScalar) return null;
22498
+ const result = bridge.elemwiseScalar(
22499
+ scalar,
22500
+ tensor.data,
22501
+ opCode,
22502
+ scalarOnLeft
22503
+ );
22504
+ return RTV.tensorRaw(result, tensor.shape);
22505
+ }
22464
22506
  function tensorElemwiseComplex(at, bt, opCode, jsOp) {
22465
22507
  const bridge = getLapackBridge();
22466
22508
  if (bridge?.elemwiseComplex) {
@@ -22531,6 +22573,13 @@ function mAdd(a, b) {
22531
22573
  im: aIm + bIm
22532
22574
  }));
22533
22575
  }
22576
+ if (isRuntimeNumber(a) && isRuntimeTensor(b)) {
22577
+ const nr = tryNativeElemwiseScalar(a, b, ELEMWISE_ADD, true);
22578
+ if (nr) return nr;
22579
+ } else if (isRuntimeTensor(a) && isRuntimeNumber(b)) {
22580
+ const nr = tryNativeElemwiseScalar(b, a, ELEMWISE_ADD, false);
22581
+ if (nr) return nr;
22582
+ }
22534
22583
  return binaryOp(a, b, (x, y) => x + y);
22535
22584
  }
22536
22585
  function mSub(a, b) {
@@ -22563,6 +22612,13 @@ function mSub(a, b) {
22563
22612
  im: aIm - bIm
22564
22613
  }));
22565
22614
  }
22615
+ if (isRuntimeNumber(a) && isRuntimeTensor(b)) {
22616
+ const nr = tryNativeElemwiseScalar(a, b, ELEMWISE_SUB, true);
22617
+ if (nr) return nr;
22618
+ } else if (isRuntimeTensor(a) && isRuntimeNumber(b)) {
22619
+ const nr = tryNativeElemwiseScalar(b, a, ELEMWISE_SUB, false);
22620
+ if (nr) return nr;
22621
+ }
22566
22622
  return binaryOp(a, b, (x, y) => x - y);
22567
22623
  }
22568
22624
  function mMul(a, b) {
@@ -22579,6 +22635,13 @@ function mMul(a, b) {
22579
22635
  im: aRe * bIm + aIm * bRe
22580
22636
  }));
22581
22637
  }
22638
+ if (isRuntimeNumber(a) && isRuntimeTensor(b)) {
22639
+ const nr = tryNativeElemwiseScalar(a, b, ELEMWISE_MUL, true);
22640
+ if (nr) return nr;
22641
+ } else if (isRuntimeTensor(a) && isRuntimeNumber(b)) {
22642
+ const nr = tryNativeElemwiseScalar(b, a, ELEMWISE_MUL, false);
22643
+ if (nr) return nr;
22644
+ }
22582
22645
  return binaryOp(a, b, (x, y) => x * y);
22583
22646
  }
22584
22647
  function mElemMul(a, b) {
@@ -22611,6 +22674,13 @@ function mElemMul(a, b) {
22611
22674
  im: aRe * bIm + aIm * bRe
22612
22675
  }));
22613
22676
  }
22677
+ if (isRuntimeNumber(a) && isRuntimeTensor(b)) {
22678
+ const nr = tryNativeElemwiseScalar(a, b, ELEMWISE_MUL, true);
22679
+ if (nr) return nr;
22680
+ } else if (isRuntimeTensor(a) && isRuntimeNumber(b)) {
22681
+ const nr = tryNativeElemwiseScalar(b, a, ELEMWISE_MUL, false);
22682
+ if (nr) return nr;
22683
+ }
22614
22684
  return binaryOp(a, b, (x, y) => x * y);
22615
22685
  }
22616
22686
  function mDiv(a, b) {
@@ -22649,6 +22719,13 @@ function mElemDiv(a, b) {
22649
22719
  if (isComplexOrMixed(a, b)) {
22650
22720
  return complexBinaryOp(a, b, complexDivide);
22651
22721
  }
22722
+ if (isRuntimeNumber(a) && isRuntimeTensor(b)) {
22723
+ const nr = tryNativeElemwiseScalar(a, b, ELEMWISE_DIV, true);
22724
+ if (nr) return nr;
22725
+ } else if (isRuntimeTensor(a) && isRuntimeNumber(b)) {
22726
+ const nr = tryNativeElemwiseScalar(b, a, ELEMWISE_DIV, false);
22727
+ if (nr) return nr;
22728
+ }
22652
22729
  return binaryOp(a, b, (x, y) => x / y);
22653
22730
  }
22654
22731
  function mLeftDiv(a, b) {
@@ -28565,6 +28642,44 @@ registerIBuiltin({
28565
28642
  }
28566
28643
  })
28567
28644
  });
28645
+ var WEBOPTIONS_DEFAULTS = {
28646
+ CharacterEncoding: RTV.char("auto"),
28647
+ UserAgent: RTV.char("numbl"),
28648
+ Timeout: 5,
28649
+ Username: RTV.char(""),
28650
+ Password: RTV.char(""),
28651
+ KeyName: RTV.char(""),
28652
+ KeyValue: RTV.char(""),
28653
+ ContentType: RTV.char("auto"),
28654
+ MediaType: RTV.char("auto"),
28655
+ RequestMethod: RTV.char("auto"),
28656
+ ArrayFormat: RTV.char("csv"),
28657
+ CertificateFilename: RTV.char("default")
28658
+ };
28659
+ registerIBuiltin({
28660
+ name: "weboptions",
28661
+ resolve: () => ({
28662
+ outputTypes: [{ kind: "struct" }],
28663
+ apply: (args) => {
28664
+ const fields = /* @__PURE__ */ new Map();
28665
+ for (const [k, v] of Object.entries(WEBOPTIONS_DEFAULTS)) {
28666
+ fields.set(k, v);
28667
+ }
28668
+ if (args.length % 2 !== 0)
28669
+ throw new RuntimeError("weboptions: expected name-value pairs");
28670
+ for (let i = 0; i < args.length; i += 2) {
28671
+ const key = args[i];
28672
+ if (!isRuntimeChar(key) && !isRuntimeString(key))
28673
+ throw new RuntimeError("weboptions: option name must be a string");
28674
+ const name = isRuntimeChar(key) ? key.value : key;
28675
+ if (!(name in WEBOPTIONS_DEFAULTS))
28676
+ throw new RuntimeError(`weboptions: unknown option '${name}'`);
28677
+ fields.set(name, args[i + 1]);
28678
+ }
28679
+ return RTV.struct(Object.fromEntries(fields));
28680
+ }
28681
+ })
28682
+ });
28568
28683
  registerIBuiltin({
28569
28684
  name: "odeget",
28570
28685
  resolve: () => ({
@@ -29119,6 +29234,130 @@ registerIBuiltin({
29119
29234
  }
29120
29235
  });
29121
29236
 
29237
+ // src/numbl-core/interpreter/builtins/time-system.ts
29238
+ var ticTime = 0;
29239
+ function getTicTime() {
29240
+ return ticTime;
29241
+ }
29242
+ defineBuiltin({
29243
+ name: "tic",
29244
+ cases: [
29245
+ {
29246
+ match: (argTypes) => argTypes.length === 0 ? [{ kind: "number" }] : null,
29247
+ apply: () => {
29248
+ ticTime = performance.now();
29249
+ return RTV.num(ticTime / 1e3);
29250
+ }
29251
+ }
29252
+ ]
29253
+ });
29254
+ defineBuiltin({
29255
+ name: "clock",
29256
+ cases: [
29257
+ {
29258
+ match: (argTypes) => argTypes.length === 0 ? [{ kind: "tensor", isComplex: false, shape: [1, 6] }] : null,
29259
+ apply: () => {
29260
+ const now = /* @__PURE__ */ new Date();
29261
+ return RTV.tensor(
29262
+ new FloatXArray([
29263
+ now.getFullYear(),
29264
+ now.getMonth() + 1,
29265
+ now.getDate(),
29266
+ now.getHours(),
29267
+ now.getMinutes(),
29268
+ now.getSeconds() + now.getMilliseconds() / 1e3
29269
+ ]),
29270
+ [1, 6]
29271
+ );
29272
+ }
29273
+ }
29274
+ ]
29275
+ });
29276
+ defineBuiltin({
29277
+ name: "etime",
29278
+ cases: [
29279
+ {
29280
+ match: (argTypes) => argTypes.length === 2 ? [{ kind: "number" }] : null,
29281
+ apply: (args) => {
29282
+ const t1 = args[0];
29283
+ const t0 = args[1];
29284
+ if (!isRuntimeTensor(t1) || !isRuntimeTensor(t0))
29285
+ throw new RuntimeError("etime: arguments must be clock vectors");
29286
+ const toMs = (t) => {
29287
+ const d = new Date(
29288
+ t.data[0],
29289
+ t.data[1] - 1,
29290
+ t.data[2],
29291
+ t.data[3],
29292
+ t.data[4],
29293
+ Math.floor(t.data[5]),
29294
+ t.data[5] % 1 * 1e3
29295
+ );
29296
+ return d.getTime();
29297
+ };
29298
+ return RTV.num((toMs(t1) - toMs(t0)) / 1e3);
29299
+ }
29300
+ }
29301
+ ]
29302
+ });
29303
+ defineBuiltin({
29304
+ name: "version",
29305
+ cases: [
29306
+ {
29307
+ match: (argTypes) => argTypes.length === 0 ? [{ kind: "char" }] : null,
29308
+ apply: () => RTV.char("9.14.0")
29309
+ }
29310
+ ]
29311
+ });
29312
+ function getComputerStrings() {
29313
+ if (typeof process === "undefined") {
29314
+ return { str: "BROWSER", arch: "browser" };
29315
+ }
29316
+ const platform = process.platform;
29317
+ const cpuArch = process.arch;
29318
+ if (platform === "win32") return { str: "PCWIN64", arch: "win64" };
29319
+ if (platform === "darwin") {
29320
+ if (cpuArch === "arm64") return { str: "MACA64", arch: "maca64" };
29321
+ return { str: "MACI64", arch: "maci64" };
29322
+ }
29323
+ return { str: "GLNXA64", arch: "glnxa64" };
29324
+ }
29325
+ registerIBuiltin({
29326
+ name: "computer",
29327
+ resolve: () => ({
29328
+ outputTypes: [{ kind: "unknown" }],
29329
+ apply: (args, nargout) => {
29330
+ const info = getComputerStrings();
29331
+ if (args.length >= 1 && isRuntimeChar(args[0])) {
29332
+ const arg = toString(args[0]);
29333
+ if (arg === "arch") return RTV.char(info.arch);
29334
+ throw new RuntimeError(`computer: unknown argument '${arg}'`);
29335
+ }
29336
+ const maxsize = 2 ** 48 - 1;
29337
+ const endian = RTV.char("L");
29338
+ if (nargout <= 1) return RTV.char(info.str);
29339
+ if (nargout === 2) return [RTV.char(info.str), RTV.num(maxsize)];
29340
+ return [RTV.char(info.str), RTV.num(maxsize), endian];
29341
+ }
29342
+ })
29343
+ });
29344
+ var _platform = typeof process !== "undefined" ? process.platform : "linux";
29345
+ for (const [name, val] of [
29346
+ ["ismac", _platform === "darwin"],
29347
+ ["ispc", _platform === "win32"],
29348
+ ["isunix", _platform !== "win32"]
29349
+ ]) {
29350
+ defineBuiltin({
29351
+ name,
29352
+ cases: [
29353
+ {
29354
+ match: (argTypes) => argTypes.length === 0 ? [{ kind: "boolean" }] : null,
29355
+ apply: () => RTV.logical(val)
29356
+ }
29357
+ ]
29358
+ });
29359
+ }
29360
+
29122
29361
  // src/numbl-core/runtime/plotUtils.ts
29123
29362
  var COLOR_SHORT = {
29124
29363
  r: [1, 0, 0],
@@ -31451,7 +31690,8 @@ var SPECIAL_BUILTIN_NAMES = [
31451
31690
  "cd",
31452
31691
  "ode45",
31453
31692
  "ode23",
31454
- "deval"
31693
+ "deval",
31694
+ "toc"
31455
31695
  ];
31456
31696
 
31457
31697
  // src/numbl-core/runtime/specialBuiltins.ts
@@ -31502,6 +31742,14 @@ function registerSpecialBuiltins(rt) {
31502
31742
  }
31503
31743
  return 0;
31504
31744
  });
31745
+ registerSpecial("toc", (nargout) => {
31746
+ const elapsed = (performance.now() - getTicTime()) / 1e3;
31747
+ if (nargout === 0) {
31748
+ rt.output(`Elapsed time is ${elapsed.toFixed(6)} seconds.
31749
+ `);
31750
+ }
31751
+ return RTV.num(elapsed);
31752
+ });
31505
31753
  registerSpecial("warning", (_nargout, args) => {
31506
31754
  if (args.length === 0) return RTV.num(0);
31507
31755
  const margs = args.map((a) => ensureRuntimeValue(a));
@@ -32140,6 +32388,40 @@ function registerSpecialBuiltins(rt) {
32140
32388
  RTV.char("")
32141
32389
  ];
32142
32390
  });
32391
+ function extractWebOptions(arg) {
32392
+ if (!isRuntimeStruct(arg)) return void 0;
32393
+ const s = arg;
32394
+ if (!s.fields.has("Timeout")) return void 0;
32395
+ const opts = {};
32396
+ const t = s.fields.get("Timeout");
32397
+ if (t !== void 0) opts.timeout = toNumber(t);
32398
+ const rm = s.fields.get("RequestMethod");
32399
+ if (rm !== void 0) {
32400
+ const v = toString(rm);
32401
+ if (v !== "auto") opts.requestMethod = v;
32402
+ }
32403
+ const un = s.fields.get("Username");
32404
+ if (un !== void 0) {
32405
+ const v = toString(un);
32406
+ if (v) opts.username = v;
32407
+ }
32408
+ const pw = s.fields.get("Password");
32409
+ if (pw !== void 0) {
32410
+ const v = toString(pw);
32411
+ if (v) opts.password = v;
32412
+ }
32413
+ const kn = s.fields.get("KeyName");
32414
+ if (kn !== void 0) {
32415
+ const v = toString(kn);
32416
+ if (v) opts.keyName = v;
32417
+ }
32418
+ const kv = s.fields.get("KeyValue");
32419
+ if (kv !== void 0) {
32420
+ const v = toString(kv);
32421
+ if (v) opts.keyValue = v;
32422
+ }
32423
+ return opts;
32424
+ }
32143
32425
  registerSpecial("websave", (_nargout, args) => {
32144
32426
  const io = requireFileIO();
32145
32427
  const margs = args.map((a) => ensureRuntimeValue(a));
@@ -32149,8 +32431,14 @@ function registerSpecialBuiltins(rt) {
32149
32431
  throw new RuntimeError("websave is not available in this environment");
32150
32432
  const filename = toString(margs[0]);
32151
32433
  let url = toString(margs[1]);
32434
+ let webOpts;
32435
+ let queryEnd = margs.length;
32436
+ if (margs.length > 2) {
32437
+ webOpts = extractWebOptions(margs[margs.length - 1]);
32438
+ if (webOpts) queryEnd = margs.length - 1;
32439
+ }
32152
32440
  const queryParts = [];
32153
- for (let i = 2; i + 1 < margs.length; i += 2) {
32441
+ for (let i = 2; i + 1 < queryEnd; i += 2) {
32154
32442
  const name = encodeURIComponent(toString(margs[i]));
32155
32443
  const value = encodeURIComponent(toString(margs[i + 1]));
32156
32444
  queryParts.push(`${name}=${value}`);
@@ -32159,7 +32447,7 @@ function registerSpecialBuiltins(rt) {
32159
32447
  const sep = url.includes("?") ? "&" : "?";
32160
32448
  url += sep + queryParts.join("&");
32161
32449
  }
32162
- io.websave(url, filename);
32450
+ io.websave(url, filename, webOpts);
32163
32451
  return RTV.char(filename);
32164
32452
  });
32165
32453
  registerSpecial("webread", (_nargout, args) => {
@@ -32170,8 +32458,14 @@ function registerSpecialBuiltins(rt) {
32170
32458
  if (!io.webread)
32171
32459
  throw new RuntimeError("webread is not available in this environment");
32172
32460
  let url = toString(margs[0]);
32461
+ let webOpts;
32462
+ let queryEnd = margs.length;
32463
+ if (margs.length > 1) {
32464
+ webOpts = extractWebOptions(margs[margs.length - 1]);
32465
+ if (webOpts) queryEnd = margs.length - 1;
32466
+ }
32173
32467
  const queryParts = [];
32174
- for (let i = 1; i + 1 < margs.length; i += 2) {
32468
+ for (let i = 1; i + 1 < queryEnd; i += 2) {
32175
32469
  const name = encodeURIComponent(toString(margs[i]));
32176
32470
  const value = encodeURIComponent(toString(margs[i + 1]));
32177
32471
  queryParts.push(`${name}=${value}`);
@@ -32180,7 +32474,7 @@ function registerSpecialBuiltins(rt) {
32180
32474
  const sep = url.includes("?") ? "&" : "?";
32181
32475
  url += sep + queryParts.join("&");
32182
32476
  }
32183
- const text = io.webread(url);
32477
+ const text = io.webread(url, webOpts);
32184
32478
  try {
32185
32479
  const parsed = JSON.parse(text);
32186
32480
  return convertJsonValue(parsed);
@@ -38960,7 +39254,7 @@ defineBuiltin({
38960
39254
  cases: [
38961
39255
  {
38962
39256
  match: (argTypes, nargout) => {
38963
- if (nargout !== 1 || argTypes.length < 1 || argTypes.length > 2)
39257
+ if (nargout > 1 || argTypes.length < 1 || argTypes.length > 2)
38964
39258
  return null;
38965
39259
  if (!isNumericJitType(argTypes[0])) return null;
38966
39260
  return [NUM];
@@ -39077,7 +39371,7 @@ defineBuiltin({
39077
39371
  cases: [
39078
39372
  {
39079
39373
  match: (argTypes, nargout) => {
39080
- if (nargout !== 1 || argTypes.length < 1 || argTypes.length > 3)
39374
+ if (nargout > 1 || argTypes.length < 1 || argTypes.length > 3)
39081
39375
  return null;
39082
39376
  if (!isNumericJitType(argTypes[0])) return null;
39083
39377
  const a = argTypes[0];
@@ -39156,7 +39450,7 @@ defineBuiltin({
39156
39450
  cases: [
39157
39451
  {
39158
39452
  match: (argTypes, nargout) => {
39159
- if (nargout !== 1 || argTypes.length !== 2) return null;
39453
+ if (nargout > 1 || argTypes.length !== 2) return null;
39160
39454
  if (!isNumericJitType(argTypes[0]) || !isNumericJitType(argTypes[1]))
39161
39455
  return null;
39162
39456
  const hasTensor = argTypes.some((t) => t.kind === "tensor");
@@ -39240,7 +39534,7 @@ defineBuiltin({
39240
39534
  cases: [
39241
39535
  {
39242
39536
  match: (argTypes, nargout) => {
39243
- if (argTypes.length !== 1 || nargout !== 1) return null;
39537
+ if (argTypes.length !== 1 || nargout > 1) return null;
39244
39538
  if (!isNumericJitType(argTypes[0])) return null;
39245
39539
  const hasComplex = argTypes[0].kind === "complex_or_number" || argTypes[0].kind === "tensor" && argTypes[0].isComplex;
39246
39540
  return [hasComplex ? COMPLEX_OR_NUM : NUM];
@@ -39352,7 +39646,7 @@ defineBuiltin({
39352
39646
  cases: [
39353
39647
  {
39354
39648
  match: (argTypes, nargout) => {
39355
- if (argTypes.length !== 1 || nargout !== 1) return null;
39649
+ if (argTypes.length !== 1 || nargout > 1) return null;
39356
39650
  if (!isNumericJitType(argTypes[0])) return null;
39357
39651
  return [NUM];
39358
39652
  },
@@ -39377,7 +39671,7 @@ defineBuiltin({
39377
39671
  cases: [
39378
39672
  {
39379
39673
  match: (argTypes, nargout) => {
39380
- if (nargout !== 1) return null;
39674
+ if (nargout > 1) return null;
39381
39675
  if (argTypes.length !== 2 && argTypes.length !== 3) return null;
39382
39676
  if (!isNumericJitType(argTypes[0]) || !isNumericJitType(argTypes[1]))
39383
39677
  return null;
@@ -39443,7 +39737,7 @@ defineBuiltin({
39443
39737
  cases: [
39444
39738
  {
39445
39739
  match: (argTypes, nargout) => {
39446
- if (argTypes.length !== 1 || nargout !== 1) return null;
39740
+ if (argTypes.length !== 1 || nargout > 1) return null;
39447
39741
  if (!isNumericJitType(argTypes[0])) return null;
39448
39742
  const a = argTypes[0];
39449
39743
  if (a.kind === "number" || a.kind === "boolean") return [NUM];
@@ -39556,11 +39850,11 @@ function invComplexJS(dataRe, dataIm, n) {
39556
39850
  registerIBuiltin({
39557
39851
  name: "svd",
39558
39852
  resolve: (argTypes, nargout) => {
39559
- if (nargout < 1 || nargout > 3 || argTypes.length < 1 || argTypes.length > 2)
39853
+ if (nargout < 0 || nargout > 3 || argTypes.length < 1 || argTypes.length > 2)
39560
39854
  return null;
39561
39855
  if (!isNumericJitType(argTypes[0])) return null;
39562
39856
  const c = tensorType();
39563
- if (nargout === 1)
39857
+ if (nargout <= 1)
39564
39858
  return { outputTypes: [c], apply: (args, n) => svdApply(args, n) };
39565
39859
  return { outputTypes: [c, c, c], apply: (args, n) => svdApply(args, n) };
39566
39860
  }
@@ -39571,7 +39865,7 @@ function svdApply(args, nargout) {
39571
39865
  const A = args[0];
39572
39866
  if (isRuntimeNumber(A)) {
39573
39867
  const val = Math.abs(A);
39574
- if (nargout === 1) return RTV.tensor(new FloatXArray([val]), [1, 1]);
39868
+ if (nargout <= 1) return RTV.tensor(new FloatXArray([val]), [1, 1]);
39575
39869
  return [
39576
39870
  RTV.tensor(new FloatXArray([A >= 0 ? 1 : -1]), [1, 1]),
39577
39871
  RTV.tensor(new FloatXArray([val]), [1, 1]),
@@ -39598,7 +39892,7 @@ function svdApply(args, nargout) {
39598
39892
  nargout === 3
39599
39893
  );
39600
39894
  if (!result) throw new RuntimeError("svd: complex SVD failed");
39601
- if (nargout === 1) return RTV.tensor(new FloatXArray(result.S), [k, 1]);
39895
+ if (nargout <= 1) return RTV.tensor(new FloatXArray(result.S), [k, 1]);
39602
39896
  const uCols = econ ? k : m;
39603
39897
  const vCols = econ ? k : n;
39604
39898
  return [
@@ -39619,7 +39913,7 @@ function svdApply(args, nargout) {
39619
39913
  if (bridge?.svd) {
39620
39914
  const result = bridge.svd(toF64(A.data), m, n, econ, nargout === 3);
39621
39915
  if (result) {
39622
- if (nargout === 1) return RTV.tensor(new FloatXArray(result.S), [k, 1]);
39916
+ if (nargout <= 1) return RTV.tensor(new FloatXArray(result.S), [k, 1]);
39623
39917
  const uCols = econ ? k : m;
39624
39918
  const vCols = econ ? k : n;
39625
39919
  return [
@@ -39689,12 +39983,12 @@ function powerIterationEigenvalues(A_data, n, numEigenvalues) {
39689
39983
  registerIBuiltin({
39690
39984
  name: "qr",
39691
39985
  resolve: (argTypes, nargout) => {
39692
- if (nargout < 1 || nargout > 3 || argTypes.length < 1 || argTypes.length > 2)
39986
+ if (nargout < 0 || nargout > 3 || argTypes.length < 1 || argTypes.length > 2)
39693
39987
  return null;
39694
39988
  if (!isNumericJitType(argTypes[0])) return null;
39695
39989
  const isComplex2 = argTypes[0].kind === "tensor" && argTypes[0].isComplex;
39696
39990
  const t = tensorType(isComplex2 || void 0);
39697
- if (nargout === 1)
39991
+ if (nargout <= 1)
39698
39992
  return { outputTypes: [t], apply: (args, n) => qrApply(args, n) };
39699
39993
  if (nargout === 3)
39700
39994
  return {
@@ -39711,7 +40005,7 @@ function qrApply(args, nargout) {
39711
40005
  if (isRuntimeNumber(A)) {
39712
40006
  const val = A;
39713
40007
  const s = val >= 0 ? 1 : -1;
39714
- if (nargout === 1) return RTV.tensor(new FloatXArray([s * val]), [1, 1]);
40008
+ if (nargout <= 1) return RTV.tensor(new FloatXArray([s * val]), [1, 1]);
39715
40009
  if (nargout === 3)
39716
40010
  return [
39717
40011
  RTV.tensor(new FloatXArray([s]), [1, 1]),
@@ -39744,7 +40038,7 @@ function qrApply(args, nargout) {
39744
40038
  nargout === 2
39745
40039
  );
39746
40040
  if (!result) throw new RuntimeError("qr: complex QR failed");
39747
- if (nargout === 1) {
40041
+ if (nargout <= 1) {
39748
40042
  const rRows = econ ? k : m;
39749
40043
  return RTV.tensor(
39750
40044
  new FloatXArray(result.RRe),
@@ -39770,7 +40064,7 @@ function qrApply(args, nargout) {
39770
40064
  if (bridge?.qr) {
39771
40065
  const result = bridge.qr(toF64(A.data), m, n, econ, nargout === 2);
39772
40066
  if (result) {
39773
- if (nargout === 1)
40067
+ if (nargout <= 1)
39774
40068
  return RTV.tensor(new FloatXArray(result.R), [econ ? k : m, n]);
39775
40069
  const qCols = econ ? k : m;
39776
40070
  return [
@@ -39813,7 +40107,7 @@ function qrApply(args, nargout) {
39813
40107
  R_data[colMajorIndex(j + i, c, m)] -= scale * v[i];
39814
40108
  }
39815
40109
  }
39816
- if (nargout === 1) {
40110
+ if (nargout <= 1) {
39817
40111
  if (econ) {
39818
40112
  const R_econ = new FloatXArray(k * n);
39819
40113
  for (let r = 0; r < k; r++)
@@ -40029,11 +40323,11 @@ function qrPivotApply(A, m, n, k, econ) {
40029
40323
  registerIBuiltin({
40030
40324
  name: "lu",
40031
40325
  resolve: (argTypes, nargout) => {
40032
- if (nargout < 1 || nargout > 3) return null;
40326
+ if (nargout < 0 || nargout > 3) return null;
40033
40327
  if (argTypes.length < 1 || argTypes.length > 2) return null;
40034
40328
  if (!isNumericJitType(argTypes[0])) return null;
40035
40329
  const t = tensorType();
40036
- if (nargout === 1)
40330
+ if (nargout <= 1)
40037
40331
  return { outputTypes: [t], apply: (args, n) => luApply(args, n) };
40038
40332
  if (nargout === 2)
40039
40333
  return { outputTypes: [t, t], apply: (args, n) => luApply(args, n) };
@@ -40052,7 +40346,7 @@ function luApply(args, nargout) {
40052
40346
  if (nargout <= 2) {
40053
40347
  const L2 = RTV.tensor(new FloatXArray([1]), [1, 1]);
40054
40348
  const U2 = RTV.tensor(new FloatXArray([val]), [1, 1]);
40055
- if (nargout === 1) return L2;
40349
+ if (nargout <= 1) return L2;
40056
40350
  return [L2, U2];
40057
40351
  }
40058
40352
  const L = RTV.tensor(new FloatXArray([1]), [1, 1]);
@@ -40090,7 +40384,7 @@ function luApply(args, nargout) {
40090
40384
  if (U_im && LU_im) U_im[i + j * k] = LU_im[i + j * m];
40091
40385
  }
40092
40386
  }
40093
- if (nargout === 1)
40387
+ if (nargout <= 1)
40094
40388
  return RTV.tensor(
40095
40389
  new FloatXArray(LU_re),
40096
40390
  [m, n],
@@ -40166,11 +40460,11 @@ function ipivToPermVector(ipiv, m) {
40166
40460
  registerIBuiltin({
40167
40461
  name: "eig",
40168
40462
  resolve: (argTypes, nargout) => {
40169
- if (nargout < 1 || nargout > 3 || argTypes.length < 1 || argTypes.length > 3)
40463
+ if (nargout < 0 || nargout > 3 || argTypes.length < 1 || argTypes.length > 3)
40170
40464
  return null;
40171
40465
  if (!isNumericJitType(argTypes[0])) return null;
40172
40466
  const c = tensorType(true);
40173
- if (nargout === 1)
40467
+ if (nargout <= 1)
40174
40468
  return { outputTypes: [c], apply: (args, n) => eigApply(args, n) };
40175
40469
  if (nargout === 2)
40176
40470
  return { outputTypes: [c, c], apply: (args, n) => eigApply(args, n) };
@@ -40184,7 +40478,7 @@ function eigApply(args, nargout) {
40184
40478
  const { balance, outputForm } = parseEigOptionsRuntime(args);
40185
40479
  if (isRuntimeNumber(A)) {
40186
40480
  const val = A;
40187
- if (nargout === 1) return RTV.num(val);
40481
+ if (nargout <= 1) return RTV.num(val);
40188
40482
  const V = RTV.tensor(new FloatXArray([1]), [1, 1]);
40189
40483
  if (nargout === 2) {
40190
40484
  if (outputForm === "vector") return [V, RTV.num(val)];
@@ -40213,7 +40507,7 @@ function eigApply(args, nargout) {
40213
40507
  );
40214
40508
  if (!result2) throw new RuntimeError("eig: complex eig failed");
40215
40509
  const { wRe, wIm, VLRe, VLIm, VRRe, VRIm } = result2;
40216
- if (nargout === 1) return maybeComplexTensor(wRe, [n, 1], wIm);
40510
+ if (nargout <= 1) return maybeComplexTensor(wRe, [n, 1], wIm);
40217
40511
  const Vout2 = computeVR && VRRe && VRIm ? maybeComplexTensor(VRRe, [n, n], VRIm) : RTV.tensor(new FloatXArray(n * n), [n, n]);
40218
40512
  const Dout2 = outputForm === "vector" ? maybeComplexTensor(wRe, [n, 1], wIm) : buildDiagMatrix(wRe, wIm, n);
40219
40513
  if (nargout === 2) return [Vout2, Dout2];
@@ -40226,7 +40520,7 @@ function eigApply(args, nargout) {
40226
40520
  if (!result) throw new RuntimeError("eig: LAPACK eig failed");
40227
40521
  const { wr, wi, VL, VR } = result;
40228
40522
  const hasComplex = wi.some((v) => v !== 0);
40229
- if (nargout === 1) return maybeComplexTensor(wr, [n, 1], wi);
40523
+ if (nargout <= 1) return maybeComplexTensor(wr, [n, 1], wi);
40230
40524
  const Vout = computeVR && VR ? buildEigenvectorMatrix(VR, wi, n, hasComplex) : RTV.tensor(new FloatXArray(n * n), [n, n]);
40231
40525
  const Dout = outputForm === "vector" ? maybeComplexTensor(wr, [n, 1], wi) : buildDiagMatrix(wr, wi, n);
40232
40526
  if (nargout === 2) return [Vout, Dout];
@@ -40250,11 +40544,11 @@ function parseEigOptionsRuntime(args) {
40250
40544
  registerIBuiltin({
40251
40545
  name: "chol",
40252
40546
  resolve: (argTypes, nargout) => {
40253
- if (nargout < 1 || nargout > 3 || argTypes.length < 1 || argTypes.length > 3)
40547
+ if (nargout < 0 || nargout > 3 || argTypes.length < 1 || argTypes.length > 3)
40254
40548
  return null;
40255
40549
  if (!isNumericJitType(argTypes[0])) return null;
40256
40550
  const t = tensorType();
40257
- if (nargout === 1)
40551
+ if (nargout <= 1)
40258
40552
  return { outputTypes: [t], apply: (args, n) => cholApply(args, n) };
40259
40553
  if (nargout === 2)
40260
40554
  return { outputTypes: [t, NUM], apply: (args, n) => cholApply(args, n) };
@@ -40415,7 +40709,7 @@ defineBuiltin({
40415
40709
  cases: [
40416
40710
  {
40417
40711
  match: (argTypes, nargout) => {
40418
- if (argTypes.length !== 2 || nargout !== 1) return null;
40712
+ if (argTypes.length !== 2 || nargout > 1) return null;
40419
40713
  if (!isNumericJitType(argTypes[0]) || !isNumericJitType(argTypes[1]))
40420
40714
  return null;
40421
40715
  return [tensorType()];
@@ -40458,7 +40752,7 @@ defineBuiltin({
40458
40752
  cases: [
40459
40753
  {
40460
40754
  match: (argTypes, nargout) => {
40461
- if (nargout !== 1 || argTypes.length < 1 || argTypes.length > 2)
40755
+ if (nargout > 1 || argTypes.length < 1 || argTypes.length > 2)
40462
40756
  return null;
40463
40757
  if (!isNumericJitType(argTypes[0])) return null;
40464
40758
  return [NUM];
@@ -40519,7 +40813,7 @@ defineBuiltin({
40519
40813
  cases: [
40520
40814
  {
40521
40815
  match: (argTypes, nargout) => {
40522
- if (nargout !== 1 || argTypes.length < 1 || argTypes.length > 2)
40816
+ if (nargout > 1 || argTypes.length < 1 || argTypes.length > 2)
40523
40817
  return null;
40524
40818
  if (!isNumericJitType(argTypes[0])) return null;
40525
40819
  return [NUM];
@@ -40567,7 +40861,7 @@ defineBuiltin({
40567
40861
  cases: [
40568
40862
  {
40569
40863
  match: (argTypes, nargout) => {
40570
- if (nargout !== 1 || argTypes.length < 1 || argTypes.length > 2)
40864
+ if (nargout > 1 || argTypes.length < 1 || argTypes.length > 2)
40571
40865
  return null;
40572
40866
  if (!isNumericJitType(argTypes[0])) return null;
40573
40867
  const a = argTypes[0];
@@ -40664,7 +40958,7 @@ defineBuiltin({
40664
40958
  cases: [
40665
40959
  {
40666
40960
  match: (argTypes, nargout) => {
40667
- if (nargout !== 1 || argTypes.length !== 2) return null;
40961
+ if (nargout > 1 || argTypes.length !== 2) return null;
40668
40962
  if (!isNumericJitType(argTypes[0]) || !isNumericJitType(argTypes[1]))
40669
40963
  return null;
40670
40964
  return [tensorType()];
@@ -40700,7 +40994,7 @@ defineBuiltin({
40700
40994
  cases: [
40701
40995
  {
40702
40996
  match: (argTypes, nargout) => {
40703
- if (nargout !== 1 || argTypes.length === 0) return null;
40997
+ if (nargout > 1 || argTypes.length === 0) return null;
40704
40998
  if (!argTypes.every(isNumericJitType)) return null;
40705
40999
  return [tensorType()];
40706
41000
  },
@@ -40743,7 +41037,7 @@ defineBuiltin({
40743
41037
  cases: [
40744
41038
  {
40745
41039
  match: (argTypes, nargout) => {
40746
- if (nargout !== 1) return null;
41040
+ if (nargout > 1) return null;
40747
41041
  if (argTypes.length !== 2 && argTypes.length !== 4) return null;
40748
41042
  const xIdx = 0, yIdx = argTypes.length === 4 ? 2 : 1;
40749
41043
  if (!isNumericJitType(argTypes[xIdx]) || !isNumericJitType(argTypes[yIdx]))
@@ -40872,7 +41166,7 @@ defineBuiltin({
40872
41166
  cases: [
40873
41167
  {
40874
41168
  match: (argTypes, nargout) => {
40875
- if (nargout !== 1 || argTypes.length !== 1) return null;
41169
+ if (nargout > 1 || argTypes.length !== 1) return null;
40876
41170
  if (argTypes[0].kind !== "tensor") return null;
40877
41171
  return [tensorType(argTypes[0].isComplex)];
40878
41172
  },
@@ -44734,9 +45028,11 @@ registerIBuiltin({
44734
45028
  // src/numbl-core/helpers/prng.ts
44735
45029
  var _rngState = null;
44736
45030
  var _rngSeed = 0;
45031
+ var _bmSpare = null;
44737
45032
  function setRngShuffle() {
44738
45033
  _rngState = null;
44739
45034
  _rngSeed = 0;
45035
+ _bmSpare = null;
44740
45036
  }
44741
45037
  function setRngSeed(seed) {
44742
45038
  _rngSeed = seed;
@@ -44752,6 +45048,7 @@ function splitmix32(seed) {
44752
45048
  };
44753
45049
  }
44754
45050
  function seedRng(seed) {
45051
+ _bmSpare = null;
44755
45052
  const sm = splitmix32(seed);
44756
45053
  _rngState = new Uint32Array([sm(), sm(), sm(), sm()]);
44757
45054
  if (_rngState[0] === 0 && _rngState[1] === 0 && _rngState[2] === 0 && _rngState[3] === 0) {
@@ -44778,10 +45075,60 @@ function rngRandom() {
44778
45075
  return (xoshiro128ss() >>> 0) / 4294967296;
44779
45076
  }
44780
45077
  function boxMullerRandom() {
44781
- let u = 0, v = 0;
44782
- while (u === 0) u = rngRandom();
44783
- while (v === 0) v = rngRandom();
44784
- return Math.sqrt(-2 * Math.log(u)) * Math.cos(2 * Math.PI * v);
45078
+ if (_bmSpare !== null) {
45079
+ const s2 = _bmSpare;
45080
+ _bmSpare = null;
45081
+ return s2;
45082
+ }
45083
+ let u, v, s;
45084
+ do {
45085
+ u = 2 * rngRandom() - 1;
45086
+ v = 2 * rngRandom() - 1;
45087
+ s = u * u + v * v;
45088
+ } while (s >= 1 || s === 0);
45089
+ const mul = Math.sqrt(-2 * Math.log(s) / s);
45090
+ _bmSpare = v * mul;
45091
+ return u * mul;
45092
+ }
45093
+ function fillRandn(data) {
45094
+ if (_rngState !== null) {
45095
+ const bridge = getLapackBridge();
45096
+ if (bridge?.fillRandn) {
45097
+ const r = bridge.fillRandn(
45098
+ _rngState,
45099
+ data.length,
45100
+ _bmSpare ?? 0,
45101
+ _bmSpare !== null
45102
+ );
45103
+ _bmSpare = r.hasSpare ? r.spare : null;
45104
+ if (data instanceof Float64Array) {
45105
+ data.set(r.data);
45106
+ } else {
45107
+ for (let i2 = 0; i2 < data.length; i2++) data[i2] = r.data[i2];
45108
+ }
45109
+ return;
45110
+ }
45111
+ }
45112
+ const n = data.length;
45113
+ let i = 0;
45114
+ if (_bmSpare !== null && i < n) {
45115
+ data[i++] = _bmSpare;
45116
+ _bmSpare = null;
45117
+ }
45118
+ for (; i + 1 < n; i += 2) {
45119
+ let u, v, s;
45120
+ do {
45121
+ u = 2 * rngRandom() - 1;
45122
+ v = 2 * rngRandom() - 1;
45123
+ s = u * u + v * v;
45124
+ } while (s >= 1 || s === 0);
45125
+ const mul = Math.sqrt(-2 * Math.log(s) / s);
45126
+ data[i] = u * mul;
45127
+ data[i + 1] = v * mul;
45128
+ }
45129
+ if (i < n) {
45130
+ data[i] = boxMullerRandom();
45131
+ }
44785
45132
  }
44786
45133
  function getRngStateStruct() {
44787
45134
  const stateArray = _rngState ? RTV.tensor(new FloatXArray(Array.from(_rngState).map((v) => v)), [4, 1]) : RTV.tensor(new FloatXArray(0), [0, 1]);
@@ -44849,7 +45196,7 @@ registerIBuiltin({
44849
45196
  };
44850
45197
  }
44851
45198
  });
44852
- function registerRandBuiltin(name, gen) {
45199
+ function registerRandBuiltin(name, gen, bulkFill) {
44853
45200
  defineBuiltin({
44854
45201
  name,
44855
45202
  cases: [
@@ -44888,7 +45235,11 @@ function registerRandBuiltin(name, gen) {
44888
45235
  if (shape.length === 1) shape.push(shape[0]);
44889
45236
  const n = numel(shape);
44890
45237
  const data = new FloatXArray(n);
44891
- for (let i = 0; i < n; i++) data[i] = gen();
45238
+ if (bulkFill) {
45239
+ bulkFill(data);
45240
+ } else {
45241
+ for (let i = 0; i < n; i++) data[i] = gen();
45242
+ }
44892
45243
  return RTV.tensor(data, shape);
44893
45244
  }
44894
45245
  }
@@ -44896,7 +45247,7 @@ function registerRandBuiltin(name, gen) {
44896
45247
  });
44897
45248
  }
44898
45249
  registerRandBuiltin("rand", rngRandom);
44899
- registerRandBuiltin("randn", boxMullerRandom);
45250
+ registerRandBuiltin("randn", boxMullerRandom, fillRandn);
44900
45251
  defineBuiltin({
44901
45252
  name: "randi",
44902
45253
  cases: [
@@ -45341,136 +45692,6 @@ registerIBuiltin({
45341
45692
  }
45342
45693
  });
45343
45694
 
45344
- // src/numbl-core/interpreter/builtins/time-system.ts
45345
- var ticTime = 0;
45346
- defineBuiltin({
45347
- name: "tic",
45348
- cases: [
45349
- {
45350
- match: (argTypes) => argTypes.length === 0 ? [{ kind: "number" }] : null,
45351
- apply: () => {
45352
- ticTime = performance.now();
45353
- return RTV.num(ticTime / 1e3);
45354
- }
45355
- }
45356
- ]
45357
- });
45358
- defineBuiltin({
45359
- name: "toc",
45360
- cases: [
45361
- {
45362
- match: (argTypes) => argTypes.length === 0 ? [{ kind: "number" }] : null,
45363
- apply: () => RTV.num((performance.now() - ticTime) / 1e3)
45364
- }
45365
- ]
45366
- });
45367
- defineBuiltin({
45368
- name: "clock",
45369
- cases: [
45370
- {
45371
- match: (argTypes) => argTypes.length === 0 ? [{ kind: "tensor", isComplex: false, shape: [1, 6] }] : null,
45372
- apply: () => {
45373
- const now = /* @__PURE__ */ new Date();
45374
- return RTV.tensor(
45375
- new FloatXArray([
45376
- now.getFullYear(),
45377
- now.getMonth() + 1,
45378
- now.getDate(),
45379
- now.getHours(),
45380
- now.getMinutes(),
45381
- now.getSeconds() + now.getMilliseconds() / 1e3
45382
- ]),
45383
- [1, 6]
45384
- );
45385
- }
45386
- }
45387
- ]
45388
- });
45389
- defineBuiltin({
45390
- name: "etime",
45391
- cases: [
45392
- {
45393
- match: (argTypes) => argTypes.length === 2 ? [{ kind: "number" }] : null,
45394
- apply: (args) => {
45395
- const t1 = args[0];
45396
- const t0 = args[1];
45397
- if (!isRuntimeTensor(t1) || !isRuntimeTensor(t0))
45398
- throw new RuntimeError("etime: arguments must be clock vectors");
45399
- const toMs = (t) => {
45400
- const d = new Date(
45401
- t.data[0],
45402
- t.data[1] - 1,
45403
- t.data[2],
45404
- t.data[3],
45405
- t.data[4],
45406
- Math.floor(t.data[5]),
45407
- t.data[5] % 1 * 1e3
45408
- );
45409
- return d.getTime();
45410
- };
45411
- return RTV.num((toMs(t1) - toMs(t0)) / 1e3);
45412
- }
45413
- }
45414
- ]
45415
- });
45416
- defineBuiltin({
45417
- name: "version",
45418
- cases: [
45419
- {
45420
- match: (argTypes) => argTypes.length === 0 ? [{ kind: "char" }] : null,
45421
- apply: () => RTV.char("9.14.0")
45422
- }
45423
- ]
45424
- });
45425
- function getComputerStrings() {
45426
- if (typeof process === "undefined") {
45427
- return { str: "BROWSER", arch: "browser" };
45428
- }
45429
- const platform = process.platform;
45430
- const cpuArch = process.arch;
45431
- if (platform === "win32") return { str: "PCWIN64", arch: "win64" };
45432
- if (platform === "darwin") {
45433
- if (cpuArch === "arm64") return { str: "MACA64", arch: "maca64" };
45434
- return { str: "MACI64", arch: "maci64" };
45435
- }
45436
- return { str: "GLNXA64", arch: "glnxa64" };
45437
- }
45438
- registerIBuiltin({
45439
- name: "computer",
45440
- resolve: () => ({
45441
- outputTypes: [{ kind: "unknown" }],
45442
- apply: (args, nargout) => {
45443
- const info = getComputerStrings();
45444
- if (args.length >= 1 && isRuntimeChar(args[0])) {
45445
- const arg = toString(args[0]);
45446
- if (arg === "arch") return RTV.char(info.arch);
45447
- throw new RuntimeError(`computer: unknown argument '${arg}'`);
45448
- }
45449
- const maxsize = 2 ** 48 - 1;
45450
- const endian = RTV.char("L");
45451
- if (nargout <= 1) return RTV.char(info.str);
45452
- if (nargout === 2) return [RTV.char(info.str), RTV.num(maxsize)];
45453
- return [RTV.char(info.str), RTV.num(maxsize), endian];
45454
- }
45455
- })
45456
- });
45457
- var _platform = typeof process !== "undefined" ? process.platform : "linux";
45458
- for (const [name, val] of [
45459
- ["ismac", _platform === "darwin"],
45460
- ["ispc", _platform === "win32"],
45461
- ["isunix", _platform !== "win32"]
45462
- ]) {
45463
- defineBuiltin({
45464
- name,
45465
- cases: [
45466
- {
45467
- match: (argTypes) => argTypes.length === 0 ? [{ kind: "boolean" }] : null,
45468
- apply: () => RTV.logical(val)
45469
- }
45470
- ]
45471
- });
45472
- }
45473
-
45474
45695
  // src/numbl-core/interpreter/builtins/sparse.ts
45475
45696
  function toNumericArray(v, name) {
45476
45697
  if (isRuntimeNumber(v)) return [v];
@@ -48330,7 +48551,7 @@ function getSourceLine(getSource, file, line) {
48330
48551
  }
48331
48552
 
48332
48553
  // src/numbl-core/version.ts
48333
- var NUMBL_VERSION = "0.1.2";
48554
+ var NUMBL_VERSION = "0.1.3";
48334
48555
 
48335
48556
  // src/cli-repl.ts
48336
48557
  import { createInterface } from "readline";
@@ -49592,9 +49813,7 @@ function lowerStmt(ctx, stmt) {
49592
49813
  result = lowerAssign(ctx, stmt);
49593
49814
  break;
49594
49815
  case "ExprStmt":
49595
- if (!stmt.suppressed) return null;
49596
- result = lowerExprStmt(ctx, stmt);
49597
- break;
49816
+ return null;
49598
49817
  case "If":
49599
49818
  result = lowerIf(ctx, stmt);
49600
49819
  break;
@@ -49669,11 +49888,6 @@ function lowerMultiAssign(ctx, stmt) {
49669
49888
  }
49670
49889
  ];
49671
49890
  }
49672
- function lowerExprStmt(ctx, stmt) {
49673
- const expr = lowerExpr(ctx, stmt.expr);
49674
- if (!expr) return null;
49675
- return [{ tag: "ExprStmt", expr }];
49676
- }
49677
49891
  function lowerIf(ctx, stmt) {
49678
49892
  const cond = lowerExpr(ctx, stmt.cond);
49679
49893
  if (!cond) return null;
@@ -50742,10 +50956,11 @@ function execStmt(stmt) {
50742
50956
  }
50743
50957
  switch (stmt.type) {
50744
50958
  case "ExprStmt": {
50745
- const val = this.evalExpr(stmt.expr);
50959
+ const val = this.evalExprNargout(stmt.expr, 0);
50746
50960
  const singleVal = Array.isArray(val) ? val[0] : val;
50747
50961
  const rv = ensureRuntimeValue(singleVal);
50748
50962
  this.ans = rv;
50963
+ this.env.set("ans", rv);
50749
50964
  if (!stmt.suppressed && !this.isOutputExpr(stmt.expr)) {
50750
50965
  this.rt.displayResult(rv);
50751
50966
  }
@@ -50795,10 +51010,12 @@ function execStmt(stmt) {
50795
51010
  const rv = this.rt.share(i < values.length ? values[i] : void 0);
50796
51011
  this.assignLValue(lv, rv);
50797
51012
  }
50798
- if (!stmt.suppressed && values.length > 0) {
50799
- const firstLv = stmt.lvalues[0];
50800
- if (firstLv.type === "Var") {
50801
- this.rt.displayAssign(firstLv.name, ensureRuntimeValue(values[0]));
51013
+ if (!stmt.suppressed) {
51014
+ for (let i = 0; i < stmt.lvalues.length; i++) {
51015
+ const lv = stmt.lvalues[i];
51016
+ if (lv.type === "Var" && i < values.length) {
51017
+ this.rt.displayAssign(lv.name, ensureRuntimeValue(values[i]));
51018
+ }
50802
51019
  }
50803
51020
  }
50804
51021
  return null;
@@ -51155,6 +51372,18 @@ function evalArgs(argExprs) {
51155
51372
  }
51156
51373
  return args;
51157
51374
  }
51375
+ var binopProfileName = {
51376
+ ["Add" /* Add */]: "plus",
51377
+ ["Sub" /* Sub */]: "minus",
51378
+ ["Mul" /* Mul */]: "mtimes",
51379
+ ["ElemMul" /* ElemMul */]: "times",
51380
+ ["Div" /* Div */]: "mrdivide",
51381
+ ["ElemDiv" /* ElemDiv */]: "rdivide",
51382
+ ["LeftDiv" /* LeftDiv */]: "mldivide",
51383
+ ["ElemLeftDiv" /* ElemLeftDiv */]: "ldivide",
51384
+ ["Pow" /* Pow */]: "mpower",
51385
+ ["ElemPow" /* ElemPow */]: "power"
51386
+ };
51158
51387
  function evalBinary(expr) {
51159
51388
  if (expr.op === "AndAnd" /* AndAnd */) {
51160
51389
  const left2 = this.evalExpr(expr.left);
@@ -51180,6 +51409,13 @@ function evalBinary(expr) {
51180
51409
  if (!isNaN(r)) return r;
51181
51410
  return mPow(ensureRuntimeValue(left), ensureRuntimeValue(right));
51182
51411
  }
51412
+ if (this.rt.profilingEnabled && (typeof left !== "number" || typeof right !== "number")) {
51413
+ const opName = binopProfileName[expr.op] ?? expr.op;
51414
+ this.rt.profileEnter("builtin:interp:" + opName);
51415
+ const result = binop(expr.op, left, right);
51416
+ this.rt.profileLeave();
51417
+ return result;
51418
+ }
51183
51419
  return binop(expr.op, left, right);
51184
51420
  }
51185
51421
  function evalUnary(expr) {
@@ -51578,7 +51814,6 @@ function switchMatch2(switchVal, caseVal) {
51578
51814
  return switchMatch(switchVal, caseVal);
51579
51815
  }
51580
51816
  function isOutputExpr(expr) {
51581
- if (expr.type !== "FuncCall") return false;
51582
51817
  const outputFunctions = [
51583
51818
  "disp",
51584
51819
  "display",
@@ -51586,9 +51821,12 @@ function isOutputExpr(expr) {
51586
51821
  "warning",
51587
51822
  "assert",
51588
51823
  "tic",
51824
+ "toc",
51589
51825
  "help"
51590
51826
  ];
51591
- return outputFunctions.includes(expr.name);
51827
+ if (expr.type === "FuncCall") return outputFunctions.includes(expr.name);
51828
+ if (expr.type === "Ident") return outputFunctions.includes(expr.name);
51829
+ return false;
51592
51830
  }
51593
51831
 
51594
51832
  // src/numbl-core/interpreter/interpreterFunctions.ts
@@ -52256,8 +52494,9 @@ function callUserFunction(fn, args, nargout, narginOverride) {
52256
52494
  }
52257
52495
  const hasVarargout = fn.outputs.length > 0 && fn.outputs[fn.outputs.length - 1] === "varargout";
52258
52496
  const regularOutputs = hasVarargout ? fn.outputs.slice(0, -1) : fn.outputs;
52497
+ const collectCount = nargout === 0 && regularOutputs.length > 0 ? 1 : Math.min(regularOutputs.length, nargout);
52259
52498
  const outputs = [];
52260
- for (let i = 0; i < Math.min(regularOutputs.length, nargout); i++) {
52499
+ for (let i = 0; i < collectCount; i++) {
52261
52500
  const val = this.env.get(regularOutputs[i]);
52262
52501
  if (val === void 0 && nargout >= i + 1) {
52263
52502
  throw new RuntimeError(
@@ -53827,10 +54066,17 @@ function executeCode(source, options = {}, workspaceFiles, mainFileName = "scrip
53827
54066
  if (options.log) {
53828
54067
  options.log("AST parsed, starting interpretation");
53829
54068
  }
54069
+ const isRepl = mainFileName === "repl";
53830
54070
  const localFunctions = [];
53831
54071
  const localClasses = [];
53832
54072
  for (const stmt of ast.body) {
53833
54073
  if (stmt.type === "Function") {
54074
+ if (isRepl) {
54075
+ throw new RuntimeError(
54076
+ "Function definitions are not supported in the REPL. Save the function to a .m file instead.",
54077
+ stmt.span
54078
+ );
54079
+ }
53834
54080
  localFunctions.push(stmt);
53835
54081
  } else if (stmt.type === "ClassDef") {
53836
54082
  localClasses.push(stmt);
@@ -54056,7 +54302,7 @@ ${jsCode}`
54056
54302
  output: rt.outputLines,
54057
54303
  generatedJS: jitSections.length > 0 ? `// Interpreter mode \u2014 JIT compiled sections:
54058
54304
 
54059
- ${jitSections.join("\n\n")}` : "// interpreted mode \u2014 no JS generated",
54305
+ ${jitSections.join("\n\n")}` : "// No JS generated",
54060
54306
  plotInstructions: rt.plotInstructions,
54061
54307
  returnValue: interpreter.ans ?? RTV.num(0),
54062
54308
  variableValues: interpreter.getVariableValues(),
@@ -54082,7 +54328,7 @@ ${jitSections.join("\n\n")}` : "// interpreted mode \u2014 no JS generated",
54082
54328
  } catch (e) {
54083
54329
  const generatedJS = jitSections.length > 0 ? `// Interpreter mode \u2014 JIT compiled sections:
54084
54330
 
54085
- ${jitSections.join("\n\n")}` : "// interpreted mode \u2014 no JS generated";
54331
+ ${jitSections.join("\n\n")}` : "// No JS generated";
54086
54332
  if (e instanceof RuntimeError) {
54087
54333
  if (e.line === null && rt.$file && rt.$line > 0) {
54088
54334
  e.file = rt.$file;
@@ -54132,7 +54378,7 @@ import {
54132
54378
  rmSync,
54133
54379
  rmdirSync
54134
54380
  } from "fs";
54135
- import { inflateRawSync } from "zlib";
54381
+ import { unzipSync } from "fflate";
54136
54382
  import { execFileSync } from "child_process";
54137
54383
  import { homedir, tmpdir } from "os";
54138
54384
  import { join as join3, resolve, dirname, basename } from "path";
@@ -54208,6 +54454,21 @@ function permissionToFlags(permission) {
54208
54454
  }
54209
54455
  }
54210
54456
  var READ_CHUNK_SIZE = 8192;
54457
+ function buildFetchOptions(options) {
54458
+ const init = {};
54459
+ if (options?.requestMethod) {
54460
+ init.method = options.requestMethod.toUpperCase();
54461
+ }
54462
+ const headers = {};
54463
+ if (options?.username && options?.password) {
54464
+ headers["Authorization"] = "Basic " + Buffer.from(`${options.username}:${options.password}`).toString("base64");
54465
+ }
54466
+ if (options?.keyName && options?.keyValue) {
54467
+ headers[options.keyName] = options.keyValue;
54468
+ }
54469
+ if (Object.keys(headers).length > 0) init.headers = headers;
54470
+ return init;
54471
+ }
54211
54472
  var NodeFileIOAdapter = class {
54212
54473
  nextFid = 3;
54213
54474
  // 0=stdin, 1=stdout, 2=stderr reserved
@@ -54381,35 +54642,43 @@ var NodeFileIOAdapter = class {
54381
54642
  tempdir() {
54382
54643
  return tmpdir();
54383
54644
  }
54384
- websave(url, filename) {
54645
+ websave(url, filename, options) {
54385
54646
  const dest = expandTilde(filename);
54647
+ const timeoutMs = options?.timeout ? Math.round(options.timeout * 1e3) : 3e4;
54648
+ const fetchOpts = buildFetchOptions(options);
54386
54649
  const script = `
54387
- fetch(${JSON.stringify(url)})
54388
- .then(r => { if (!r.ok) throw new Error('HTTP ' + r.status); return r.arrayBuffer(); })
54650
+ const ac = new AbortController();
54651
+ const t = setTimeout(() => ac.abort(), ${timeoutMs});
54652
+ fetch(${JSON.stringify(url)}, { ...${JSON.stringify(fetchOpts)}, signal: ac.signal })
54653
+ .then(r => { clearTimeout(t); if (!r.ok) throw new Error('HTTP ' + r.status); return r.arrayBuffer(); })
54389
54654
  .then(buf => require('fs').writeFileSync(${JSON.stringify(dest)}, Buffer.from(buf)))
54390
54655
  .catch(e => { process.stderr.write(e.message + '\\n'); process.exit(1); });
54391
54656
  `;
54392
54657
  try {
54393
54658
  execFileSync(process.execPath, ["-e", script], {
54394
54659
  stdio: ["ignore", "ignore", "pipe"],
54395
- timeout: 3e4
54660
+ timeout: timeoutMs + 5e3
54396
54661
  });
54397
54662
  } catch (e) {
54398
54663
  const msg = e instanceof Error && "stderr" in e ? e.stderr.toString().trim() : String(e);
54399
54664
  throw new Error(`websave: failed to download ${url}: ${msg}`);
54400
54665
  }
54401
54666
  }
54402
- webread(url) {
54667
+ webread(url, options) {
54668
+ const timeoutMs = options?.timeout ? Math.round(options.timeout * 1e3) : 3e4;
54669
+ const fetchOpts = buildFetchOptions(options);
54403
54670
  const script = `
54404
- fetch(${JSON.stringify(url)})
54405
- .then(r => { if (!r.ok) throw new Error('HTTP ' + r.status); return r.text(); })
54671
+ const ac = new AbortController();
54672
+ const t = setTimeout(() => ac.abort(), ${timeoutMs});
54673
+ fetch(${JSON.stringify(url)}, { ...${JSON.stringify(fetchOpts)}, signal: ac.signal })
54674
+ .then(r => { clearTimeout(t); if (!r.ok) throw new Error('HTTP ' + r.status); return r.text(); })
54406
54675
  .then(t => process.stdout.write(t))
54407
54676
  .catch(e => { process.stderr.write(e.message + '\\n'); process.exit(1); });
54408
54677
  `;
54409
54678
  try {
54410
54679
  const result = execFileSync(process.execPath, ["-e", script], {
54411
54680
  stdio: ["ignore", "pipe", "pipe"],
54412
- timeout: 3e4,
54681
+ timeout: timeoutMs + 5e3,
54413
54682
  maxBuffer: 50 * 1024 * 1024
54414
54683
  });
54415
54684
  return result.toString();
@@ -54466,56 +54735,18 @@ var NodeFileIOAdapter = class {
54466
54735
  const dest = resolve(expandTilde(outputfolder));
54467
54736
  mkdirSync(dest, { recursive: true });
54468
54737
  const buf = readFileSync3(src);
54469
- let eocdOffset = -1;
54470
- for (let i = buf.length - 22; i >= 0; i--) {
54471
- if (buf[i] === 80 && buf[i + 1] === 75 && buf[i + 2] === 5 && buf[i + 3] === 6) {
54472
- eocdOffset = i;
54473
- break;
54474
- }
54475
- }
54476
- if (eocdOffset === -1) throw new Error("unzip: invalid ZIP file");
54477
- const cdOffset = buf.readUInt32LE(eocdOffset + 16);
54478
- const cdEntries = buf.readUInt16LE(eocdOffset + 10);
54738
+ const files = unzipSync(
54739
+ new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength)
54740
+ );
54479
54741
  const extracted = [];
54480
- let pos = cdOffset;
54481
- for (let i = 0; i < cdEntries; i++) {
54482
- if (buf.readUInt32LE(pos) !== 33639248)
54483
- throw new Error("unzip: corrupt central directory");
54484
- const method = buf.readUInt16LE(pos + 10);
54485
- const nameLen = buf.readUInt16LE(pos + 28);
54486
- const extraLen = buf.readUInt16LE(pos + 30);
54487
- const commentLen = buf.readUInt16LE(pos + 32);
54488
- const localHeaderOffset = buf.readUInt32LE(pos + 42);
54489
- const entryName = buf.toString("utf-8", pos + 46, pos + 46 + nameLen);
54490
- pos += 46 + nameLen + extraLen + commentLen;
54742
+ for (const [entryName, data] of Object.entries(files)) {
54491
54743
  if (entryName.endsWith("/")) {
54492
54744
  mkdirSync(join3(dest, entryName), { recursive: true });
54493
54745
  continue;
54494
54746
  }
54495
- const localPos = localHeaderOffset;
54496
- if (buf.readUInt32LE(localPos) !== 67324752)
54497
- throw new Error("unzip: corrupt local header");
54498
- const localNameLen = buf.readUInt16LE(localPos + 26);
54499
- const localExtraLen = buf.readUInt16LE(localPos + 28);
54500
- const compressedSize = buf.readUInt32LE(localPos + 18);
54501
- const dataStart = localPos + 30 + localNameLen + localExtraLen;
54502
- const compressedData = buf.subarray(
54503
- dataStart,
54504
- dataStart + compressedSize
54505
- );
54506
- let fileData;
54507
- if (method === 0) {
54508
- fileData = Buffer.from(compressedData);
54509
- } else if (method === 8) {
54510
- fileData = inflateRawSync(compressedData);
54511
- } else {
54512
- throw new Error(
54513
- `unzip: unsupported compression method ${method} for ${entryName}`
54514
- );
54515
- }
54516
54747
  const outPath = join3(dest, entryName);
54517
54748
  mkdirSync(dirname(outPath), { recursive: true });
54518
- writeFileSync(outPath, fileData);
54749
+ writeFileSync(outPath, data);
54519
54750
  extracted.push(outPath);
54520
54751
  }
54521
54752
  return extracted;
@@ -55241,65 +55472,15 @@ async function runRepl(initialWorkspaceFiles, onDrawnow, initialSearchPaths, nat
55241
55472
  }
55242
55473
 
55243
55474
  // src/vfs/unzipToFiles.ts
55244
- import { inflateSync } from "fflate";
55245
- var TEXT_DECODER = new TextDecoder("utf-8");
55475
+ import { unzipSync as unzipSync2 } from "fflate";
55246
55476
  function unzipToFiles(zipData) {
55247
- let eocdOffset = -1;
55248
- for (let i = zipData.length - 22; i >= 0; i--) {
55249
- if (zipData[i] === 80 && zipData[i + 1] === 75 && zipData[i + 2] === 5 && zipData[i + 3] === 6) {
55250
- eocdOffset = i;
55251
- break;
55252
- }
55253
- }
55254
- if (eocdOffset === -1) throw new Error("Invalid ZIP file");
55255
- const view = new DataView(
55256
- zipData.buffer,
55257
- zipData.byteOffset,
55258
- zipData.byteLength
55259
- );
55260
- const cdOffset = view.getUint32(eocdOffset + 16, true);
55261
- const cdEntries = view.getUint16(eocdOffset + 10, true);
55262
- const files = [];
55263
- let pos = cdOffset;
55264
- for (let i = 0; i < cdEntries; i++) {
55265
- if (view.getUint32(pos, true) !== 33639248) {
55266
- throw new Error("Corrupt ZIP central directory");
55267
- }
55268
- const method = view.getUint16(pos + 10, true);
55269
- const nameLen = view.getUint16(pos + 28, true);
55270
- const extraLen = view.getUint16(pos + 30, true);
55271
- const commentLen = view.getUint16(pos + 32, true);
55272
- const localHeaderOffset = view.getUint32(pos + 42, true);
55273
- const entryName = TEXT_DECODER.decode(
55274
- zipData.subarray(pos + 46, pos + 46 + nameLen)
55275
- );
55276
- pos += 46 + nameLen + extraLen + commentLen;
55277
- if (entryName.endsWith("/")) continue;
55278
- const localPos = localHeaderOffset;
55279
- if (view.getUint32(localPos, true) !== 67324752) {
55280
- throw new Error("Corrupt ZIP local header");
55281
- }
55282
- const localNameLen = view.getUint16(localPos + 26, true);
55283
- const localExtraLen = view.getUint16(localPos + 28, true);
55284
- const compressedSize = view.getUint32(localPos + 18, true);
55285
- const dataStart = localPos + 30 + localNameLen + localExtraLen;
55286
- const compressedData = zipData.subarray(
55287
- dataStart,
55288
- dataStart + compressedSize
55289
- );
55290
- let content;
55291
- if (method === 0) {
55292
- content = new Uint8Array(compressedData);
55293
- } else if (method === 8) {
55294
- content = inflateSync(compressedData);
55295
- } else {
55296
- throw new Error(
55297
- `Unsupported ZIP compression method ${method} for ${entryName}`
55298
- );
55299
- }
55300
- files.push({ path: entryName, content });
55477
+ const files = unzipSync2(zipData);
55478
+ const out = [];
55479
+ for (const [path, content] of Object.entries(files)) {
55480
+ if (path.endsWith("/")) continue;
55481
+ out.push({ path, content });
55301
55482
  }
55302
- return files;
55483
+ return out;
55303
55484
  }
55304
55485
 
55305
55486
  // src/cli.ts