numbl 0.1.3 → 0.1.5
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 +1603 -415
- package/dist-lib/lib.js +1514 -393
- package/dist-lib/numbl-core/executeCode.d.ts +9 -0
- package/dist-lib/numbl-core/fileIOAdapter.d.ts +2 -0
- package/dist-lib/numbl-core/helpers/quadgk.d.ts +32 -0
- package/dist-lib/numbl-core/helpers/string.d.ts +6 -0
- package/dist-lib/numbl-core/interpreter/builtins/index.d.ts +1 -0
- package/dist-lib/numbl-core/interpreter/builtins/logical.d.ts +9 -0
- package/dist-lib/numbl-core/interpreter/interpreterSpecialBuiltins.d.ts +3 -0
- package/dist-lib/numbl-core/runtime/runtime.d.ts +9 -0
- package/dist-lib/numbl-core/version.d.ts +1 -1
- package/package.json +1 -1
package/dist-cli/cli.js
CHANGED
|
@@ -20298,6 +20298,7 @@ function extractTensorElement(base, i) {
|
|
|
20298
20298
|
const im2 = base.imag[i];
|
|
20299
20299
|
return im2 === 0 ? RTV.num(base.data[i]) : RTV.complex(base.data[i], im2);
|
|
20300
20300
|
}
|
|
20301
|
+
if (base._isLogical === true) return base.data[i] !== 0;
|
|
20301
20302
|
return RTV.num(base.data[i]);
|
|
20302
20303
|
}
|
|
20303
20304
|
function resolveIndex(idx, dimSize, boundsLimit = dimSize) {
|
|
@@ -20351,17 +20352,35 @@ function growTensor2D(base, newRows, newCols) {
|
|
|
20351
20352
|
}
|
|
20352
20353
|
function assignSlice(base, rowIndices, colIndices, rhs, curRows) {
|
|
20353
20354
|
if (isRuntimeTensor(rhs)) {
|
|
20355
|
+
const nR = rowIndices.length;
|
|
20356
|
+
const nC = colIndices.length;
|
|
20354
20357
|
const [rhsRows, rhsCols] = tensorSize2D(rhs);
|
|
20355
|
-
|
|
20358
|
+
const shapeMatches = rhsRows === nR && rhsCols === nC;
|
|
20359
|
+
const sliceIsVector = nR === 1 || nC === 1;
|
|
20360
|
+
const rhsIsVector = rhsRows === 1 || rhsCols === 1;
|
|
20361
|
+
const countMatches = rhs.data.length === nR * nC;
|
|
20362
|
+
if (!shapeMatches && !(sliceIsVector && rhsIsVector && countMatches)) {
|
|
20356
20363
|
throw new RuntimeError("Subscripted assignment dimension mismatch");
|
|
20357
20364
|
}
|
|
20358
20365
|
if (rhs.imag || base.imag) ensureImag(base);
|
|
20359
|
-
|
|
20360
|
-
for (let
|
|
20361
|
-
|
|
20362
|
-
|
|
20363
|
-
|
|
20364
|
-
|
|
20366
|
+
if (shapeMatches) {
|
|
20367
|
+
for (let ri = 0; ri < nR; ri++) {
|
|
20368
|
+
for (let ci = 0; ci < nC; ci++) {
|
|
20369
|
+
const dstLi = colMajorIndex(rowIndices[ri], colIndices[ci], curRows);
|
|
20370
|
+
const srcLi = colMajorIndex(ri, ci, rhsRows);
|
|
20371
|
+
base.data[dstLi] = rhs.data[srcLi];
|
|
20372
|
+
if (base.imag) base.imag[dstLi] = rhs.imag ? rhs.imag[srcLi] : 0;
|
|
20373
|
+
}
|
|
20374
|
+
}
|
|
20375
|
+
} else {
|
|
20376
|
+
let k = 0;
|
|
20377
|
+
for (let ci = 0; ci < nC; ci++) {
|
|
20378
|
+
for (let ri = 0; ri < nR; ri++) {
|
|
20379
|
+
const dstLi = colMajorIndex(rowIndices[ri], colIndices[ci], curRows);
|
|
20380
|
+
base.data[dstLi] = rhs.data[k];
|
|
20381
|
+
if (base.imag) base.imag[dstLi] = rhs.imag ? rhs.imag[k] : 0;
|
|
20382
|
+
k++;
|
|
20383
|
+
}
|
|
20365
20384
|
}
|
|
20366
20385
|
}
|
|
20367
20386
|
} else {
|
|
@@ -20698,6 +20717,23 @@ function indexIntoScalar(base, indices) {
|
|
|
20698
20717
|
return RTV.tensor(out, [1, count]);
|
|
20699
20718
|
}
|
|
20700
20719
|
}
|
|
20720
|
+
if (indices.length === 1 && isRuntimeTensor(indices[0])) {
|
|
20721
|
+
const idx = indices[0];
|
|
20722
|
+
for (let i = 0; i < idx.data.length; i++) {
|
|
20723
|
+
const k = Math.round(idx.data[i]);
|
|
20724
|
+
if (k !== 1) throw new RuntimeError("Index exceeds array bounds");
|
|
20725
|
+
}
|
|
20726
|
+
const n = idx.data.length;
|
|
20727
|
+
const scalarRe = isRuntimeNumber(base) ? base : base.re;
|
|
20728
|
+
const data = new FloatXArray(n);
|
|
20729
|
+
data.fill(scalarRe);
|
|
20730
|
+
if (isRuntimeComplexNumber(base) && base.im !== 0) {
|
|
20731
|
+
const im2 = new FloatXArray(n);
|
|
20732
|
+
im2.fill(base.im);
|
|
20733
|
+
return RTV.tensor(data, [...idx.shape], im2);
|
|
20734
|
+
}
|
|
20735
|
+
return RTV.tensor(data, [...idx.shape]);
|
|
20736
|
+
}
|
|
20701
20737
|
for (const idx of indices) {
|
|
20702
20738
|
if (isColonIndex(idx)) continue;
|
|
20703
20739
|
const i = toNumber(idx);
|
|
@@ -20709,6 +20745,22 @@ function indexIntoTensor(base, indices) {
|
|
|
20709
20745
|
if (indices.length === 1) {
|
|
20710
20746
|
return indexIntoTensor1D(base, indices[0]);
|
|
20711
20747
|
}
|
|
20748
|
+
if (base.shape.length > indices.length) {
|
|
20749
|
+
const collapsedShape = [];
|
|
20750
|
+
for (let d = 0; d < indices.length - 1; d++) {
|
|
20751
|
+
collapsedShape.push(base.shape[d]);
|
|
20752
|
+
}
|
|
20753
|
+
let tail = 1;
|
|
20754
|
+
for (let d = indices.length - 1; d < base.shape.length; d++) {
|
|
20755
|
+
tail *= base.shape[d];
|
|
20756
|
+
}
|
|
20757
|
+
collapsedShape.push(tail);
|
|
20758
|
+
const view = { ...base, shape: collapsedShape };
|
|
20759
|
+
if (indices.length === 2) {
|
|
20760
|
+
return indexIntoTensor2D(view, indices[0], indices[1]);
|
|
20761
|
+
}
|
|
20762
|
+
return indexIntoTensorND(view, indices);
|
|
20763
|
+
}
|
|
20712
20764
|
if (indices.length === 2) {
|
|
20713
20765
|
return indexIntoTensor2D(base, indices[0], indices[1]);
|
|
20714
20766
|
}
|
|
@@ -20737,6 +20789,11 @@ function indexIntoTensor1D(base, idx) {
|
|
|
20737
20789
|
}
|
|
20738
20790
|
function indexIntoTensor2D(base, rowIdx, colIdx) {
|
|
20739
20791
|
const [rows, cols] = tensorSize2D(base);
|
|
20792
|
+
const baseLogical = base._isLogical === true;
|
|
20793
|
+
const markLogical = (t) => {
|
|
20794
|
+
if (baseLogical && isRuntimeTensor(t)) t._isLogical = true;
|
|
20795
|
+
return t;
|
|
20796
|
+
};
|
|
20740
20797
|
if (isRuntimeNumber(rowIdx) && isColonIndex(colIdx)) {
|
|
20741
20798
|
const r = Math.round(rowIdx) - 1;
|
|
20742
20799
|
if (r < 0 || r >= rows)
|
|
@@ -20747,7 +20804,7 @@ function indexIntoTensor2D(base, rowIdx, colIdx) {
|
|
|
20747
20804
|
resultData2[ci] = base.data[r + ci * rows];
|
|
20748
20805
|
if (resultImag2 && base.imag) resultImag2[ci] = base.imag[r + ci * rows];
|
|
20749
20806
|
}
|
|
20750
|
-
return RTV.tensor(resultData2, [1, cols], resultImag2);
|
|
20807
|
+
return markLogical(RTV.tensor(resultData2, [1, cols], resultImag2));
|
|
20751
20808
|
}
|
|
20752
20809
|
if (isColonIndex(rowIdx) && isRuntimeNumber(colIdx)) {
|
|
20753
20810
|
const c = Math.round(colIdx) - 1;
|
|
@@ -20759,7 +20816,7 @@ function indexIntoTensor2D(base, rowIdx, colIdx) {
|
|
|
20759
20816
|
const resultImag2 = base.imag ? new FloatXArray(rows) : void 0;
|
|
20760
20817
|
if (resultImag2 && base.imag)
|
|
20761
20818
|
for (let ri = 0; ri < rows; ri++) resultImag2[ri] = base.imag[offset + ri];
|
|
20762
|
-
return RTV.tensor(resultData2, [rows, 1], resultImag2);
|
|
20819
|
+
return markLogical(RTV.tensor(resultData2, [rows, 1], resultImag2));
|
|
20763
20820
|
}
|
|
20764
20821
|
const rowIdxArr = resolveIndex(rowIdx, rows);
|
|
20765
20822
|
const colIdxArr = resolveIndex(colIdx, cols);
|
|
@@ -20781,7 +20838,7 @@ function indexIntoTensor2D(base, rowIdx, colIdx) {
|
|
|
20781
20838
|
}
|
|
20782
20839
|
}
|
|
20783
20840
|
}
|
|
20784
|
-
return RTV.tensor(resultData, [numR, numC], resultImag);
|
|
20841
|
+
return markLogical(RTV.tensor(resultData, [numR, numC], resultImag));
|
|
20785
20842
|
}
|
|
20786
20843
|
function indexIntoTensorND(base, indices) {
|
|
20787
20844
|
const shape = base.shape;
|
|
@@ -20829,7 +20886,13 @@ function indexIntoTensorND(base, indices) {
|
|
|
20829
20886
|
subs[d] = 0;
|
|
20830
20887
|
}
|
|
20831
20888
|
}
|
|
20832
|
-
|
|
20889
|
+
const result = RTV.tensor(
|
|
20890
|
+
resultData,
|
|
20891
|
+
resultShape,
|
|
20892
|
+
resultImag
|
|
20893
|
+
);
|
|
20894
|
+
if (base._isLogical === true) result._isLogical = true;
|
|
20895
|
+
return result;
|
|
20833
20896
|
}
|
|
20834
20897
|
function indexIntoCell(base, indices) {
|
|
20835
20898
|
if (indices.length === 1) {
|
|
@@ -20994,6 +21057,7 @@ function indexIntoLogical(base, indices) {
|
|
|
20994
21057
|
return base;
|
|
20995
21058
|
}
|
|
20996
21059
|
function indexIntoTensorWithTensor(base, idx) {
|
|
21060
|
+
const baseLogical = base._isLogical === true;
|
|
20997
21061
|
if (idx._isLogical) {
|
|
20998
21062
|
const selected = [];
|
|
20999
21063
|
const selectedIm = [];
|
|
@@ -21007,12 +21071,19 @@ function indexIntoTensorWithTensor(base, idx) {
|
|
|
21007
21071
|
if (selected.length === 1) {
|
|
21008
21072
|
if (hasImag2 && selectedIm[0] !== 0)
|
|
21009
21073
|
return RTV.complex(selected[0], selectedIm[0]);
|
|
21074
|
+
if (baseLogical) return selected[0] !== 0;
|
|
21010
21075
|
return RTV.num(selected[0]);
|
|
21011
21076
|
}
|
|
21012
21077
|
const imOut2 = hasImag2 && selectedIm.some((x) => x !== 0) ? new FloatXArray(selectedIm) : void 0;
|
|
21013
21078
|
const isRow = base.shape.length === 2 && base.shape[0] === 1;
|
|
21014
21079
|
const outShape2 = isRow ? [1, selected.length] : [selected.length, 1];
|
|
21015
|
-
|
|
21080
|
+
const result2 = RTV.tensor(
|
|
21081
|
+
new FloatXArray(selected),
|
|
21082
|
+
outShape2,
|
|
21083
|
+
imOut2
|
|
21084
|
+
);
|
|
21085
|
+
if (baseLogical) result2._isLogical = true;
|
|
21086
|
+
return result2;
|
|
21016
21087
|
}
|
|
21017
21088
|
const resultData = [];
|
|
21018
21089
|
const hasImag = base.imag !== void 0;
|
|
@@ -21028,7 +21099,13 @@ function indexIntoTensorWithTensor(base, idx) {
|
|
|
21028
21099
|
const baseIsVector = base.shape.length <= 2 && (base.shape[0] === 1 || base.shape[1] === 1 || base.shape.length === 1);
|
|
21029
21100
|
const outShape = idxIs0x0 ? [0, 0] : baseIsVector ? base.shape[0] === 1 ? [1, resultData.length] : [resultData.length, 1] : idx.shape;
|
|
21030
21101
|
const imOut = hasImag && imIndices.some((x) => x !== 0) ? new FloatXArray(imIndices) : void 0;
|
|
21031
|
-
|
|
21102
|
+
const result = RTV.tensor(
|
|
21103
|
+
new FloatXArray(resultData),
|
|
21104
|
+
outShape,
|
|
21105
|
+
imOut
|
|
21106
|
+
);
|
|
21107
|
+
if (baseLogical) result._isLogical = true;
|
|
21108
|
+
return result;
|
|
21032
21109
|
}
|
|
21033
21110
|
function indexIntoRTValue(base, indices) {
|
|
21034
21111
|
if (isRuntimeNumber(base) || isRuntimeComplexNumber(base)) {
|
|
@@ -21378,10 +21455,18 @@ function storeIntoTensor2D(base, indices, rhs) {
|
|
|
21378
21455
|
return storeIntoTensorColonCol(base, indices[0], rhs, rows, cols);
|
|
21379
21456
|
}
|
|
21380
21457
|
if (rowIsTensor || colIsTensor) {
|
|
21381
|
-
const
|
|
21382
|
-
|
|
21383
|
-
|
|
21384
|
-
|
|
21458
|
+
const isEmpty = base.data.length === 0;
|
|
21459
|
+
let effectiveCols = cols;
|
|
21460
|
+
let effectiveRows = rows;
|
|
21461
|
+
if (isEmpty && isRuntimeTensor(rhs)) {
|
|
21462
|
+
const [rhsRowsG, rhsColsG] = tensorSize2D(rhs);
|
|
21463
|
+
if (rowIsColon && !colIsColon) effectiveRows = rhsRowsG;
|
|
21464
|
+
if (colIsColon && !rowIsColon) effectiveCols = rhsColsG;
|
|
21465
|
+
}
|
|
21466
|
+
const rowIndices = rowIsColon ? Array.from({ length: effectiveRows }, (_, i) => i) : resolveIndex(indices[0], rows, 0);
|
|
21467
|
+
const colIndices = colIsColon ? Array.from({ length: effectiveCols }, (_, i) => i) : resolveIndex(indices[1], cols, 0);
|
|
21468
|
+
const maxRow = rowIndices.length > 0 ? Math.max(...rowIndices) + 1 : effectiveRows;
|
|
21469
|
+
const maxCol = colIndices.length > 0 ? Math.max(...colIndices) + 1 : effectiveCols;
|
|
21385
21470
|
base = growTensor2D(base, maxRow, maxCol);
|
|
21386
21471
|
const [curRows] = tensorSize2D(base);
|
|
21387
21472
|
assignSlice(base, rowIndices, colIndices, rhs, curRows);
|
|
@@ -21809,6 +21894,9 @@ function horzcat(...values) {
|
|
|
21809
21894
|
if (values.some((v) => isRuntimeCell(v))) {
|
|
21810
21895
|
return cellCatAlongDim(values, 1);
|
|
21811
21896
|
}
|
|
21897
|
+
if (values.some((v) => isRuntimeStruct(v) || isRuntimeStructArray(v))) {
|
|
21898
|
+
return structCat(values);
|
|
21899
|
+
}
|
|
21812
21900
|
return catAlongDim(values, 1);
|
|
21813
21901
|
}
|
|
21814
21902
|
function vertcat(...values) {
|
|
@@ -21820,8 +21908,47 @@ function vertcat(...values) {
|
|
|
21820
21908
|
if (values.some((v) => isRuntimeCell(v))) {
|
|
21821
21909
|
return cellCatAlongDim(values, 0);
|
|
21822
21910
|
}
|
|
21911
|
+
if (values.some((v) => isRuntimeStruct(v) || isRuntimeStructArray(v))) {
|
|
21912
|
+
return structCat(values);
|
|
21913
|
+
}
|
|
21823
21914
|
return catAlongDim(values, 0);
|
|
21824
21915
|
}
|
|
21916
|
+
function structCat(values) {
|
|
21917
|
+
const elements = [];
|
|
21918
|
+
let fieldNames = null;
|
|
21919
|
+
for (const v of values) {
|
|
21920
|
+
if (isRuntimeStruct(v)) {
|
|
21921
|
+
const keys = Array.from(v.fields.keys());
|
|
21922
|
+
if (fieldNames === null) fieldNames = keys;
|
|
21923
|
+
else if (!arraysEqual(fieldNames, keys)) {
|
|
21924
|
+
throw new RuntimeError(
|
|
21925
|
+
"Cannot concatenate structs with different field names"
|
|
21926
|
+
);
|
|
21927
|
+
}
|
|
21928
|
+
elements.push(v);
|
|
21929
|
+
} else if (isRuntimeStructArray(v)) {
|
|
21930
|
+
if (fieldNames === null) fieldNames = [...v.fieldNames];
|
|
21931
|
+
else if (!arraysEqual(fieldNames, v.fieldNames)) {
|
|
21932
|
+
throw new RuntimeError(
|
|
21933
|
+
"Cannot concatenate struct arrays with different field names"
|
|
21934
|
+
);
|
|
21935
|
+
}
|
|
21936
|
+
for (const e of v.elements) elements.push(e);
|
|
21937
|
+
} else {
|
|
21938
|
+
if (isRuntimeTensor(v) && v.data.length === 0 && v.shape.every((d) => d === 0)) {
|
|
21939
|
+
continue;
|
|
21940
|
+
}
|
|
21941
|
+
throw new RuntimeError(`Cannot concatenate ${kstr(v)} into struct`);
|
|
21942
|
+
}
|
|
21943
|
+
}
|
|
21944
|
+
if (fieldNames === null) fieldNames = [];
|
|
21945
|
+
return RTV.structArray(fieldNames, elements);
|
|
21946
|
+
}
|
|
21947
|
+
function arraysEqual(a, b) {
|
|
21948
|
+
if (a.length !== b.length) return false;
|
|
21949
|
+
for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;
|
|
21950
|
+
return true;
|
|
21951
|
+
}
|
|
21825
21952
|
function toSparseForCat(v) {
|
|
21826
21953
|
if (isRuntimeSparseMatrix(v)) return v;
|
|
21827
21954
|
if (isRuntimeNumber(v)) {
|
|
@@ -22316,6 +22443,258 @@ function coerceToTensor(v, name) {
|
|
|
22316
22443
|
throw new RuntimeError(`${name}: argument must be numeric`);
|
|
22317
22444
|
}
|
|
22318
22445
|
|
|
22446
|
+
// src/numbl-core/helpers/string.ts
|
|
22447
|
+
function numStr(n) {
|
|
22448
|
+
if (n === Infinity) return "Inf";
|
|
22449
|
+
if (n === -Infinity) return "-Inf";
|
|
22450
|
+
if (isNaN(n)) return "NaN";
|
|
22451
|
+
if (n === 0) return "0";
|
|
22452
|
+
const prec = 5;
|
|
22453
|
+
const exp = Math.floor(Math.log10(Math.abs(n)));
|
|
22454
|
+
let s;
|
|
22455
|
+
if (exp < -4 || exp >= prec) {
|
|
22456
|
+
s = n.toExponential(prec - 1);
|
|
22457
|
+
const ePos = s.indexOf("e");
|
|
22458
|
+
let mantissa = s.slice(0, ePos);
|
|
22459
|
+
const expPart0 = s.slice(ePos);
|
|
22460
|
+
if (mantissa.includes(".")) mantissa = mantissa.replace(/\.?0+$/, "");
|
|
22461
|
+
const expPart = expPart0.replace(/([eE][+-])(\d)$/, "$10$2");
|
|
22462
|
+
s = mantissa + expPart;
|
|
22463
|
+
} else {
|
|
22464
|
+
if (Number.isInteger(n)) return String(n);
|
|
22465
|
+
s = n.toPrecision(prec);
|
|
22466
|
+
if (s.includes(".")) s = s.replace(/\.?0+$/, "");
|
|
22467
|
+
}
|
|
22468
|
+
return s;
|
|
22469
|
+
}
|
|
22470
|
+
function num2strScalar(n) {
|
|
22471
|
+
if (n === Infinity) return "Inf";
|
|
22472
|
+
if (n === -Infinity) return "-Inf";
|
|
22473
|
+
if (isNaN(n)) return "NaN";
|
|
22474
|
+
if (n === 0) return "0";
|
|
22475
|
+
if (Number.isInteger(n)) return String(n);
|
|
22476
|
+
const prec = 5;
|
|
22477
|
+
const exp = Math.floor(Math.log10(Math.abs(n)));
|
|
22478
|
+
let s;
|
|
22479
|
+
if (exp < -4 || exp >= prec) {
|
|
22480
|
+
s = n.toExponential(prec - 1);
|
|
22481
|
+
const ePos = s.indexOf("e");
|
|
22482
|
+
let mantissa = s.slice(0, ePos);
|
|
22483
|
+
const expPart0 = s.slice(ePos);
|
|
22484
|
+
if (mantissa.includes(".")) mantissa = mantissa.replace(/\.?0+$/, "");
|
|
22485
|
+
const expPart = expPart0.replace(/([eE][+-])(\d)$/, "$10$2");
|
|
22486
|
+
s = mantissa + expPart;
|
|
22487
|
+
} else {
|
|
22488
|
+
s = n.toPrecision(prec);
|
|
22489
|
+
if (s.includes(".")) s = s.replace(/\.?0+$/, "");
|
|
22490
|
+
}
|
|
22491
|
+
return s;
|
|
22492
|
+
}
|
|
22493
|
+
function applyWidth(spec, str) {
|
|
22494
|
+
const m = spec.match(/^%([-+ #]*)0?(\d+)?/);
|
|
22495
|
+
if (!m) return str;
|
|
22496
|
+
const explicitFlags = m[1] || "";
|
|
22497
|
+
const leftAlign = explicitFlags.includes("-");
|
|
22498
|
+
const afterPercent = spec.slice(1);
|
|
22499
|
+
const flagAndWidth = afterPercent.match(/^([-+ #]*)(0?)(\d+)?/);
|
|
22500
|
+
const zeroFlag = flagAndWidth ? flagAndWidth[2] === "0" : false;
|
|
22501
|
+
const width = flagAndWidth && flagAndWidth[3] ? parseInt(flagAndWidth[3]) : 0;
|
|
22502
|
+
if (width <= str.length) return str;
|
|
22503
|
+
const zeroPad = !leftAlign && zeroFlag;
|
|
22504
|
+
const padLen = width - str.length;
|
|
22505
|
+
if (leftAlign) return str + " ".repeat(padLen);
|
|
22506
|
+
if (zeroPad) {
|
|
22507
|
+
if (str[0] === "-" || str[0] === "+") {
|
|
22508
|
+
return str[0] + "0".repeat(padLen) + str.slice(1);
|
|
22509
|
+
}
|
|
22510
|
+
return "0".repeat(padLen) + str;
|
|
22511
|
+
}
|
|
22512
|
+
return " ".repeat(padLen) + str;
|
|
22513
|
+
}
|
|
22514
|
+
function sprintfFormat(fmt, args) {
|
|
22515
|
+
const flatArgs = [];
|
|
22516
|
+
for (const arg of args) {
|
|
22517
|
+
if (isRuntimeTensor(arg)) {
|
|
22518
|
+
for (let k = 0; k < arg.data.length; k++) {
|
|
22519
|
+
flatArgs.push(arg.data[k]);
|
|
22520
|
+
}
|
|
22521
|
+
} else {
|
|
22522
|
+
flatArgs.push(arg);
|
|
22523
|
+
}
|
|
22524
|
+
}
|
|
22525
|
+
let result = "";
|
|
22526
|
+
let argIdx = 0;
|
|
22527
|
+
do {
|
|
22528
|
+
const startArgIdx = argIdx;
|
|
22529
|
+
let outOfArgs = false;
|
|
22530
|
+
let i = 0;
|
|
22531
|
+
while (i < fmt.length && !outOfArgs) {
|
|
22532
|
+
if (fmt[i] === "%" && i + 1 < fmt.length) {
|
|
22533
|
+
i++;
|
|
22534
|
+
let spec = "%";
|
|
22535
|
+
while (i < fmt.length && !"dfigeEsoxXuc%".includes(fmt[i])) {
|
|
22536
|
+
if (fmt[i] === "*") {
|
|
22537
|
+
if (argIdx >= flatArgs.length) {
|
|
22538
|
+
outOfArgs = true;
|
|
22539
|
+
break;
|
|
22540
|
+
}
|
|
22541
|
+
spec += String(Math.round(toNumber(flatArgs[argIdx++])));
|
|
22542
|
+
i++;
|
|
22543
|
+
} else {
|
|
22544
|
+
spec += fmt[i];
|
|
22545
|
+
i++;
|
|
22546
|
+
}
|
|
22547
|
+
}
|
|
22548
|
+
if (outOfArgs) break;
|
|
22549
|
+
if (i < fmt.length) {
|
|
22550
|
+
const ch = fmt[i];
|
|
22551
|
+
i++;
|
|
22552
|
+
if (ch === "%") {
|
|
22553
|
+
result += "%";
|
|
22554
|
+
} else if (argIdx >= flatArgs.length) {
|
|
22555
|
+
outOfArgs = true;
|
|
22556
|
+
} else if (ch === "d" || ch === "i" || ch === "u") {
|
|
22557
|
+
const raw = toNumber(flatArgs[argIdx++]);
|
|
22558
|
+
const isInt = Number.isInteger(raw);
|
|
22559
|
+
const canPrintAsInt = ch === "u" ? isInt && raw >= 0 : isInt;
|
|
22560
|
+
if (!canPrintAsInt) {
|
|
22561
|
+
let eStr = raw.toExponential(6);
|
|
22562
|
+
eStr = eStr.replace(/e([+-])(\d)$/, "e$10$2");
|
|
22563
|
+
result += applyWidth(spec, eStr);
|
|
22564
|
+
} else {
|
|
22565
|
+
const n = raw;
|
|
22566
|
+
const flags = spec.slice(1);
|
|
22567
|
+
const hasPlus = flags.includes("+");
|
|
22568
|
+
const leftAlign = flags.includes("-");
|
|
22569
|
+
const widthMatch = spec.match(/^%[^0-9]*(\d+)/);
|
|
22570
|
+
const width = widthMatch ? parseInt(widthMatch[1]) : 0;
|
|
22571
|
+
const zeroPad = !leftAlign && /^[-+ ]*0/.test(spec.slice(1));
|
|
22572
|
+
const s = String(Math.abs(n));
|
|
22573
|
+
const sign = n < 0 ? "-" : hasPlus ? "+" : "";
|
|
22574
|
+
if (width > 0) {
|
|
22575
|
+
const padChar = zeroPad ? "0" : " ";
|
|
22576
|
+
const padLen = Math.max(0, width - sign.length - s.length);
|
|
22577
|
+
const pad = padChar.repeat(padLen);
|
|
22578
|
+
result += leftAlign ? sign + s + " ".repeat(padLen) : zeroPad ? sign + pad + s : pad + sign + s;
|
|
22579
|
+
} else {
|
|
22580
|
+
result += sign + s;
|
|
22581
|
+
}
|
|
22582
|
+
}
|
|
22583
|
+
} else if (ch === "f") {
|
|
22584
|
+
const n = toNumber(flatArgs[argIdx++]);
|
|
22585
|
+
if (!isFinite(n) || isNaN(n)) {
|
|
22586
|
+
result += applyWidth(spec, numStr(n));
|
|
22587
|
+
} else {
|
|
22588
|
+
const fFlags = spec.slice(1);
|
|
22589
|
+
const fHasPlus = fFlags.includes("+");
|
|
22590
|
+
const precMatch = spec.match(/\.(\d+)/);
|
|
22591
|
+
const prec = precMatch ? parseInt(precMatch[1]) : 6;
|
|
22592
|
+
const formatted = n.toFixed(prec);
|
|
22593
|
+
const fSign = n < 0 ? "" : fHasPlus ? "+" : "";
|
|
22594
|
+
result += applyWidth(spec, fSign + formatted);
|
|
22595
|
+
}
|
|
22596
|
+
} else if (ch === "e" || ch === "E") {
|
|
22597
|
+
const n = toNumber(flatArgs[argIdx++]);
|
|
22598
|
+
if (!isFinite(n) || isNaN(n)) {
|
|
22599
|
+
result += applyWidth(spec, numStr(n));
|
|
22600
|
+
} else {
|
|
22601
|
+
const precMatch = spec.match(/\.(\d+)/);
|
|
22602
|
+
const prec = precMatch ? parseInt(precMatch[1]) : 6;
|
|
22603
|
+
let eStr = n.toExponential(prec);
|
|
22604
|
+
eStr = eStr.replace(/e([+-])(\d)$/, "e$10$2");
|
|
22605
|
+
if (ch === "E") eStr = eStr.toUpperCase();
|
|
22606
|
+
result += applyWidth(spec, eStr);
|
|
22607
|
+
}
|
|
22608
|
+
} else if (ch === "x" || ch === "X") {
|
|
22609
|
+
const n = Math.round(toNumber(flatArgs[argIdx++]));
|
|
22610
|
+
let s = Math.abs(n).toString(16);
|
|
22611
|
+
if (ch === "X") s = s.toUpperCase();
|
|
22612
|
+
result += applyWidth(spec, s);
|
|
22613
|
+
} else if (ch === "o") {
|
|
22614
|
+
const n = Math.round(toNumber(flatArgs[argIdx++]));
|
|
22615
|
+
result += applyWidth(spec, Math.abs(n).toString(8));
|
|
22616
|
+
} else if (ch === "g" || ch === "G") {
|
|
22617
|
+
const gVal = toNumber(flatArgs[argIdx++]);
|
|
22618
|
+
if (!isFinite(gVal) || isNaN(gVal)) {
|
|
22619
|
+
result += applyWidth(spec, numStr(gVal));
|
|
22620
|
+
} else {
|
|
22621
|
+
const precMatch = spec.match(/\.(\d+)/);
|
|
22622
|
+
const gPrec = precMatch ? parseInt(precMatch[1]) : 6;
|
|
22623
|
+
let gStr;
|
|
22624
|
+
if (gVal === 0) {
|
|
22625
|
+
gStr = "0";
|
|
22626
|
+
} else {
|
|
22627
|
+
const exp = Math.floor(Math.log10(Math.abs(gVal)));
|
|
22628
|
+
if (exp < -4 || exp >= gPrec) {
|
|
22629
|
+
gStr = gVal.toExponential(gPrec - 1);
|
|
22630
|
+
const ePos = gStr.indexOf("e");
|
|
22631
|
+
let mantissa = gStr.slice(0, ePos);
|
|
22632
|
+
let expPart = gStr.slice(ePos);
|
|
22633
|
+
if (mantissa.includes(".")) {
|
|
22634
|
+
mantissa = mantissa.replace(/\.?0+$/, "");
|
|
22635
|
+
}
|
|
22636
|
+
expPart = expPart.replace(/e([+-])(\d)$/, "e$10$2");
|
|
22637
|
+
gStr = mantissa + expPart;
|
|
22638
|
+
} else {
|
|
22639
|
+
gStr = gVal.toPrecision(gPrec);
|
|
22640
|
+
if (gStr.includes(".")) {
|
|
22641
|
+
gStr = gStr.replace(/\.?0+$/, "");
|
|
22642
|
+
}
|
|
22643
|
+
if (gStr.includes("e")) {
|
|
22644
|
+
gStr = String(parseFloat(gStr));
|
|
22645
|
+
}
|
|
22646
|
+
}
|
|
22647
|
+
}
|
|
22648
|
+
if (ch === "G") gStr = gStr.toUpperCase();
|
|
22649
|
+
result += applyWidth(spec, gStr);
|
|
22650
|
+
}
|
|
22651
|
+
} else if (ch === "s") {
|
|
22652
|
+
const sVal = toString(flatArgs[argIdx++]);
|
|
22653
|
+
const sFlags = spec.slice(1);
|
|
22654
|
+
const sLeftAlign = sFlags.includes("-");
|
|
22655
|
+
const sWidthMatch = spec.match(/^%[^0-9]*(\d+)/);
|
|
22656
|
+
const sWidth = sWidthMatch ? parseInt(sWidthMatch[1]) : 0;
|
|
22657
|
+
if (sWidth > sVal.length) {
|
|
22658
|
+
const sPad = " ".repeat(sWidth - sVal.length);
|
|
22659
|
+
result += sLeftAlign ? sVal + sPad : sPad + sVal;
|
|
22660
|
+
} else {
|
|
22661
|
+
result += sVal;
|
|
22662
|
+
}
|
|
22663
|
+
} else if (ch === "c") {
|
|
22664
|
+
result += String.fromCharCode(
|
|
22665
|
+
Math.round(toNumber(flatArgs[argIdx++]))
|
|
22666
|
+
);
|
|
22667
|
+
} else {
|
|
22668
|
+
result += spec + ch;
|
|
22669
|
+
argIdx++;
|
|
22670
|
+
}
|
|
22671
|
+
}
|
|
22672
|
+
} else if (fmt[i] === "\\" && i + 1 < fmt.length) {
|
|
22673
|
+
i++;
|
|
22674
|
+
switch (fmt[i]) {
|
|
22675
|
+
case "n":
|
|
22676
|
+
result += "\n";
|
|
22677
|
+
break;
|
|
22678
|
+
case "t":
|
|
22679
|
+
result += " ";
|
|
22680
|
+
break;
|
|
22681
|
+
case "\\":
|
|
22682
|
+
result += "\\";
|
|
22683
|
+
break;
|
|
22684
|
+
default:
|
|
22685
|
+
result += "\\" + fmt[i];
|
|
22686
|
+
}
|
|
22687
|
+
i++;
|
|
22688
|
+
} else {
|
|
22689
|
+
result += fmt[i];
|
|
22690
|
+
i++;
|
|
22691
|
+
}
|
|
22692
|
+
}
|
|
22693
|
+
if (argIdx === startArgIdx) break;
|
|
22694
|
+
} while (argIdx < flatArgs.length);
|
|
22695
|
+
return result;
|
|
22696
|
+
}
|
|
22697
|
+
|
|
22319
22698
|
// src/numbl-core/helpers/arithmetic.ts
|
|
22320
22699
|
function toComplex(v) {
|
|
22321
22700
|
if (isRuntimeComplexNumber(v)) return { re: v.re, im: v.im };
|
|
@@ -22543,7 +22922,26 @@ function tensorElemwiseComplex(at, bt, opCode, jsOp) {
|
|
|
22543
22922
|
const isReal = resultIm.every((x) => x === 0);
|
|
22544
22923
|
return RTV.tensor(resultRe, at.shape, isReal ? void 0 : resultIm);
|
|
22545
22924
|
}
|
|
22925
|
+
function coerceToConcatString(v) {
|
|
22926
|
+
if (isRuntimeString(v)) return v;
|
|
22927
|
+
if (isRuntimeChar(v)) return v.value;
|
|
22928
|
+
if (isRuntimeLogical(v)) return v ? "true" : "false";
|
|
22929
|
+
if (isRuntimeNumber(v)) return num2strScalar(v);
|
|
22930
|
+
if (isRuntimeTensor(v) && v.data.length === 1 && !v.imag) {
|
|
22931
|
+
const x = v.data[0];
|
|
22932
|
+
if (v._isLogical === true) return x ? "true" : "false";
|
|
22933
|
+
return num2strScalar(x);
|
|
22934
|
+
}
|
|
22935
|
+
return null;
|
|
22936
|
+
}
|
|
22546
22937
|
function mAdd(a, b) {
|
|
22938
|
+
if (isRuntimeString(a) || isRuntimeString(b)) {
|
|
22939
|
+
const aStr = coerceToConcatString(a);
|
|
22940
|
+
const bStr = coerceToConcatString(b);
|
|
22941
|
+
if (aStr !== null && bStr !== null) {
|
|
22942
|
+
return RTV.string(aStr + bStr);
|
|
22943
|
+
}
|
|
22944
|
+
}
|
|
22547
22945
|
const m = matchSameShapeTensors(a, b);
|
|
22548
22946
|
if (m) {
|
|
22549
22947
|
const [at, bt] = m;
|
|
@@ -23695,7 +24093,7 @@ var token_config_default = {
|
|
|
23695
24093
|
stripUnderscores: true,
|
|
23696
24094
|
integerToken: "Integer",
|
|
23697
24095
|
floatToken: "Float",
|
|
23698
|
-
exponentChars: ["e", "E"],
|
|
24096
|
+
exponentChars: ["e", "E", "d", "D"],
|
|
23699
24097
|
decimalPoint: ".",
|
|
23700
24098
|
dotOperatorPrefixes: ["*", "/", "\\", "^"]
|
|
23701
24099
|
},
|
|
@@ -24000,6 +24398,9 @@ function tokenizeDetailed(input) {
|
|
|
24000
24398
|
if (numCfg.stripUnderscores) {
|
|
24001
24399
|
lexeme = lexeme.replace(/_/g, "");
|
|
24002
24400
|
}
|
|
24401
|
+
if (isFloat) {
|
|
24402
|
+
lexeme = lexeme.replace(/[dD]/g, "e");
|
|
24403
|
+
}
|
|
24003
24404
|
const tok = isFloat ? Token[numCfg.floatToken] : Token[numCfg.integerToken];
|
|
24004
24405
|
lineStart = false;
|
|
24005
24406
|
out.push({ token: tok, lexeme, start, end: pos });
|
|
@@ -26991,6 +27392,29 @@ function methodDispatch(rt, name, nargout, args) {
|
|
|
26991
27392
|
}
|
|
26992
27393
|
return fieldVal;
|
|
26993
27394
|
}
|
|
27395
|
+
{
|
|
27396
|
+
const accessorKey = `${firstRV.className}.get.${name}`;
|
|
27397
|
+
if (!rt.activeAccessors.has(accessorKey)) {
|
|
27398
|
+
const getter = rt.cachedResolveClassMethod(
|
|
27399
|
+
firstRV.className,
|
|
27400
|
+
`get.${name}`
|
|
27401
|
+
);
|
|
27402
|
+
if (getter) {
|
|
27403
|
+
rt.activeAccessors.add(accessorKey);
|
|
27404
|
+
let gotVal;
|
|
27405
|
+
try {
|
|
27406
|
+
gotVal = getter(1, first);
|
|
27407
|
+
} finally {
|
|
27408
|
+
rt.activeAccessors.delete(accessorKey);
|
|
27409
|
+
}
|
|
27410
|
+
const remaining = args.slice(1);
|
|
27411
|
+
if (remaining.length > 0) {
|
|
27412
|
+
return rt.index(gotVal, remaining, nargout);
|
|
27413
|
+
}
|
|
27414
|
+
return gotVal;
|
|
27415
|
+
}
|
|
27416
|
+
}
|
|
27417
|
+
}
|
|
26994
27418
|
try {
|
|
26995
27419
|
return callClassMethod(rt, firstRV.className, name, nargout, args);
|
|
26996
27420
|
} catch (e) {
|
|
@@ -27945,6 +28369,7 @@ function index(rt, base, indices, nargout = 1, skipSubsref = false) {
|
|
|
27945
28369
|
const im2 = t.imag[i];
|
|
27946
28370
|
return im2 === 0 ? t.data[i] : RTV.complex(t.data[i], im2);
|
|
27947
28371
|
}
|
|
28372
|
+
if (t._isLogical === true) return t.data[i] !== 0;
|
|
27948
28373
|
return t.data[i];
|
|
27949
28374
|
}
|
|
27950
28375
|
} else if (nIdx === 2) {
|
|
@@ -27953,7 +28378,14 @@ function index(rt, base, indices, nargout = 1, skipSubsref = false) {
|
|
|
27953
28378
|
if (typeof ri === "number" && typeof ci === "number") {
|
|
27954
28379
|
const s = t.shape;
|
|
27955
28380
|
const rows = s.length === 0 ? 1 : s.length === 1 ? 1 : s[0];
|
|
27956
|
-
|
|
28381
|
+
let cols;
|
|
28382
|
+
if (s.length === 0) cols = 1;
|
|
28383
|
+
else if (s.length === 1) cols = s[0];
|
|
28384
|
+
else if (s.length === 2) cols = s[1];
|
|
28385
|
+
else {
|
|
28386
|
+
cols = 1;
|
|
28387
|
+
for (let k = 1; k < s.length; k++) cols *= s[k];
|
|
28388
|
+
}
|
|
27957
28389
|
const r = Math.round(ri) - 1;
|
|
27958
28390
|
const c = Math.round(ci) - 1;
|
|
27959
28391
|
if (r < 0 || r >= rows || c < 0 || c >= cols)
|
|
@@ -27963,6 +28395,7 @@ function index(rt, base, indices, nargout = 1, skipSubsref = false) {
|
|
|
27963
28395
|
const im2 = t.imag[lin];
|
|
27964
28396
|
return im2 === 0 ? t.data[lin] : RTV.complex(t.data[lin], im2);
|
|
27965
28397
|
}
|
|
28398
|
+
if (t._isLogical === true) return t.data[lin] !== 0;
|
|
27966
28399
|
return t.data[lin];
|
|
27967
28400
|
}
|
|
27968
28401
|
} else if (nIdx >= 3) {
|
|
@@ -28353,14 +28786,20 @@ function multiOutputCellAssign(base, indices, results) {
|
|
|
28353
28786
|
if (base === void 0 || base === null) base = RTV.cell([], [0, 0]);
|
|
28354
28787
|
let mv = ensureRuntimeValue(base);
|
|
28355
28788
|
if (!isRuntimeCell(mv)) mv = RTV.cell([], [0, 0]);
|
|
28356
|
-
const idxMv = ensureRuntimeValue(indices);
|
|
28357
28789
|
let idxArray;
|
|
28358
|
-
if (
|
|
28359
|
-
|
|
28360
|
-
|
|
28361
|
-
|
|
28790
|
+
if (indices === COLON_SENTINEL) {
|
|
28791
|
+
const n = mv.data.length;
|
|
28792
|
+
idxArray = [];
|
|
28793
|
+
for (let i = 1; i <= n; i++) idxArray.push(i);
|
|
28362
28794
|
} else {
|
|
28363
|
-
|
|
28795
|
+
const idxMv = ensureRuntimeValue(indices);
|
|
28796
|
+
if (isRuntimeTensor(idxMv)) {
|
|
28797
|
+
idxArray = Array.from(idxMv.data);
|
|
28798
|
+
} else if (isRuntimeNumber(idxMv)) {
|
|
28799
|
+
idxArray = [idxMv];
|
|
28800
|
+
} else {
|
|
28801
|
+
idxArray = [1];
|
|
28802
|
+
}
|
|
28364
28803
|
}
|
|
28365
28804
|
for (let i = 0; i < idxArray.length && i < results.length; i++) {
|
|
28366
28805
|
const idx = idxArray[i];
|
|
@@ -28371,225 +28810,6 @@ function multiOutputCellAssign(base, indices, results) {
|
|
|
28371
28810
|
return mv;
|
|
28372
28811
|
}
|
|
28373
28812
|
|
|
28374
|
-
// src/numbl-core/helpers/string.ts
|
|
28375
|
-
function numStr(n) {
|
|
28376
|
-
if (n === Infinity) return "Inf";
|
|
28377
|
-
if (n === -Infinity) return "-Inf";
|
|
28378
|
-
if (isNaN(n)) return "NaN";
|
|
28379
|
-
if (n === 0) return "0";
|
|
28380
|
-
const prec = 5;
|
|
28381
|
-
const exp = Math.floor(Math.log10(Math.abs(n)));
|
|
28382
|
-
let s;
|
|
28383
|
-
if (exp < -4 || exp >= prec) {
|
|
28384
|
-
s = n.toExponential(prec - 1);
|
|
28385
|
-
const ePos = s.indexOf("e");
|
|
28386
|
-
let mantissa = s.slice(0, ePos);
|
|
28387
|
-
const expPart0 = s.slice(ePos);
|
|
28388
|
-
if (mantissa.includes(".")) mantissa = mantissa.replace(/\.?0+$/, "");
|
|
28389
|
-
const expPart = expPart0.replace(/([eE][+-])(\d)$/, "$10$2");
|
|
28390
|
-
s = mantissa + expPart;
|
|
28391
|
-
} else {
|
|
28392
|
-
if (Number.isInteger(n)) return String(n);
|
|
28393
|
-
s = n.toPrecision(prec);
|
|
28394
|
-
if (s.includes(".")) s = s.replace(/\.?0+$/, "");
|
|
28395
|
-
}
|
|
28396
|
-
return s;
|
|
28397
|
-
}
|
|
28398
|
-
function applyWidth(spec, str) {
|
|
28399
|
-
const m = spec.match(/^%([-+ #]*)0?(\d+)?/);
|
|
28400
|
-
if (!m) return str;
|
|
28401
|
-
const explicitFlags = m[1] || "";
|
|
28402
|
-
const leftAlign = explicitFlags.includes("-");
|
|
28403
|
-
const afterPercent = spec.slice(1);
|
|
28404
|
-
const flagAndWidth = afterPercent.match(/^([-+ #]*)(0?)(\d+)?/);
|
|
28405
|
-
const zeroFlag = flagAndWidth ? flagAndWidth[2] === "0" : false;
|
|
28406
|
-
const width = flagAndWidth && flagAndWidth[3] ? parseInt(flagAndWidth[3]) : 0;
|
|
28407
|
-
if (width <= str.length) return str;
|
|
28408
|
-
const zeroPad = !leftAlign && zeroFlag;
|
|
28409
|
-
const padLen = width - str.length;
|
|
28410
|
-
if (leftAlign) return str + " ".repeat(padLen);
|
|
28411
|
-
if (zeroPad) {
|
|
28412
|
-
if (str[0] === "-" || str[0] === "+") {
|
|
28413
|
-
return str[0] + "0".repeat(padLen) + str.slice(1);
|
|
28414
|
-
}
|
|
28415
|
-
return "0".repeat(padLen) + str;
|
|
28416
|
-
}
|
|
28417
|
-
return " ".repeat(padLen) + str;
|
|
28418
|
-
}
|
|
28419
|
-
function sprintfFormat(fmt, args) {
|
|
28420
|
-
const flatArgs = [];
|
|
28421
|
-
for (const arg of args) {
|
|
28422
|
-
if (isRuntimeTensor(arg)) {
|
|
28423
|
-
for (let k = 0; k < arg.data.length; k++) {
|
|
28424
|
-
flatArgs.push(arg.data[k]);
|
|
28425
|
-
}
|
|
28426
|
-
} else {
|
|
28427
|
-
flatArgs.push(arg);
|
|
28428
|
-
}
|
|
28429
|
-
}
|
|
28430
|
-
let result = "";
|
|
28431
|
-
let argIdx = 0;
|
|
28432
|
-
do {
|
|
28433
|
-
const startArgIdx = argIdx;
|
|
28434
|
-
let outOfArgs = false;
|
|
28435
|
-
let i = 0;
|
|
28436
|
-
while (i < fmt.length && !outOfArgs) {
|
|
28437
|
-
if (fmt[i] === "%" && i + 1 < fmt.length) {
|
|
28438
|
-
i++;
|
|
28439
|
-
let spec = "%";
|
|
28440
|
-
while (i < fmt.length && !"dfigeEsoxXuc%".includes(fmt[i])) {
|
|
28441
|
-
spec += fmt[i];
|
|
28442
|
-
i++;
|
|
28443
|
-
}
|
|
28444
|
-
if (i < fmt.length) {
|
|
28445
|
-
const ch = fmt[i];
|
|
28446
|
-
i++;
|
|
28447
|
-
if (ch === "%") {
|
|
28448
|
-
result += "%";
|
|
28449
|
-
} else if (argIdx >= flatArgs.length) {
|
|
28450
|
-
outOfArgs = true;
|
|
28451
|
-
} else if (ch === "d" || ch === "i" || ch === "u") {
|
|
28452
|
-
const raw = toNumber(flatArgs[argIdx++]);
|
|
28453
|
-
const isInt = Number.isInteger(raw);
|
|
28454
|
-
const canPrintAsInt = ch === "u" ? isInt && raw >= 0 : isInt;
|
|
28455
|
-
if (!canPrintAsInt) {
|
|
28456
|
-
let eStr = raw.toExponential(6);
|
|
28457
|
-
eStr = eStr.replace(/e([+-])(\d)$/, "e$10$2");
|
|
28458
|
-
result += applyWidth(spec, eStr);
|
|
28459
|
-
} else {
|
|
28460
|
-
const n = raw;
|
|
28461
|
-
const flags = spec.slice(1);
|
|
28462
|
-
const hasPlus = flags.includes("+");
|
|
28463
|
-
const leftAlign = flags.includes("-");
|
|
28464
|
-
const widthMatch = spec.match(/^%[^0-9]*(\d+)/);
|
|
28465
|
-
const width = widthMatch ? parseInt(widthMatch[1]) : 0;
|
|
28466
|
-
const zeroPad = !leftAlign && /^[-+ ]*0/.test(spec.slice(1));
|
|
28467
|
-
const s = String(Math.abs(n));
|
|
28468
|
-
const sign = n < 0 ? "-" : hasPlus ? "+" : "";
|
|
28469
|
-
if (width > 0) {
|
|
28470
|
-
const padChar = zeroPad ? "0" : " ";
|
|
28471
|
-
const padLen = Math.max(0, width - sign.length - s.length);
|
|
28472
|
-
const pad = padChar.repeat(padLen);
|
|
28473
|
-
result += leftAlign ? sign + s + " ".repeat(padLen) : zeroPad ? sign + pad + s : pad + sign + s;
|
|
28474
|
-
} else {
|
|
28475
|
-
result += sign + s;
|
|
28476
|
-
}
|
|
28477
|
-
}
|
|
28478
|
-
} else if (ch === "f") {
|
|
28479
|
-
const n = toNumber(flatArgs[argIdx++]);
|
|
28480
|
-
if (!isFinite(n) || isNaN(n)) {
|
|
28481
|
-
result += applyWidth(spec, numStr(n));
|
|
28482
|
-
} else {
|
|
28483
|
-
const fFlags = spec.slice(1);
|
|
28484
|
-
const fHasPlus = fFlags.includes("+");
|
|
28485
|
-
const precMatch = spec.match(/\.(\d+)/);
|
|
28486
|
-
const prec = precMatch ? parseInt(precMatch[1]) : 6;
|
|
28487
|
-
const formatted = n.toFixed(prec);
|
|
28488
|
-
const fSign = n < 0 ? "" : fHasPlus ? "+" : "";
|
|
28489
|
-
result += applyWidth(spec, fSign + formatted);
|
|
28490
|
-
}
|
|
28491
|
-
} else if (ch === "e" || ch === "E") {
|
|
28492
|
-
const n = toNumber(flatArgs[argIdx++]);
|
|
28493
|
-
if (!isFinite(n) || isNaN(n)) {
|
|
28494
|
-
result += applyWidth(spec, numStr(n));
|
|
28495
|
-
} else {
|
|
28496
|
-
const precMatch = spec.match(/\.(\d+)/);
|
|
28497
|
-
const prec = precMatch ? parseInt(precMatch[1]) : 6;
|
|
28498
|
-
let eStr = n.toExponential(prec);
|
|
28499
|
-
eStr = eStr.replace(/e([+-])(\d)$/, "e$10$2");
|
|
28500
|
-
if (ch === "E") eStr = eStr.toUpperCase();
|
|
28501
|
-
result += applyWidth(spec, eStr);
|
|
28502
|
-
}
|
|
28503
|
-
} else if (ch === "x" || ch === "X") {
|
|
28504
|
-
const n = Math.round(toNumber(flatArgs[argIdx++]));
|
|
28505
|
-
let s = Math.abs(n).toString(16);
|
|
28506
|
-
if (ch === "X") s = s.toUpperCase();
|
|
28507
|
-
result += applyWidth(spec, s);
|
|
28508
|
-
} else if (ch === "o") {
|
|
28509
|
-
const n = Math.round(toNumber(flatArgs[argIdx++]));
|
|
28510
|
-
result += applyWidth(spec, Math.abs(n).toString(8));
|
|
28511
|
-
} else if (ch === "g" || ch === "G") {
|
|
28512
|
-
const gVal = toNumber(flatArgs[argIdx++]);
|
|
28513
|
-
if (!isFinite(gVal) || isNaN(gVal)) {
|
|
28514
|
-
result += applyWidth(spec, numStr(gVal));
|
|
28515
|
-
} else {
|
|
28516
|
-
const precMatch = spec.match(/\.(\d+)/);
|
|
28517
|
-
const gPrec = precMatch ? parseInt(precMatch[1]) : 6;
|
|
28518
|
-
let gStr;
|
|
28519
|
-
if (gVal === 0) {
|
|
28520
|
-
gStr = "0";
|
|
28521
|
-
} else {
|
|
28522
|
-
const exp = Math.floor(Math.log10(Math.abs(gVal)));
|
|
28523
|
-
if (exp < -4 || exp >= gPrec) {
|
|
28524
|
-
gStr = gVal.toExponential(gPrec - 1);
|
|
28525
|
-
const ePos = gStr.indexOf("e");
|
|
28526
|
-
let mantissa = gStr.slice(0, ePos);
|
|
28527
|
-
let expPart = gStr.slice(ePos);
|
|
28528
|
-
if (mantissa.includes(".")) {
|
|
28529
|
-
mantissa = mantissa.replace(/\.?0+$/, "");
|
|
28530
|
-
}
|
|
28531
|
-
expPart = expPart.replace(/e([+-])(\d)$/, "e$10$2");
|
|
28532
|
-
gStr = mantissa + expPart;
|
|
28533
|
-
} else {
|
|
28534
|
-
gStr = gVal.toPrecision(gPrec);
|
|
28535
|
-
if (gStr.includes(".")) {
|
|
28536
|
-
gStr = gStr.replace(/\.?0+$/, "");
|
|
28537
|
-
}
|
|
28538
|
-
if (gStr.includes("e")) {
|
|
28539
|
-
gStr = String(parseFloat(gStr));
|
|
28540
|
-
}
|
|
28541
|
-
}
|
|
28542
|
-
}
|
|
28543
|
-
if (ch === "G") gStr = gStr.toUpperCase();
|
|
28544
|
-
result += applyWidth(spec, gStr);
|
|
28545
|
-
}
|
|
28546
|
-
} else if (ch === "s") {
|
|
28547
|
-
const sVal = toString(flatArgs[argIdx++]);
|
|
28548
|
-
const sFlags = spec.slice(1);
|
|
28549
|
-
const sLeftAlign = sFlags.includes("-");
|
|
28550
|
-
const sWidthMatch = spec.match(/^%[^0-9]*(\d+)/);
|
|
28551
|
-
const sWidth = sWidthMatch ? parseInt(sWidthMatch[1]) : 0;
|
|
28552
|
-
if (sWidth > sVal.length) {
|
|
28553
|
-
const sPad = " ".repeat(sWidth - sVal.length);
|
|
28554
|
-
result += sLeftAlign ? sVal + sPad : sPad + sVal;
|
|
28555
|
-
} else {
|
|
28556
|
-
result += sVal;
|
|
28557
|
-
}
|
|
28558
|
-
} else if (ch === "c") {
|
|
28559
|
-
result += String.fromCharCode(
|
|
28560
|
-
Math.round(toNumber(flatArgs[argIdx++]))
|
|
28561
|
-
);
|
|
28562
|
-
} else {
|
|
28563
|
-
result += spec + ch;
|
|
28564
|
-
argIdx++;
|
|
28565
|
-
}
|
|
28566
|
-
}
|
|
28567
|
-
} else if (fmt[i] === "\\" && i + 1 < fmt.length) {
|
|
28568
|
-
i++;
|
|
28569
|
-
switch (fmt[i]) {
|
|
28570
|
-
case "n":
|
|
28571
|
-
result += "\n";
|
|
28572
|
-
break;
|
|
28573
|
-
case "t":
|
|
28574
|
-
result += " ";
|
|
28575
|
-
break;
|
|
28576
|
-
case "\\":
|
|
28577
|
-
result += "\\";
|
|
28578
|
-
break;
|
|
28579
|
-
default:
|
|
28580
|
-
result += "\\" + fmt[i];
|
|
28581
|
-
}
|
|
28582
|
-
i++;
|
|
28583
|
-
} else {
|
|
28584
|
-
result += fmt[i];
|
|
28585
|
-
i++;
|
|
28586
|
-
}
|
|
28587
|
-
}
|
|
28588
|
-
if (argIdx === startArgIdx) break;
|
|
28589
|
-
} while (argIdx < flatArgs.length);
|
|
28590
|
-
return result;
|
|
28591
|
-
}
|
|
28592
|
-
|
|
28593
28813
|
// src/numbl-core/interpreter/builtins/misc.ts
|
|
28594
28814
|
registerIBuiltin({
|
|
28595
28815
|
name: "substruct",
|
|
@@ -28789,7 +29009,7 @@ for (const name of ["clear", "clc", "clf"]) {
|
|
|
28789
29009
|
name,
|
|
28790
29010
|
resolve: () => ({
|
|
28791
29011
|
outputTypes: [],
|
|
28792
|
-
apply: () => 0
|
|
29012
|
+
apply: () => void 0
|
|
28793
29013
|
})
|
|
28794
29014
|
});
|
|
28795
29015
|
}
|
|
@@ -28923,7 +29143,7 @@ registerIBuiltin({
|
|
|
28923
29143
|
name: "set",
|
|
28924
29144
|
resolve: () => ({
|
|
28925
29145
|
outputTypes: [],
|
|
28926
|
-
apply: () => 0
|
|
29146
|
+
apply: () => void 0
|
|
28927
29147
|
})
|
|
28928
29148
|
});
|
|
28929
29149
|
for (const name of [
|
|
@@ -28945,7 +29165,7 @@ for (const name of [
|
|
|
28945
29165
|
name,
|
|
28946
29166
|
resolve: () => ({
|
|
28947
29167
|
outputTypes: [],
|
|
28948
|
-
apply: () => 0
|
|
29168
|
+
apply: () => void 0
|
|
28949
29169
|
})
|
|
28950
29170
|
});
|
|
28951
29171
|
}
|
|
@@ -29341,6 +29561,24 @@ registerIBuiltin({
|
|
|
29341
29561
|
}
|
|
29342
29562
|
})
|
|
29343
29563
|
});
|
|
29564
|
+
function getMexExt() {
|
|
29565
|
+
if (typeof process === "undefined") return "";
|
|
29566
|
+
const platform = process.platform;
|
|
29567
|
+
const cpuArch = process.arch;
|
|
29568
|
+
if (platform === "win32") return "mexw64";
|
|
29569
|
+
if (platform === "darwin")
|
|
29570
|
+
return cpuArch === "arm64" ? "mexmaca64" : "mexmaci64";
|
|
29571
|
+
return "mexa64";
|
|
29572
|
+
}
|
|
29573
|
+
defineBuiltin({
|
|
29574
|
+
name: "mexext",
|
|
29575
|
+
cases: [
|
|
29576
|
+
{
|
|
29577
|
+
match: (argTypes) => argTypes.length === 0 ? [{ kind: "char" }] : null,
|
|
29578
|
+
apply: () => RTV.char(getMexExt())
|
|
29579
|
+
}
|
|
29580
|
+
]
|
|
29581
|
+
});
|
|
29344
29582
|
var _platform = typeof process !== "undefined" ? process.platform : "linux";
|
|
29345
29583
|
for (const [name, val] of [
|
|
29346
29584
|
["ismac", _platform === "darwin"],
|
|
@@ -31590,6 +31828,114 @@ function bisectEvent(eventIdx, step, events) {
|
|
|
31590
31828
|
return [tOld + xFinal * h, denseOutputEval(yOld, Q, h, xFinal)];
|
|
31591
31829
|
}
|
|
31592
31830
|
|
|
31831
|
+
// src/numbl-core/helpers/quadgk.ts
|
|
31832
|
+
var XK = [
|
|
31833
|
+
-0.9914553711208126,
|
|
31834
|
+
-0.9491079123427585,
|
|
31835
|
+
-0.8648644233597691,
|
|
31836
|
+
-0.7415311855993945,
|
|
31837
|
+
-0.586087235467691,
|
|
31838
|
+
-0.4058451513773972,
|
|
31839
|
+
-0.2077849550078985,
|
|
31840
|
+
0,
|
|
31841
|
+
0.2077849550078985,
|
|
31842
|
+
0.4058451513773972,
|
|
31843
|
+
0.586087235467691,
|
|
31844
|
+
0.7415311855993945,
|
|
31845
|
+
0.8648644233597691,
|
|
31846
|
+
0.9491079123427585,
|
|
31847
|
+
0.9914553711208126
|
|
31848
|
+
];
|
|
31849
|
+
var WK = [
|
|
31850
|
+
0.0229353220105292,
|
|
31851
|
+
0.0630920926299786,
|
|
31852
|
+
0.1047900103222502,
|
|
31853
|
+
0.1406532597155259,
|
|
31854
|
+
0.1690047266392679,
|
|
31855
|
+
0.1903505780647854,
|
|
31856
|
+
0.2044329400752989,
|
|
31857
|
+
0.2094821410847278,
|
|
31858
|
+
0.2044329400752989,
|
|
31859
|
+
0.1903505780647854,
|
|
31860
|
+
0.1690047266392679,
|
|
31861
|
+
0.1406532597155259,
|
|
31862
|
+
0.1047900103222502,
|
|
31863
|
+
0.0630920926299786,
|
|
31864
|
+
0.0229353220105292
|
|
31865
|
+
];
|
|
31866
|
+
var WG = [
|
|
31867
|
+
0.1294849661688697,
|
|
31868
|
+
0.2797053914892767,
|
|
31869
|
+
0.3818300505051189,
|
|
31870
|
+
0.4179591836734694,
|
|
31871
|
+
0.3818300505051189,
|
|
31872
|
+
0.2797053914892767,
|
|
31873
|
+
0.1294849661688697
|
|
31874
|
+
];
|
|
31875
|
+
function kronrodNodes(lo, hi) {
|
|
31876
|
+
const m = (lo + hi) / 2;
|
|
31877
|
+
const h = (hi - lo) / 2;
|
|
31878
|
+
const out = new Array(15);
|
|
31879
|
+
for (let i = 0; i < 15; i++) out[i] = m + h * XK[i];
|
|
31880
|
+
return out;
|
|
31881
|
+
}
|
|
31882
|
+
function segmentEstimate(lo, hi, fv) {
|
|
31883
|
+
const h = (hi - lo) / 2;
|
|
31884
|
+
let K = 0;
|
|
31885
|
+
let G = 0;
|
|
31886
|
+
for (let i = 0; i < 15; i++) K += WK[i] * fv[i];
|
|
31887
|
+
for (let i = 0; i < 7; i++) G += WG[i] * fv[2 * i + 1];
|
|
31888
|
+
K *= h;
|
|
31889
|
+
G *= h;
|
|
31890
|
+
return { K, err: Math.abs(K - G) };
|
|
31891
|
+
}
|
|
31892
|
+
function quadgkAdaptive(integrand, a, b, opts = {}) {
|
|
31893
|
+
const relTol = opts.relTol ?? 1e-6;
|
|
31894
|
+
const absTol = opts.absTol ?? 1e-10;
|
|
31895
|
+
const maxIntervals = opts.maxIntervalCount ?? 650;
|
|
31896
|
+
if (a === b) return { value: 0, errbnd: 0, intervalsUsed: 0 };
|
|
31897
|
+
const sign = a < b ? 1 : -1;
|
|
31898
|
+
const lo0 = Math.min(a, b);
|
|
31899
|
+
const hi0 = Math.max(a, b);
|
|
31900
|
+
const segmentOn = (lo, hi) => {
|
|
31901
|
+
const pts = kronrodNodes(lo, hi);
|
|
31902
|
+
const fv = integrand(pts);
|
|
31903
|
+
if (fv.length !== 15) {
|
|
31904
|
+
throw new Error(
|
|
31905
|
+
`quadgk: integrand must return 15 values for 15 nodes, got ${fv.length}`
|
|
31906
|
+
);
|
|
31907
|
+
}
|
|
31908
|
+
return segmentEstimate(lo, hi, fv);
|
|
31909
|
+
};
|
|
31910
|
+
const initial = segmentOn(lo0, hi0);
|
|
31911
|
+
let totalK = initial.K;
|
|
31912
|
+
let totalErr = initial.err;
|
|
31913
|
+
const worklist = [{ lo: lo0, hi: hi0, ...initial }];
|
|
31914
|
+
const converged = () => totalErr <= Math.max(absTol, relTol * Math.abs(totalK));
|
|
31915
|
+
let iters = 0;
|
|
31916
|
+
while (!converged() && worklist.length < maxIntervals && iters < 1e4) {
|
|
31917
|
+
iters++;
|
|
31918
|
+
let worstIdx = 0;
|
|
31919
|
+
for (let i = 1; i < worklist.length; i++) {
|
|
31920
|
+
if (worklist[i].err > worklist[worstIdx].err) worstIdx = i;
|
|
31921
|
+
}
|
|
31922
|
+
const worst = worklist[worstIdx];
|
|
31923
|
+
if (worst.hi - worst.lo <= 1e-15 * (hi0 - lo0)) break;
|
|
31924
|
+
const mid = (worst.lo + worst.hi) / 2;
|
|
31925
|
+
const s1 = segmentOn(worst.lo, mid);
|
|
31926
|
+
const s2 = segmentOn(mid, worst.hi);
|
|
31927
|
+
totalK += s1.K + s2.K - worst.K;
|
|
31928
|
+
totalErr += s1.err + s2.err - worst.err;
|
|
31929
|
+
worklist[worstIdx] = { lo: worst.lo, hi: mid, ...s1 };
|
|
31930
|
+
worklist.push({ lo: mid, hi: worst.hi, ...s2 });
|
|
31931
|
+
}
|
|
31932
|
+
return {
|
|
31933
|
+
value: sign * totalK,
|
|
31934
|
+
errbnd: totalErr,
|
|
31935
|
+
intervalsUsed: worklist.length
|
|
31936
|
+
};
|
|
31937
|
+
}
|
|
31938
|
+
|
|
31593
31939
|
// src/numbl-core/runtime/specialBuiltinNames.ts
|
|
31594
31940
|
var SPECIAL_BUILTIN_NAMES = [
|
|
31595
31941
|
"help",
|
|
@@ -31678,6 +32024,7 @@ var SPECIAL_BUILTIN_NAMES = [
|
|
|
31678
32024
|
"webread",
|
|
31679
32025
|
"delete",
|
|
31680
32026
|
"rmdir",
|
|
32027
|
+
"movefile",
|
|
31681
32028
|
"unzip",
|
|
31682
32029
|
"dir",
|
|
31683
32030
|
"warning",
|
|
@@ -31691,7 +32038,8 @@ var SPECIAL_BUILTIN_NAMES = [
|
|
|
31691
32038
|
"ode45",
|
|
31692
32039
|
"ode23",
|
|
31693
32040
|
"deval",
|
|
31694
|
-
"toc"
|
|
32041
|
+
"toc",
|
|
32042
|
+
"quadgk"
|
|
31695
32043
|
];
|
|
31696
32044
|
|
|
31697
32045
|
// src/numbl-core/runtime/specialBuiltins.ts
|
|
@@ -31705,42 +32053,58 @@ function registerSpecial(name, fn) {
|
|
|
31705
32053
|
})
|
|
31706
32054
|
});
|
|
31707
32055
|
}
|
|
32056
|
+
function registerSpecialVoid(name, fn) {
|
|
32057
|
+
registerDynamicIBuiltin({
|
|
32058
|
+
name,
|
|
32059
|
+
resolve: () => ({
|
|
32060
|
+
outputTypes: [],
|
|
32061
|
+
apply: (args) => {
|
|
32062
|
+
fn(args);
|
|
32063
|
+
return void 0;
|
|
32064
|
+
}
|
|
32065
|
+
})
|
|
32066
|
+
});
|
|
32067
|
+
}
|
|
31708
32068
|
function registerSpecialBuiltins(rt) {
|
|
31709
|
-
registerSpecial("help", (
|
|
32069
|
+
registerSpecial("help", (nargout, args) => {
|
|
32070
|
+
let text = "";
|
|
32071
|
+
const emit = (s) => {
|
|
32072
|
+
text += s;
|
|
32073
|
+
if (nargout === 0) rt.output(s);
|
|
32074
|
+
};
|
|
31710
32075
|
if (args.length === 0) {
|
|
31711
32076
|
const names = getAllBuiltinNames().sort();
|
|
31712
|
-
|
|
31713
|
-
|
|
31714
|
-
|
|
31715
|
-
|
|
31716
|
-
|
|
31717
|
-
|
|
31718
|
-
|
|
31719
|
-
|
|
31720
|
-
|
|
31721
|
-
|
|
31722
|
-
rt.output(`No help available for '${name}'.
|
|
32077
|
+
emit("Available builtins:\n");
|
|
32078
|
+
emit(" " + names.join(", ") + "\n");
|
|
32079
|
+
emit("\nType 'help <name>' for help on a specific builtin.\n");
|
|
32080
|
+
} else {
|
|
32081
|
+
const name = toString(args[0]);
|
|
32082
|
+
const h = getIBuiltinHelp(name);
|
|
32083
|
+
if (!h) {
|
|
32084
|
+
const allNames = getAllBuiltinNames();
|
|
32085
|
+
if (allNames.includes(name)) {
|
|
32086
|
+
emit(`No help available for '${name}'.
|
|
31723
32087
|
`);
|
|
31724
|
-
|
|
31725
|
-
|
|
32088
|
+
} else {
|
|
32089
|
+
emit(`Unknown function '${name}'.
|
|
31726
32090
|
`);
|
|
31727
|
-
|
|
31728
|
-
|
|
31729
|
-
|
|
31730
|
-
rt.output(` ${h.signatures.join("\n ")}
|
|
32091
|
+
}
|
|
32092
|
+
} else {
|
|
32093
|
+
emit(` ${h.signatures.join("\n ")}
|
|
31731
32094
|
|
|
31732
32095
|
`);
|
|
31733
|
-
|
|
32096
|
+
emit(`${h.description}
|
|
31734
32097
|
`);
|
|
31735
|
-
|
|
32098
|
+
}
|
|
32099
|
+
}
|
|
32100
|
+
return nargout >= 1 ? RTV.char(text) : void 0;
|
|
31736
32101
|
});
|
|
31737
|
-
|
|
32102
|
+
registerSpecialVoid("disp", (args) => {
|
|
31738
32103
|
if (args.length >= 1) {
|
|
31739
32104
|
const mv = ensureRuntimeValue(args[0]);
|
|
31740
|
-
if (isRuntimeTensor(mv) && mv.data.length === 0) return
|
|
32105
|
+
if (isRuntimeTensor(mv) && mv.data.length === 0) return;
|
|
31741
32106
|
rt.output(displayValue(mv) + "\n");
|
|
31742
32107
|
}
|
|
31743
|
-
return 0;
|
|
31744
32108
|
});
|
|
31745
32109
|
registerSpecial("toc", (nargout) => {
|
|
31746
32110
|
const elapsed = (performance.now() - getTicTime()) / 1e3;
|
|
@@ -31750,12 +32114,13 @@ function registerSpecialBuiltins(rt) {
|
|
|
31750
32114
|
}
|
|
31751
32115
|
return RTV.num(elapsed);
|
|
31752
32116
|
});
|
|
31753
|
-
registerSpecial("warning", (
|
|
31754
|
-
if (args.length === 0) return RTV.num(0);
|
|
32117
|
+
registerSpecial("warning", (nargout, args) => {
|
|
32118
|
+
if (args.length === 0) return nargout >= 1 ? RTV.num(0) : void 0;
|
|
31755
32119
|
const margs = args.map((a) => ensureRuntimeValue(a));
|
|
31756
32120
|
if (margs.length === 2 && isRuntimeChar(margs[0]) && isRuntimeChar(margs[1])) {
|
|
31757
32121
|
const state = toString(margs[0]);
|
|
31758
32122
|
if (state === "on" || state === "off") {
|
|
32123
|
+
if (nargout === 0) return void 0;
|
|
31759
32124
|
return RTV.struct(
|
|
31760
32125
|
/* @__PURE__ */ new Map([
|
|
31761
32126
|
["state", RTV.char("on")],
|
|
@@ -31784,9 +32149,9 @@ function registerSpecialBuiltins(rt) {
|
|
|
31784
32149
|
} else {
|
|
31785
32150
|
rt.output("Warning: " + sprintfFormat(fmt, fmtArgs) + "\n");
|
|
31786
32151
|
}
|
|
31787
|
-
return RTV.num(0);
|
|
32152
|
+
return nargout >= 1 ? RTV.num(0) : void 0;
|
|
31788
32153
|
});
|
|
31789
|
-
registerSpecial("fprintf", (
|
|
32154
|
+
registerSpecial("fprintf", (nargout, args) => {
|
|
31790
32155
|
let output = "";
|
|
31791
32156
|
if (args.length >= 1) {
|
|
31792
32157
|
const margs = args.map((a) => ensureRuntimeValue(a));
|
|
@@ -31797,27 +32162,7 @@ function registerSpecialBuiltins(rt) {
|
|
|
31797
32162
|
fmtIdx = 1;
|
|
31798
32163
|
}
|
|
31799
32164
|
const fmt = toString(margs[fmtIdx]);
|
|
31800
|
-
|
|
31801
|
-
for (let i = fmtIdx + 1; i < margs.length; i++) {
|
|
31802
|
-
const a = margs[i];
|
|
31803
|
-
if (isRuntimeTensor(a)) {
|
|
31804
|
-
for (let j = 0; j < a.data.length; j++)
|
|
31805
|
-
scalarArgs.push(RTV.num(a.data[j]));
|
|
31806
|
-
} else {
|
|
31807
|
-
scalarArgs.push(a);
|
|
31808
|
-
}
|
|
31809
|
-
}
|
|
31810
|
-
const specCount = (fmt.match(/%[^%]/g) || []).length;
|
|
31811
|
-
if (specCount === 0 || scalarArgs.length === 0) {
|
|
31812
|
-
output = sprintfFormat(fmt, scalarArgs);
|
|
31813
|
-
} else {
|
|
31814
|
-
let idx = 0;
|
|
31815
|
-
while (idx < scalarArgs.length) {
|
|
31816
|
-
const batch = scalarArgs.slice(idx, idx + specCount);
|
|
31817
|
-
output += sprintfFormat(fmt, batch);
|
|
31818
|
-
idx += specCount;
|
|
31819
|
-
}
|
|
31820
|
-
}
|
|
32165
|
+
output = sprintfFormat(fmt, margs.slice(fmtIdx + 1));
|
|
31821
32166
|
if (fid === 1 || fid === 2) {
|
|
31822
32167
|
rt.output(output);
|
|
31823
32168
|
} else {
|
|
@@ -31828,7 +32173,7 @@ function registerSpecialBuiltins(rt) {
|
|
|
31828
32173
|
rt.fileIO.fwrite(fid, output);
|
|
31829
32174
|
}
|
|
31830
32175
|
}
|
|
31831
|
-
return output.length;
|
|
32176
|
+
return nargout >= 1 ? output.length : void 0;
|
|
31832
32177
|
});
|
|
31833
32178
|
registerSpecial("arrayfun", (nargout, args) => {
|
|
31834
32179
|
return arrayfunImpl(rt, nargout, args);
|
|
@@ -31860,6 +32205,55 @@ function registerSpecialBuiltins(rt) {
|
|
|
31860
32205
|
registerSpecial("bsxfun", (nargout, args) => {
|
|
31861
32206
|
return bsxfunImpl(rt, nargout, args);
|
|
31862
32207
|
});
|
|
32208
|
+
registerSpecial("quadgk", (nargout, args) => {
|
|
32209
|
+
if (args.length < 3)
|
|
32210
|
+
throw new RuntimeError(
|
|
32211
|
+
"quadgk: requires at least 3 arguments (fun, a, b)"
|
|
32212
|
+
);
|
|
32213
|
+
const fnArg = ensureRuntimeValue(args[0]);
|
|
32214
|
+
if (!isRuntimeFunction(fnArg))
|
|
32215
|
+
throw new RuntimeError("quadgk: first argument must be a function");
|
|
32216
|
+
const a = toNumber(ensureRuntimeValue(args[1]));
|
|
32217
|
+
const b = toNumber(ensureRuntimeValue(args[2]));
|
|
32218
|
+
let relTol;
|
|
32219
|
+
let absTol;
|
|
32220
|
+
let maxIntervalCount;
|
|
32221
|
+
for (let i = 3; i + 1 < args.length; i += 2) {
|
|
32222
|
+
const keyRv = ensureRuntimeValue(args[i]);
|
|
32223
|
+
const key = isRuntimeChar(keyRv) ? keyRv.value : isRuntimeString(keyRv) ? keyRv : "";
|
|
32224
|
+
const lowerKey = key.toLowerCase();
|
|
32225
|
+
const valRv = ensureRuntimeValue(args[i + 1]);
|
|
32226
|
+
if (lowerKey === "reltol") relTol = toNumber(valRv);
|
|
32227
|
+
else if (lowerKey === "abstol") absTol = toNumber(valRv);
|
|
32228
|
+
else if (lowerKey === "maxintervalcount")
|
|
32229
|
+
maxIntervalCount = toNumber(valRv);
|
|
32230
|
+
}
|
|
32231
|
+
const integrand = (pts) => {
|
|
32232
|
+
const vecData = new FloatXArray(pts);
|
|
32233
|
+
const vec = RTV.tensor(vecData, [1, pts.length]);
|
|
32234
|
+
const resultRaw = rt.index(fnArg, [vec], 1);
|
|
32235
|
+
const rv = ensureRuntimeValue(resultRaw);
|
|
32236
|
+
if (isRuntimeNumber(rv)) {
|
|
32237
|
+
return new Array(pts.length).fill(rv);
|
|
32238
|
+
}
|
|
32239
|
+
if (isRuntimeTensor(rv)) {
|
|
32240
|
+
if (rv.data.length !== pts.length) {
|
|
32241
|
+
throw new RuntimeError(
|
|
32242
|
+
`quadgk: integrand returned ${rv.data.length} values for ${pts.length} nodes`
|
|
32243
|
+
);
|
|
32244
|
+
}
|
|
32245
|
+
return Array.from(rv.data);
|
|
32246
|
+
}
|
|
32247
|
+
throw new RuntimeError("quadgk: integrand must return a numeric vector");
|
|
32248
|
+
};
|
|
32249
|
+
const result = quadgkAdaptive(integrand, a, b, {
|
|
32250
|
+
relTol,
|
|
32251
|
+
absTol,
|
|
32252
|
+
maxIntervalCount
|
|
32253
|
+
});
|
|
32254
|
+
if (nargout >= 2) return [result.value, result.errbnd];
|
|
32255
|
+
return result.value;
|
|
32256
|
+
});
|
|
31863
32257
|
registerSpecial("subsref", (nargout, args) => {
|
|
31864
32258
|
return subsrefBuiltin(rt, nargout, args);
|
|
31865
32259
|
});
|
|
@@ -32482,7 +32876,7 @@ function registerSpecialBuiltins(rt) {
|
|
|
32482
32876
|
return RTV.char(text);
|
|
32483
32877
|
}
|
|
32484
32878
|
});
|
|
32485
|
-
|
|
32879
|
+
registerSpecialVoid("delete", (args) => {
|
|
32486
32880
|
const io = requireFileIO();
|
|
32487
32881
|
if (!io.deleteFile)
|
|
32488
32882
|
throw new RuntimeError("delete is not available in this environment");
|
|
@@ -32492,7 +32886,6 @@ function registerSpecialBuiltins(rt) {
|
|
|
32492
32886
|
for (const arg of margs) {
|
|
32493
32887
|
io.deleteFile(toString(arg));
|
|
32494
32888
|
}
|
|
32495
|
-
return 0;
|
|
32496
32889
|
});
|
|
32497
32890
|
registerSpecial("rmdir", (nargout, args) => {
|
|
32498
32891
|
const io = requireFileIO();
|
|
@@ -32515,6 +32908,34 @@ function registerSpecialBuiltins(rt) {
|
|
|
32515
32908
|
RTV.char("")
|
|
32516
32909
|
];
|
|
32517
32910
|
});
|
|
32911
|
+
registerSpecial("movefile", (nargout, args) => {
|
|
32912
|
+
const io = requireFileIO();
|
|
32913
|
+
if (!io.movefile)
|
|
32914
|
+
throw new RuntimeError("movefile is not available in this environment");
|
|
32915
|
+
const margs = args.map((a) => ensureRuntimeValue(a));
|
|
32916
|
+
if (margs.length < 1)
|
|
32917
|
+
throw new RuntimeError("movefile requires at least 1 argument");
|
|
32918
|
+
const source = toString(margs[0]);
|
|
32919
|
+
const destination = margs.length >= 2 ? toString(margs[1]) : rt.system?.cwd() ?? ".";
|
|
32920
|
+
let force = false;
|
|
32921
|
+
if (margs.length >= 3) {
|
|
32922
|
+
const third = toString(margs[2]);
|
|
32923
|
+
if (third.toLowerCase() === "f") force = true;
|
|
32924
|
+
}
|
|
32925
|
+
const ok = io.movefile(source, destination, force);
|
|
32926
|
+
if (nargout === 0) {
|
|
32927
|
+
if (!ok)
|
|
32928
|
+
throw new RuntimeError(
|
|
32929
|
+
`movefile: cannot move '${source}' to '${destination}'`
|
|
32930
|
+
);
|
|
32931
|
+
return void 0;
|
|
32932
|
+
}
|
|
32933
|
+
return nargout <= 1 ? RTV.num(ok ? 1 : 0) : [
|
|
32934
|
+
RTV.num(ok ? 1 : 0),
|
|
32935
|
+
RTV.char(ok ? "" : `Cannot move '${source}' to '${destination}'`),
|
|
32936
|
+
RTV.char("")
|
|
32937
|
+
];
|
|
32938
|
+
});
|
|
32518
32939
|
registerSpecial("unzip", (nargout, args) => {
|
|
32519
32940
|
const io = requireFileIO();
|
|
32520
32941
|
if (!io.unzip)
|
|
@@ -32566,7 +32987,7 @@ function registerSpecialBuiltins(rt) {
|
|
|
32566
32987
|
const cellData = extracted.map((f) => RTV.char(f));
|
|
32567
32988
|
return RTV.cell(cellData, [1, cellData.length]);
|
|
32568
32989
|
}
|
|
32569
|
-
return 0;
|
|
32990
|
+
return void 0;
|
|
32570
32991
|
});
|
|
32571
32992
|
registerSpecial("dir", (nargout, args) => {
|
|
32572
32993
|
const io = requireFileIO();
|
|
@@ -32663,7 +33084,7 @@ function registerSpecialBuiltins(rt) {
|
|
|
32663
33084
|
const parts = margs.map((a) => toString(a));
|
|
32664
33085
|
return RTV.char(parts.join("/"));
|
|
32665
33086
|
});
|
|
32666
|
-
|
|
33087
|
+
registerSpecialVoid("assignin", (args) => {
|
|
32667
33088
|
if (args.length < 3)
|
|
32668
33089
|
throw new RuntimeError("assignin requires 3 arguments");
|
|
32669
33090
|
const margs = args.map((a) => ensureRuntimeValue(a));
|
|
@@ -32678,7 +33099,6 @@ function registerSpecialBuiltins(rt) {
|
|
|
32678
33099
|
} else {
|
|
32679
33100
|
rt.setWorkspaceVariable(varName, args[2]);
|
|
32680
33101
|
}
|
|
32681
|
-
return 0;
|
|
32682
33102
|
});
|
|
32683
33103
|
registerSpecial("evalin", (_nargout, args) => {
|
|
32684
33104
|
if (args.length < 2)
|
|
@@ -32699,13 +33119,12 @@ function registerSpecialBuiltins(rt) {
|
|
|
32699
33119
|
}
|
|
32700
33120
|
return val;
|
|
32701
33121
|
});
|
|
32702
|
-
|
|
33122
|
+
registerSpecialVoid("drawnow", () => {
|
|
32703
33123
|
rt.drawnow();
|
|
32704
|
-
return 0;
|
|
32705
33124
|
});
|
|
32706
|
-
registerSpecial("pause", (
|
|
33125
|
+
registerSpecial("pause", (nargout, args) => {
|
|
32707
33126
|
rt.pause(args[0] ?? 0);
|
|
32708
|
-
return 0;
|
|
33127
|
+
return nargout >= 1 ? RTV.char("on") : void 0;
|
|
32709
33128
|
});
|
|
32710
33129
|
registerSpecial("mfilename", (_nargout, args) => {
|
|
32711
33130
|
const file = rt.$file ?? "";
|
|
@@ -32749,7 +33168,7 @@ function registerSpecialBuiltins(rt) {
|
|
|
32749
33168
|
}
|
|
32750
33169
|
}
|
|
32751
33170
|
if (nargout >= 1) return RTV.char(rt.searchPaths.join(";"));
|
|
32752
|
-
return 0;
|
|
33171
|
+
return void 0;
|
|
32753
33172
|
});
|
|
32754
33173
|
registerSpecial("rmpath", (nargout, args) => {
|
|
32755
33174
|
if (!rt.onPathChange) {
|
|
@@ -32769,11 +33188,11 @@ function registerSpecialBuiltins(rt) {
|
|
|
32769
33188
|
}
|
|
32770
33189
|
}
|
|
32771
33190
|
if (nargout >= 1) return RTV.char(rt.searchPaths.join(";"));
|
|
32772
|
-
return 0;
|
|
33191
|
+
return void 0;
|
|
32773
33192
|
});
|
|
32774
|
-
registerSpecial("savepath", () => {
|
|
33193
|
+
registerSpecial("savepath", (nargout) => {
|
|
32775
33194
|
rt.output("Warning: savepath is a no-op in numbl\n");
|
|
32776
|
-
return 0;
|
|
33195
|
+
return nargout >= 1 ? RTV.num(0) : void 0;
|
|
32777
33196
|
});
|
|
32778
33197
|
registerSpecial("input", (_nargout, args) => {
|
|
32779
33198
|
const margs = args.map((a) => ensureRuntimeValue(a));
|
|
@@ -32836,11 +33255,11 @@ function registerSpecialBuiltins(rt) {
|
|
|
32836
33255
|
}
|
|
32837
33256
|
return RTV.char(sys?.getEnv(toString(args[0])) ?? "");
|
|
32838
33257
|
});
|
|
32839
|
-
|
|
33258
|
+
registerSpecialVoid("setenv", (args) => {
|
|
32840
33259
|
const sys = rt.system;
|
|
32841
33260
|
if (args.length === 2) {
|
|
32842
33261
|
sys?.setEnv(toString(args[0]), toString(args[1]));
|
|
32843
|
-
return
|
|
33262
|
+
return;
|
|
32844
33263
|
}
|
|
32845
33264
|
if (args.length === 1) {
|
|
32846
33265
|
const d = args[0];
|
|
@@ -32848,20 +33267,26 @@ function registerSpecialBuiltins(rt) {
|
|
|
32848
33267
|
for (const { key, value } of d.entries.values()) {
|
|
32849
33268
|
sys?.setEnv(toString(key), toString(value));
|
|
32850
33269
|
}
|
|
32851
|
-
return
|
|
33270
|
+
return;
|
|
32852
33271
|
}
|
|
32853
33272
|
sys?.setEnv(toString(d), "");
|
|
32854
|
-
return
|
|
33273
|
+
return;
|
|
32855
33274
|
}
|
|
32856
33275
|
throw new RuntimeError("setenv: invalid arguments");
|
|
32857
33276
|
});
|
|
32858
33277
|
registerSpecial("pwd", () => {
|
|
32859
33278
|
return RTV.char(rt.system?.cwd() ?? "/");
|
|
32860
33279
|
});
|
|
32861
|
-
registerSpecial("cd", (
|
|
33280
|
+
registerSpecial("cd", (nargout, args) => {
|
|
32862
33281
|
const sys = rt.system;
|
|
32863
33282
|
const curDir = sys?.cwd() ?? "/";
|
|
32864
|
-
if (args.length === 0)
|
|
33283
|
+
if (args.length === 0) {
|
|
33284
|
+
if (nargout === 0) {
|
|
33285
|
+
rt.output(curDir + "\n");
|
|
33286
|
+
return void 0;
|
|
33287
|
+
}
|
|
33288
|
+
return RTV.char(curDir);
|
|
33289
|
+
}
|
|
32865
33290
|
const target = toString(args[0]);
|
|
32866
33291
|
if (sys) {
|
|
32867
33292
|
try {
|
|
@@ -32869,15 +33294,18 @@ function registerSpecialBuiltins(rt) {
|
|
|
32869
33294
|
} catch {
|
|
32870
33295
|
throw new RuntimeError(`Cannot change directory to '${target}'`);
|
|
32871
33296
|
}
|
|
33297
|
+
if (rt.onCwdChange) {
|
|
33298
|
+
rt.onCwdChange(sys.cwd());
|
|
33299
|
+
}
|
|
32872
33300
|
}
|
|
32873
|
-
return RTV.char(curDir);
|
|
33301
|
+
return nargout >= 1 ? RTV.char(curDir) : void 0;
|
|
32874
33302
|
});
|
|
32875
|
-
registerSpecial("figure", (
|
|
33303
|
+
registerSpecial("figure", (nargout, args) => {
|
|
32876
33304
|
const handle = args.length > 0 ? args[0] : 1;
|
|
32877
33305
|
plotInstr(rt.plotInstructions, { type: "set_figure_handle", handle });
|
|
32878
|
-
return 0;
|
|
33306
|
+
return nargout >= 1 ? RTV.num(toNumber(ensureRuntimeValue(handle))) : void 0;
|
|
32879
33307
|
});
|
|
32880
|
-
registerSpecial("subplot", (
|
|
33308
|
+
registerSpecial("subplot", (nargout, args) => {
|
|
32881
33309
|
if (args.length >= 3) {
|
|
32882
33310
|
plotInstr(rt.plotInstructions, {
|
|
32883
33311
|
type: "set_subplot",
|
|
@@ -32886,43 +33314,41 @@ function registerSpecialBuiltins(rt) {
|
|
|
32886
33314
|
index: args[2]
|
|
32887
33315
|
});
|
|
32888
33316
|
}
|
|
32889
|
-
return 0;
|
|
33317
|
+
return nargout >= 1 ? RTV.num(0) : void 0;
|
|
32890
33318
|
});
|
|
32891
|
-
registerSpecial("title", (
|
|
33319
|
+
registerSpecial("title", (nargout, args) => {
|
|
32892
33320
|
if (args.length > 0) {
|
|
32893
33321
|
plotInstr(rt.plotInstructions, { type: "set_title", text: args[0] });
|
|
32894
33322
|
}
|
|
32895
|
-
return 0;
|
|
33323
|
+
return nargout >= 1 ? RTV.num(0) : void 0;
|
|
32896
33324
|
});
|
|
32897
|
-
registerSpecial("xlabel", (
|
|
33325
|
+
registerSpecial("xlabel", (nargout, args) => {
|
|
32898
33326
|
if (args.length > 0) {
|
|
32899
33327
|
plotInstr(rt.plotInstructions, { type: "set_xlabel", text: args[0] });
|
|
32900
33328
|
}
|
|
32901
|
-
return 0;
|
|
33329
|
+
return nargout >= 1 ? RTV.num(0) : void 0;
|
|
32902
33330
|
});
|
|
32903
|
-
registerSpecial("ylabel", (
|
|
33331
|
+
registerSpecial("ylabel", (nargout, args) => {
|
|
32904
33332
|
if (args.length > 0) {
|
|
32905
33333
|
plotInstr(rt.plotInstructions, { type: "set_ylabel", text: args[0] });
|
|
32906
33334
|
}
|
|
32907
|
-
return 0;
|
|
33335
|
+
return nargout >= 1 ? RTV.num(0) : void 0;
|
|
32908
33336
|
});
|
|
32909
|
-
|
|
33337
|
+
registerSpecialVoid("hold", (args) => {
|
|
32910
33338
|
if (args.length > 0) {
|
|
32911
33339
|
plotInstr(rt.plotInstructions, { type: "set_hold", value: args[0] });
|
|
32912
33340
|
}
|
|
32913
|
-
return 0;
|
|
32914
33341
|
});
|
|
32915
|
-
|
|
33342
|
+
registerSpecialVoid("grid", (args) => {
|
|
32916
33343
|
if (args.length > 0) {
|
|
32917
33344
|
plotInstr(rt.plotInstructions, { type: "set_grid", value: args[0] });
|
|
32918
33345
|
}
|
|
32919
|
-
return 0;
|
|
32920
33346
|
});
|
|
32921
|
-
registerSpecial("legend", (
|
|
33347
|
+
registerSpecial("legend", (nargout, args) => {
|
|
32922
33348
|
legendCall(rt.plotInstructions, args);
|
|
32923
|
-
return 0;
|
|
33349
|
+
return nargout >= 1 ? RTV.num(0) : void 0;
|
|
32924
33350
|
});
|
|
32925
|
-
registerSpecial("close", (
|
|
33351
|
+
registerSpecial("close", (nargout, args) => {
|
|
32926
33352
|
if (args.length > 0) {
|
|
32927
33353
|
const val = toString(args[0]);
|
|
32928
33354
|
if (val === "all") {
|
|
@@ -32933,26 +33359,25 @@ function registerSpecialBuiltins(rt) {
|
|
|
32933
33359
|
} else {
|
|
32934
33360
|
plotInstr(rt.plotInstructions, { type: "close" });
|
|
32935
33361
|
}
|
|
32936
|
-
return 0;
|
|
33362
|
+
return nargout >= 1 ? RTV.num(1) : void 0;
|
|
32937
33363
|
});
|
|
32938
|
-
registerSpecial("sgtitle", (
|
|
33364
|
+
registerSpecial("sgtitle", (nargout, args) => {
|
|
32939
33365
|
if (args.length > 0) {
|
|
32940
33366
|
plotInstr(rt.plotInstructions, { type: "set_sgtitle", text: args[0] });
|
|
32941
33367
|
}
|
|
32942
|
-
return 0;
|
|
33368
|
+
return nargout >= 1 ? RTV.num(0) : void 0;
|
|
32943
33369
|
});
|
|
32944
|
-
|
|
33370
|
+
registerSpecialVoid("shading", (args) => {
|
|
32945
33371
|
if (args.length > 0) {
|
|
32946
33372
|
plotInstr(rt.plotInstructions, {
|
|
32947
33373
|
type: "set_shading",
|
|
32948
33374
|
shading: args[0]
|
|
32949
33375
|
});
|
|
32950
33376
|
}
|
|
32951
|
-
return 0;
|
|
32952
33377
|
});
|
|
32953
|
-
registerSpecial("clf", () => {
|
|
33378
|
+
registerSpecial("clf", (nargout) => {
|
|
32954
33379
|
plotInstr(rt.plotInstructions, { type: "clf" });
|
|
32955
|
-
return 0;
|
|
33380
|
+
return nargout >= 1 ? RTV.num(1) : void 0;
|
|
32956
33381
|
});
|
|
32957
33382
|
registerSpecial("ode45", (nargout, args) => {
|
|
32958
33383
|
return _ode45Impl(rt, nargout, args, dormandPrince45);
|
|
@@ -33408,6 +33833,8 @@ var Runtime = class _Runtime {
|
|
|
33408
33833
|
classMethodCache = /* @__PURE__ */ new Map();
|
|
33409
33834
|
/** Callback for addpath/rmpath — mutates search paths and rebuilds function index. */
|
|
33410
33835
|
onPathChange = null;
|
|
33836
|
+
/** Callback invoked after cd() to update the implicit cwd search path. */
|
|
33837
|
+
onCwdChange = null;
|
|
33411
33838
|
/** Reference to the active search paths (set by executeCode). */
|
|
33412
33839
|
searchPaths = [];
|
|
33413
33840
|
// Workspace accessors: varName → { get, set } closures over script-level vars
|
|
@@ -33687,23 +34114,26 @@ var Runtime = class _Runtime {
|
|
|
33687
34114
|
if (e instanceof RuntimeError) {
|
|
33688
34115
|
return RTV.struct(
|
|
33689
34116
|
/* @__PURE__ */ new Map([
|
|
33690
|
-
["message", RTV.
|
|
33691
|
-
["identifier", RTV.
|
|
34117
|
+
["message", RTV.char(e.message)],
|
|
34118
|
+
["identifier", RTV.char(e.identifier)],
|
|
34119
|
+
["stack", buildStackField(e)]
|
|
33692
34120
|
])
|
|
33693
34121
|
);
|
|
33694
34122
|
}
|
|
33695
34123
|
if (e instanceof Error) {
|
|
33696
34124
|
return RTV.struct(
|
|
33697
34125
|
/* @__PURE__ */ new Map([
|
|
33698
|
-
["message", RTV.
|
|
33699
|
-
["identifier", RTV.
|
|
34126
|
+
["message", RTV.char(e.message)],
|
|
34127
|
+
["identifier", RTV.char("")],
|
|
34128
|
+
["stack", emptyStackField()]
|
|
33700
34129
|
])
|
|
33701
34130
|
);
|
|
33702
34131
|
}
|
|
33703
34132
|
return RTV.struct(
|
|
33704
34133
|
/* @__PURE__ */ new Map([
|
|
33705
|
-
["message", RTV.
|
|
33706
|
-
["identifier", RTV.
|
|
34134
|
+
["message", RTV.char(String(e))],
|
|
34135
|
+
["identifier", RTV.char("")],
|
|
34136
|
+
["stack", emptyStackField()]
|
|
33707
34137
|
])
|
|
33708
34138
|
);
|
|
33709
34139
|
}
|
|
@@ -34535,6 +34965,63 @@ var rstr = (s) => {
|
|
|
34535
34965
|
if (isRuntimeChar(s)) return s.value;
|
|
34536
34966
|
throw new RuntimeError(`Expected string or char, got ${kstr(s)}`);
|
|
34537
34967
|
};
|
|
34968
|
+
function emptyStackField() {
|
|
34969
|
+
return RTV.structArray(["file", "name", "line"], []);
|
|
34970
|
+
}
|
|
34971
|
+
function buildStackField(e) {
|
|
34972
|
+
const fieldNames = ["file", "name", "line"];
|
|
34973
|
+
const frames = e.callStack;
|
|
34974
|
+
if (!frames || frames.length === 0) {
|
|
34975
|
+
if (e.file || e.line !== null) {
|
|
34976
|
+
return RTV.structArray(fieldNames, [
|
|
34977
|
+
RTV.struct(
|
|
34978
|
+
/* @__PURE__ */ new Map([
|
|
34979
|
+
["file", RTV.char(e.file ?? "")],
|
|
34980
|
+
["name", RTV.char("")],
|
|
34981
|
+
["line", e.line ?? 0]
|
|
34982
|
+
])
|
|
34983
|
+
)
|
|
34984
|
+
]);
|
|
34985
|
+
}
|
|
34986
|
+
return emptyStackField();
|
|
34987
|
+
}
|
|
34988
|
+
const elements = [];
|
|
34989
|
+
const N = frames.length;
|
|
34990
|
+
for (let i = N - 1; i >= 0; i--) {
|
|
34991
|
+
let frameFile;
|
|
34992
|
+
let frameLine;
|
|
34993
|
+
if (i === N - 1) {
|
|
34994
|
+
frameFile = e.file;
|
|
34995
|
+
frameLine = e.line ?? 0;
|
|
34996
|
+
} else {
|
|
34997
|
+
const callerFrame = frames[i + 1];
|
|
34998
|
+
frameFile = callerFrame.callerFile;
|
|
34999
|
+
frameLine = callerFrame.callerLine;
|
|
35000
|
+
}
|
|
35001
|
+
elements.push(
|
|
35002
|
+
RTV.struct(
|
|
35003
|
+
/* @__PURE__ */ new Map([
|
|
35004
|
+
["file", RTV.char(frameFile ?? "")],
|
|
35005
|
+
["name", RTV.char(frames[i].name)],
|
|
35006
|
+
["line", frameLine]
|
|
35007
|
+
])
|
|
35008
|
+
)
|
|
35009
|
+
);
|
|
35010
|
+
}
|
|
35011
|
+
const outermost = frames[0];
|
|
35012
|
+
if (outermost.callerFile && outermost.callerLine > 0) {
|
|
35013
|
+
elements.push(
|
|
35014
|
+
RTV.struct(
|
|
35015
|
+
/* @__PURE__ */ new Map([
|
|
35016
|
+
["file", RTV.char(outermost.callerFile)],
|
|
35017
|
+
["name", RTV.char("")],
|
|
35018
|
+
["line", outermost.callerLine]
|
|
35019
|
+
])
|
|
35020
|
+
)
|
|
35021
|
+
);
|
|
35022
|
+
}
|
|
35023
|
+
return RTV.structArray(fieldNames, elements);
|
|
35024
|
+
}
|
|
34538
35025
|
|
|
34539
35026
|
// src/numbl-core/helpers/reduction-helpers.ts
|
|
34540
35027
|
function squeezeTrailing(shape) {
|
|
@@ -35542,6 +36029,89 @@ defineBuiltin({
|
|
|
35542
36029
|
}
|
|
35543
36030
|
});
|
|
35544
36031
|
|
|
36032
|
+
// src/numbl-core/interpreter/builtins/logical.ts
|
|
36033
|
+
var LOGICAL_KINDS = /* @__PURE__ */ new Set([
|
|
36034
|
+
"number",
|
|
36035
|
+
"boolean",
|
|
36036
|
+
"tensor",
|
|
36037
|
+
"sparse_matrix"
|
|
36038
|
+
]);
|
|
36039
|
+
function binaryLogicalMatch(argTypes) {
|
|
36040
|
+
if (argTypes.length !== 2) return null;
|
|
36041
|
+
if (!LOGICAL_KINDS.has(argTypes[0].kind)) return null;
|
|
36042
|
+
if (!LOGICAL_KINDS.has(argTypes[1].kind)) return null;
|
|
36043
|
+
if (argTypes[0].kind === "tensor" || argTypes[1].kind === "tensor") {
|
|
36044
|
+
return [{ kind: "tensor", isComplex: false, isLogical: true }];
|
|
36045
|
+
}
|
|
36046
|
+
if (argTypes[0].kind === "sparse_matrix" || argTypes[1].kind === "sparse_matrix") {
|
|
36047
|
+
return [{ kind: "tensor", isComplex: false, isLogical: true }];
|
|
36048
|
+
}
|
|
36049
|
+
return [{ kind: "boolean" }];
|
|
36050
|
+
}
|
|
36051
|
+
function isTensorLike(v) {
|
|
36052
|
+
return isRuntimeTensor(v) || isRuntimeSparseMatrix(v);
|
|
36053
|
+
}
|
|
36054
|
+
function applyBinaryLogical(args, op, scalarFn) {
|
|
36055
|
+
const a = args[0];
|
|
36056
|
+
const b = args[1];
|
|
36057
|
+
if (isTensorLike(a) || isTensorLike(b)) {
|
|
36058
|
+
return elementWiseLogicalOp(a, b, op);
|
|
36059
|
+
}
|
|
36060
|
+
return RTV.logical(scalarFn(toBool(a), toBool(b)));
|
|
36061
|
+
}
|
|
36062
|
+
var orCase = {
|
|
36063
|
+
match: binaryLogicalMatch,
|
|
36064
|
+
apply: (args) => applyBinaryLogical(
|
|
36065
|
+
args,
|
|
36066
|
+
(x, y) => x !== 0 || y !== 0 ? 1 : 0,
|
|
36067
|
+
(a, b) => a || b
|
|
36068
|
+
)
|
|
36069
|
+
};
|
|
36070
|
+
defineBuiltin({
|
|
36071
|
+
name: "or",
|
|
36072
|
+
help: {
|
|
36073
|
+
signatures: ["TF = or(A, B)"],
|
|
36074
|
+
description: "Logical OR. Functional form of A | B; returns a logical scalar or tensor."
|
|
36075
|
+
},
|
|
36076
|
+
cases: [orCase]
|
|
36077
|
+
});
|
|
36078
|
+
var andCase = {
|
|
36079
|
+
match: binaryLogicalMatch,
|
|
36080
|
+
apply: (args) => applyBinaryLogical(
|
|
36081
|
+
args,
|
|
36082
|
+
(x, y) => x !== 0 && y !== 0 ? 1 : 0,
|
|
36083
|
+
(a, b) => a && b
|
|
36084
|
+
)
|
|
36085
|
+
};
|
|
36086
|
+
defineBuiltin({
|
|
36087
|
+
name: "and",
|
|
36088
|
+
help: {
|
|
36089
|
+
signatures: ["TF = and(A, B)"],
|
|
36090
|
+
description: "Logical AND. Functional form of A & B; returns a logical scalar or tensor."
|
|
36091
|
+
},
|
|
36092
|
+
cases: [andCase]
|
|
36093
|
+
});
|
|
36094
|
+
defineBuiltin({
|
|
36095
|
+
name: "not",
|
|
36096
|
+
help: {
|
|
36097
|
+
signatures: ["TF = not(A)"],
|
|
36098
|
+
description: "Logical negation. Functional form of ~A; returns a logical scalar or tensor."
|
|
36099
|
+
},
|
|
36100
|
+
cases: [
|
|
36101
|
+
{
|
|
36102
|
+
match: (argTypes) => {
|
|
36103
|
+
if (argTypes.length !== 1) return null;
|
|
36104
|
+
if (!LOGICAL_KINDS.has(argTypes[0].kind)) return null;
|
|
36105
|
+
if (argTypes[0].kind === "tensor" || argTypes[0].kind === "sparse_matrix") {
|
|
36106
|
+
return [{ kind: "tensor", isComplex: false, isLogical: true }];
|
|
36107
|
+
}
|
|
36108
|
+
return [{ kind: "boolean" }];
|
|
36109
|
+
},
|
|
36110
|
+
apply: (args) => not(args[0])
|
|
36111
|
+
}
|
|
36112
|
+
]
|
|
36113
|
+
});
|
|
36114
|
+
|
|
35545
36115
|
// src/numbl-core/interpreter/builtins/utility.ts
|
|
35546
36116
|
function sparseToDense2(S) {
|
|
35547
36117
|
const data = new FloatXArray(S.m * S.n);
|
|
@@ -35650,7 +36220,7 @@ defineBuiltin({
|
|
|
35650
36220
|
{
|
|
35651
36221
|
match: (argTypes) => {
|
|
35652
36222
|
if (argTypes.length < 1) return null;
|
|
35653
|
-
return [
|
|
36223
|
+
return [];
|
|
35654
36224
|
},
|
|
35655
36225
|
apply: (args) => {
|
|
35656
36226
|
const v = args[0];
|
|
@@ -35671,7 +36241,7 @@ defineBuiltin({
|
|
|
35671
36241
|
const msg = args.length > 1 ? textValue(args[1]) ?? String(args[1]) : "Assertion failed";
|
|
35672
36242
|
throw new Error(msg);
|
|
35673
36243
|
}
|
|
35674
|
-
return 0;
|
|
36244
|
+
return void 0;
|
|
35675
36245
|
}
|
|
35676
36246
|
}
|
|
35677
36247
|
]
|
|
@@ -35682,7 +36252,7 @@ defineBuiltin({
|
|
|
35682
36252
|
{
|
|
35683
36253
|
match: (argTypes) => {
|
|
35684
36254
|
if (argTypes.length === 0) return null;
|
|
35685
|
-
return [
|
|
36255
|
+
return [];
|
|
35686
36256
|
},
|
|
35687
36257
|
apply: (args) => {
|
|
35688
36258
|
const first = textValue(args[0]) ?? String(args[0]);
|
|
@@ -36354,6 +36924,19 @@ defineBuiltin({
|
|
|
36354
36924
|
name: "NaN",
|
|
36355
36925
|
cases: arrayConstructorCases(nanFill, NaN)
|
|
36356
36926
|
});
|
|
36927
|
+
function infFill(shape) {
|
|
36928
|
+
const data = new FloatXArray(numel(shape));
|
|
36929
|
+
data.fill(Infinity);
|
|
36930
|
+
return makeTensor(data, void 0, shape);
|
|
36931
|
+
}
|
|
36932
|
+
defineBuiltin({
|
|
36933
|
+
name: "inf",
|
|
36934
|
+
cases: arrayConstructorCases(infFill, Infinity)
|
|
36935
|
+
});
|
|
36936
|
+
defineBuiltin({
|
|
36937
|
+
name: "Inf",
|
|
36938
|
+
cases: arrayConstructorCases(infFill, Infinity)
|
|
36939
|
+
});
|
|
36357
36940
|
defineBuiltin({
|
|
36358
36941
|
name: "eye",
|
|
36359
36942
|
cases: arrayConstructorCases(
|
|
@@ -37191,19 +37774,33 @@ function preserveTextType(t) {
|
|
|
37191
37774
|
if (t.kind === "string") return { kind: "string" };
|
|
37192
37775
|
return null;
|
|
37193
37776
|
}
|
|
37777
|
+
function applyTextFn(v, fn) {
|
|
37778
|
+
if (isRuntimeCell(v)) {
|
|
37779
|
+
const out = new Array(v.data.length);
|
|
37780
|
+
for (let i = 0; i < v.data.length; i++) {
|
|
37781
|
+
out[i] = applyTextFn(v.data[i], fn);
|
|
37782
|
+
}
|
|
37783
|
+
return RTV.cell(out, [...v.shape]);
|
|
37784
|
+
}
|
|
37785
|
+
if (isRuntimeChar(v)) return RTV.char(fn(v.value));
|
|
37786
|
+
if (isRuntimeString(v)) return RTV.string(fn(toString(v)));
|
|
37787
|
+
return v;
|
|
37788
|
+
}
|
|
37194
37789
|
function textPreserveResolve(fn) {
|
|
37195
37790
|
return (argTypes) => {
|
|
37196
37791
|
if (argTypes.length !== 1) return null;
|
|
37197
|
-
const
|
|
37792
|
+
const t = argTypes[0];
|
|
37793
|
+
if (t.kind === "cell") {
|
|
37794
|
+
return {
|
|
37795
|
+
outputTypes: [{ kind: "cell" }],
|
|
37796
|
+
apply: (args) => applyTextFn(args[0], fn)
|
|
37797
|
+
};
|
|
37798
|
+
}
|
|
37799
|
+
const out = preserveTextType(t);
|
|
37198
37800
|
if (!out) return null;
|
|
37199
37801
|
return {
|
|
37200
37802
|
outputTypes: [out],
|
|
37201
|
-
apply: (args) =>
|
|
37202
|
-
const v = args[0];
|
|
37203
|
-
const s = toString(v);
|
|
37204
|
-
const result = fn(s);
|
|
37205
|
-
return isRuntimeChar(v) ? RTV.char(result) : RTV.string(result);
|
|
37206
|
-
}
|
|
37803
|
+
apply: (args) => applyTextFn(args[0], fn)
|
|
37207
37804
|
};
|
|
37208
37805
|
};
|
|
37209
37806
|
}
|
|
@@ -37581,6 +38178,150 @@ registerIBuiltin({
|
|
|
37581
38178
|
};
|
|
37582
38179
|
}
|
|
37583
38180
|
});
|
|
38181
|
+
var RE_ALPHA = /\p{L}/u;
|
|
38182
|
+
var RE_ALPHANUM = /[\p{L}\p{N}]/u;
|
|
38183
|
+
var RE_CNTRL = /\p{Cc}/u;
|
|
38184
|
+
var RE_GRAPHIC = /[\p{L}\p{N}\p{P}\p{S}\p{M}]/u;
|
|
38185
|
+
var RE_LOWER = /\p{Ll}/u;
|
|
38186
|
+
var RE_PUNCT = /\p{P}/u;
|
|
38187
|
+
var RE_UPPER = /\p{Lu}/u;
|
|
38188
|
+
var RE_WSPACE = /\s/u;
|
|
38189
|
+
function isstrpropPredicate(category) {
|
|
38190
|
+
switch (category) {
|
|
38191
|
+
case "alpha":
|
|
38192
|
+
return (cp) => RE_ALPHA.test(String.fromCodePoint(cp));
|
|
38193
|
+
case "alphanum":
|
|
38194
|
+
return (cp) => RE_ALPHANUM.test(String.fromCodePoint(cp));
|
|
38195
|
+
case "cntrl":
|
|
38196
|
+
return (cp) => RE_CNTRL.test(String.fromCodePoint(cp));
|
|
38197
|
+
case "digit":
|
|
38198
|
+
return (cp) => cp >= 48 && cp <= 57;
|
|
38199
|
+
case "graphic":
|
|
38200
|
+
return (cp) => RE_GRAPHIC.test(String.fromCodePoint(cp));
|
|
38201
|
+
case "lower":
|
|
38202
|
+
return (cp) => RE_LOWER.test(String.fromCodePoint(cp));
|
|
38203
|
+
case "print":
|
|
38204
|
+
return (cp) => cp === 32 || RE_GRAPHIC.test(String.fromCodePoint(cp));
|
|
38205
|
+
case "punct":
|
|
38206
|
+
return (cp) => RE_PUNCT.test(String.fromCodePoint(cp));
|
|
38207
|
+
case "wspace":
|
|
38208
|
+
return (cp) => RE_WSPACE.test(String.fromCodePoint(cp));
|
|
38209
|
+
case "upper":
|
|
38210
|
+
return (cp) => RE_UPPER.test(String.fromCodePoint(cp));
|
|
38211
|
+
case "xdigit":
|
|
38212
|
+
return (cp) => cp >= 48 && cp <= 57 || cp >= 65 && cp <= 70 || cp >= 97 && cp <= 102;
|
|
38213
|
+
default:
|
|
38214
|
+
return null;
|
|
38215
|
+
}
|
|
38216
|
+
}
|
|
38217
|
+
function stringCodePoints(s) {
|
|
38218
|
+
const out = [];
|
|
38219
|
+
for (const ch of s) out.push(ch.codePointAt(0));
|
|
38220
|
+
return out;
|
|
38221
|
+
}
|
|
38222
|
+
function logicalRowFromString(s, pred, shape) {
|
|
38223
|
+
const cps = stringCodePoints(s);
|
|
38224
|
+
const data = new FloatXArray(cps.length);
|
|
38225
|
+
for (let i = 0; i < cps.length; i++) data[i] = pred(cps[i]) ? 1 : 0;
|
|
38226
|
+
return {
|
|
38227
|
+
kind: "tensor",
|
|
38228
|
+
data,
|
|
38229
|
+
shape: shape ?? [1, cps.length],
|
|
38230
|
+
_isLogical: true,
|
|
38231
|
+
_rc: 1
|
|
38232
|
+
};
|
|
38233
|
+
}
|
|
38234
|
+
function logicalFromNumericTensor(data, shape, pred) {
|
|
38235
|
+
const out = new FloatXArray(data.length);
|
|
38236
|
+
for (let i = 0; i < data.length; i++) {
|
|
38237
|
+
out[i] = pred(Math.round(data[i])) ? 1 : 0;
|
|
38238
|
+
}
|
|
38239
|
+
return {
|
|
38240
|
+
kind: "tensor",
|
|
38241
|
+
data: out,
|
|
38242
|
+
shape: [...shape],
|
|
38243
|
+
_isLogical: true,
|
|
38244
|
+
_rc: 1
|
|
38245
|
+
};
|
|
38246
|
+
}
|
|
38247
|
+
function isstrpropApply(args) {
|
|
38248
|
+
const v = args[0];
|
|
38249
|
+
const category = toString(args[1]);
|
|
38250
|
+
const pred = isstrpropPredicate(category);
|
|
38251
|
+
if (!pred) {
|
|
38252
|
+
throw new RuntimeError(`isstrprop: unknown category '${category}'`);
|
|
38253
|
+
}
|
|
38254
|
+
let forceCell = false;
|
|
38255
|
+
if (args.length >= 3) {
|
|
38256
|
+
const flagName = toString(args[2]).toLowerCase();
|
|
38257
|
+
if (flagName !== "forcecelloutput") {
|
|
38258
|
+
throw new RuntimeError(`isstrprop: unknown name '${toString(args[2])}'`);
|
|
38259
|
+
}
|
|
38260
|
+
if (args.length < 4) {
|
|
38261
|
+
throw new RuntimeError("isstrprop: 'ForceCellOutput' requires a value");
|
|
38262
|
+
}
|
|
38263
|
+
forceCell = toNumber(args[3]) !== 0;
|
|
38264
|
+
}
|
|
38265
|
+
if (isRuntimeCell(v)) {
|
|
38266
|
+
const out = new Array(v.data.length);
|
|
38267
|
+
for (let i = 0; i < v.data.length; i++) {
|
|
38268
|
+
const elem = v.data[i];
|
|
38269
|
+
const s = isText(elem) ? toString(elem) : "";
|
|
38270
|
+
out[i] = logicalRowFromString(s, pred);
|
|
38271
|
+
}
|
|
38272
|
+
return RTV.cell(out, [...v.shape]);
|
|
38273
|
+
}
|
|
38274
|
+
let result;
|
|
38275
|
+
if (isRuntimeString(v)) {
|
|
38276
|
+
result = logicalRowFromString(toString(v), pred);
|
|
38277
|
+
} else if (isRuntimeChar(v)) {
|
|
38278
|
+
const c = v;
|
|
38279
|
+
result = logicalRowFromString(
|
|
38280
|
+
c.value,
|
|
38281
|
+
pred,
|
|
38282
|
+
c.shape ? [...c.shape] : void 0
|
|
38283
|
+
);
|
|
38284
|
+
} else if (isRuntimeTensor(v)) {
|
|
38285
|
+
result = logicalFromNumericTensor(v.data, v.shape, pred);
|
|
38286
|
+
} else if (isRuntimeNumber(v) || isRuntimeLogical(v)) {
|
|
38287
|
+
const cp = Math.round(toNumber(v));
|
|
38288
|
+
const data = new FloatXArray(1);
|
|
38289
|
+
data[0] = pred(cp) ? 1 : 0;
|
|
38290
|
+
result = { kind: "tensor", data, shape: [1, 1], _isLogical: true, _rc: 1 };
|
|
38291
|
+
} else {
|
|
38292
|
+
throw new RuntimeError("isstrprop: unsupported input type");
|
|
38293
|
+
}
|
|
38294
|
+
if (forceCell) return RTV.cell([result], [1, 1]);
|
|
38295
|
+
return result;
|
|
38296
|
+
}
|
|
38297
|
+
registerIBuiltin({
|
|
38298
|
+
name: "isstrprop",
|
|
38299
|
+
help: {
|
|
38300
|
+
signatures: [
|
|
38301
|
+
"TF = isstrprop(str, category)",
|
|
38302
|
+
"TF = isstrprop(str, category, 'ForceCellOutput', tf)"
|
|
38303
|
+
],
|
|
38304
|
+
description: "Test which characters in str belong to a category (alpha, alphanum, cntrl, digit, graphic, lower, print, punct, upper, wspace, xdigit). Returns a logical array, or a cell of logical vectors when str is a cell array or ForceCellOutput is true. Numeric input is treated as Unicode code points."
|
|
38305
|
+
},
|
|
38306
|
+
resolve: (argTypes) => {
|
|
38307
|
+
if (argTypes.length < 2 || argTypes.length > 4) return null;
|
|
38308
|
+
if (!isTextType(argTypes[1])) return null;
|
|
38309
|
+
if (argTypes.length >= 3 && !isTextType(argTypes[2])) return null;
|
|
38310
|
+
if (argTypes.length === 4) {
|
|
38311
|
+
const k = argTypes[3].kind;
|
|
38312
|
+
if (k !== "number" && k !== "boolean") return null;
|
|
38313
|
+
}
|
|
38314
|
+
const t0 = argTypes[0];
|
|
38315
|
+
if (t0.kind !== "char" && t0.kind !== "string" && t0.kind !== "number" && t0.kind !== "boolean" && t0.kind !== "tensor" && t0.kind !== "cell") {
|
|
38316
|
+
return null;
|
|
38317
|
+
}
|
|
38318
|
+
const isCell = t0.kind === "cell";
|
|
38319
|
+
return {
|
|
38320
|
+
outputTypes: isCell ? [{ kind: "cell" }] : [{ kind: "tensor", isComplex: false, isLogical: true }],
|
|
38321
|
+
apply: (args) => isstrpropApply(args)
|
|
38322
|
+
};
|
|
38323
|
+
}
|
|
38324
|
+
});
|
|
37584
38325
|
registerIBuiltin({
|
|
37585
38326
|
name: "contains",
|
|
37586
38327
|
resolve: (argTypes) => {
|
|
@@ -40966,11 +41707,15 @@ defineBuiltin({
|
|
|
40966
41707
|
apply: (args) => {
|
|
40967
41708
|
if (args.length !== 2)
|
|
40968
41709
|
throw new RuntimeError("kron requires 2 arguments");
|
|
40969
|
-
const
|
|
40970
|
-
|
|
40971
|
-
|
|
40972
|
-
|
|
41710
|
+
const coerce = (v) => {
|
|
41711
|
+
if (isRuntimeNumber(v))
|
|
41712
|
+
return RTV.tensor(new FloatXArray([v]), [1, 1]);
|
|
41713
|
+
if (isRuntimeSparseMatrix(v)) return sparseToDense(v);
|
|
41714
|
+
if (isRuntimeTensor(v)) return v;
|
|
40973
41715
|
throw new RuntimeError("kron: arguments must be numeric");
|
|
41716
|
+
};
|
|
41717
|
+
const A = coerce(args[0]);
|
|
41718
|
+
const B = coerce(args[1]);
|
|
40974
41719
|
const [m, n] = tensorSize2D(A);
|
|
40975
41720
|
const [p2, q] = tensorSize2D(B);
|
|
40976
41721
|
const rows = m * p2, cols = n * q;
|
|
@@ -43288,6 +44033,65 @@ defineBuiltin({
|
|
|
43288
44033
|
}
|
|
43289
44034
|
]
|
|
43290
44035
|
});
|
|
44036
|
+
defineBuiltin({
|
|
44037
|
+
name: "bitget",
|
|
44038
|
+
cases: [
|
|
44039
|
+
{
|
|
44040
|
+
match: (argTypes) => {
|
|
44041
|
+
if (argTypes.length !== 2) return null;
|
|
44042
|
+
return [{ kind: "unknown" }];
|
|
44043
|
+
},
|
|
44044
|
+
// bitget(A, bit) returns bit number `bit` (1-based, 1 = LSB) of each
|
|
44045
|
+
// element of A. MATLAB supports vector `bit` with broadcasting; we
|
|
44046
|
+
// match the scalar-or-same-shape rules used by the other bitwise ops.
|
|
44047
|
+
apply: (args) => bitwiseOp(
|
|
44048
|
+
args[0],
|
|
44049
|
+
args[1],
|
|
44050
|
+
(a, bit) => {
|
|
44051
|
+
const b = Math.round(bit);
|
|
44052
|
+
if (b < 1) return 0;
|
|
44053
|
+
if (b <= 31) return a >>> b - 1 & 1;
|
|
44054
|
+
const bi = BigInt(a);
|
|
44055
|
+
return Number(bi >> BigInt(b - 1) & 1n);
|
|
44056
|
+
},
|
|
44057
|
+
"bitget"
|
|
44058
|
+
)
|
|
44059
|
+
}
|
|
44060
|
+
]
|
|
44061
|
+
});
|
|
44062
|
+
defineBuiltin({
|
|
44063
|
+
name: "bitset",
|
|
44064
|
+
cases: [
|
|
44065
|
+
{
|
|
44066
|
+
match: (argTypes) => {
|
|
44067
|
+
if (argTypes.length < 2 || argTypes.length > 3) return null;
|
|
44068
|
+
return [{ kind: "unknown" }];
|
|
44069
|
+
},
|
|
44070
|
+
// bitset(A, bit) → set bit to 1
|
|
44071
|
+
// bitset(A, bit, v) → set bit to v (0 or 1)
|
|
44072
|
+
apply: (args) => {
|
|
44073
|
+
const v = args.length >= 3 ? Math.round(toNumber(args[2])) : 1;
|
|
44074
|
+
return bitwiseOp(
|
|
44075
|
+
args[0],
|
|
44076
|
+
args[1],
|
|
44077
|
+
(a, bit) => {
|
|
44078
|
+
const b = Math.round(bit);
|
|
44079
|
+
if (b < 1) return a;
|
|
44080
|
+
if (b <= 31) {
|
|
44081
|
+
const mask2 = 1 << b - 1;
|
|
44082
|
+
return v ? a | mask2 : a & ~mask2;
|
|
44083
|
+
}
|
|
44084
|
+
const bi = BigInt(a);
|
|
44085
|
+
const mask = 1n << BigInt(b - 1);
|
|
44086
|
+
const out = v ? bi | mask : bi & ~mask;
|
|
44087
|
+
return Number(out);
|
|
44088
|
+
},
|
|
44089
|
+
"bitset"
|
|
44090
|
+
);
|
|
44091
|
+
}
|
|
44092
|
+
}
|
|
44093
|
+
]
|
|
44094
|
+
});
|
|
43291
44095
|
function coordTransform(name, nArgs, nOut, fn) {
|
|
43292
44096
|
defineBuiltin({
|
|
43293
44097
|
name,
|
|
@@ -44417,6 +45221,131 @@ defineBuiltin({
|
|
|
44417
45221
|
}
|
|
44418
45222
|
]
|
|
44419
45223
|
});
|
|
45224
|
+
var INT_RANGES = [
|
|
45225
|
+
{ name: "int8", min: -128, max: 127 },
|
|
45226
|
+
{ name: "int16", min: -32768, max: 32767 },
|
|
45227
|
+
{ name: "int32", min: -2147483648, max: 2147483647 },
|
|
45228
|
+
// int64/uint64 can't represent their full native range as doubles;
|
|
45229
|
+
// clamp at Number.MAX_SAFE_INTEGER to avoid silent precision loss.
|
|
45230
|
+
{
|
|
45231
|
+
name: "int64",
|
|
45232
|
+
min: -Number.MAX_SAFE_INTEGER,
|
|
45233
|
+
max: Number.MAX_SAFE_INTEGER
|
|
45234
|
+
},
|
|
45235
|
+
{ name: "uint8", min: 0, max: 255 },
|
|
45236
|
+
{ name: "uint16", min: 0, max: 65535 },
|
|
45237
|
+
{ name: "uint32", min: 0, max: 4294967295 },
|
|
45238
|
+
{ name: "uint64", min: 0, max: Number.MAX_SAFE_INTEGER }
|
|
45239
|
+
];
|
|
45240
|
+
function saturateRoundToward(x, min, max) {
|
|
45241
|
+
if (isNaN(x)) return 0;
|
|
45242
|
+
const r = x >= 0 ? Math.floor(x + 0.5) : -Math.floor(-x + 0.5);
|
|
45243
|
+
if (r < min) return min;
|
|
45244
|
+
if (r > max) return max;
|
|
45245
|
+
return r;
|
|
45246
|
+
}
|
|
45247
|
+
for (const { name, min, max } of INT_RANGES) {
|
|
45248
|
+
defineBuiltin({
|
|
45249
|
+
name,
|
|
45250
|
+
cases: [
|
|
45251
|
+
{
|
|
45252
|
+
match: (argTypes) => {
|
|
45253
|
+
if (argTypes.length !== 1) return null;
|
|
45254
|
+
const a = argTypes[0];
|
|
45255
|
+
if (a.kind === "number" || a.kind === "boolean" || a.kind === "char" || a.kind === "complex_or_number")
|
|
45256
|
+
return [{ kind: "number" }];
|
|
45257
|
+
if (a.kind === "tensor")
|
|
45258
|
+
return [
|
|
45259
|
+
{
|
|
45260
|
+
kind: "tensor",
|
|
45261
|
+
isComplex: false,
|
|
45262
|
+
shape: a.shape,
|
|
45263
|
+
ndim: a.ndim
|
|
45264
|
+
}
|
|
45265
|
+
];
|
|
45266
|
+
return null;
|
|
45267
|
+
},
|
|
45268
|
+
apply: (args) => {
|
|
45269
|
+
const v = args[0];
|
|
45270
|
+
if (isRuntimeNumber(v))
|
|
45271
|
+
return RTV.num(saturateRoundToward(v, min, max));
|
|
45272
|
+
if (isRuntimeLogical(v)) return RTV.num(v ? 1 : 0);
|
|
45273
|
+
if (isRuntimeComplexNumber(v))
|
|
45274
|
+
return RTV.num(saturateRoundToward(v.re, min, max));
|
|
45275
|
+
if (isRuntimeChar(v)) {
|
|
45276
|
+
if (v.value.length === 0)
|
|
45277
|
+
return RTV.tensor(new FloatXArray(0), [0, 0]);
|
|
45278
|
+
if (v.value.length === 1)
|
|
45279
|
+
return RTV.num(
|
|
45280
|
+
saturateRoundToward(v.value.charCodeAt(0), min, max)
|
|
45281
|
+
);
|
|
45282
|
+
const out = new FloatXArray(v.value.length);
|
|
45283
|
+
for (let i = 0; i < v.value.length; i++) {
|
|
45284
|
+
out[i] = saturateRoundToward(v.value.charCodeAt(i), min, max);
|
|
45285
|
+
}
|
|
45286
|
+
return RTV.row(Array.from(out));
|
|
45287
|
+
}
|
|
45288
|
+
if (isRuntimeTensor(v)) {
|
|
45289
|
+
const data = new FloatXArray(v.data.length);
|
|
45290
|
+
for (let i = 0; i < v.data.length; i++) {
|
|
45291
|
+
data[i] = saturateRoundToward(v.data[i], min, max);
|
|
45292
|
+
}
|
|
45293
|
+
return RTV.tensor(data, [...v.shape]);
|
|
45294
|
+
}
|
|
45295
|
+
return RTV.num(saturateRoundToward(toNumber(v), min, max));
|
|
45296
|
+
}
|
|
45297
|
+
}
|
|
45298
|
+
]
|
|
45299
|
+
});
|
|
45300
|
+
}
|
|
45301
|
+
defineBuiltin({
|
|
45302
|
+
name: "idivide",
|
|
45303
|
+
cases: [
|
|
45304
|
+
{
|
|
45305
|
+
match: (argTypes) => {
|
|
45306
|
+
if (argTypes.length < 2 || argTypes.length > 3) return null;
|
|
45307
|
+
return [{ kind: "unknown" }];
|
|
45308
|
+
},
|
|
45309
|
+
apply: (args) => {
|
|
45310
|
+
const divFix = (a2, b2) => {
|
|
45311
|
+
if (b2 === 0) {
|
|
45312
|
+
return 0;
|
|
45313
|
+
}
|
|
45314
|
+
const q = a2 / b2;
|
|
45315
|
+
return q >= 0 ? Math.floor(q) : -Math.floor(-q);
|
|
45316
|
+
};
|
|
45317
|
+
const a = args[0];
|
|
45318
|
+
const b = args[1];
|
|
45319
|
+
if (isRuntimeNumber(a) && isRuntimeNumber(b)) {
|
|
45320
|
+
return RTV.num(divFix(a, b));
|
|
45321
|
+
}
|
|
45322
|
+
if (isRuntimeTensor(a) && isRuntimeNumber(b)) {
|
|
45323
|
+
const bv = b;
|
|
45324
|
+
const data = new FloatXArray(a.data.length);
|
|
45325
|
+
for (let i = 0; i < a.data.length; i++)
|
|
45326
|
+
data[i] = divFix(a.data[i], bv);
|
|
45327
|
+
return RTV.tensor(data, [...a.shape]);
|
|
45328
|
+
}
|
|
45329
|
+
if (isRuntimeNumber(a) && isRuntimeTensor(b)) {
|
|
45330
|
+
const av = a;
|
|
45331
|
+
const data = new FloatXArray(b.data.length);
|
|
45332
|
+
for (let i = 0; i < b.data.length; i++)
|
|
45333
|
+
data[i] = divFix(av, b.data[i]);
|
|
45334
|
+
return RTV.tensor(data, [...b.shape]);
|
|
45335
|
+
}
|
|
45336
|
+
if (isRuntimeTensor(a) && isRuntimeTensor(b)) {
|
|
45337
|
+
if (a.data.length !== b.data.length)
|
|
45338
|
+
throw new RuntimeError("idivide: arrays must be the same size");
|
|
45339
|
+
const data = new FloatXArray(a.data.length);
|
|
45340
|
+
for (let i = 0; i < a.data.length; i++)
|
|
45341
|
+
data[i] = divFix(a.data[i], b.data[i]);
|
|
45342
|
+
return RTV.tensor(data, [...a.shape]);
|
|
45343
|
+
}
|
|
45344
|
+
throw new RuntimeError("idivide: arguments must be numeric");
|
|
45345
|
+
}
|
|
45346
|
+
}
|
|
45347
|
+
]
|
|
45348
|
+
});
|
|
44420
45349
|
defineBuiltin({
|
|
44421
45350
|
name: "logical",
|
|
44422
45351
|
cases: [
|
|
@@ -47654,6 +48583,15 @@ var H = {
|
|
|
47654
48583
|
signatures: ["TF = isequal(A, B, ...)"],
|
|
47655
48584
|
description: "True if all inputs are equal (NaN ~= NaN)."
|
|
47656
48585
|
},
|
|
48586
|
+
// ── Dynamic evaluation ────────────────────────────────────────────────
|
|
48587
|
+
evalin: {
|
|
48588
|
+
signatures: ["V = evalin(WS, EXPR)", "V = evalin(WS, EXPR, DEFAULT)"],
|
|
48589
|
+
description: "Evaluate EXPR in workspace WS ('caller' or 'base'/'workspace').\n\nnumbl-specific note: variables read by evalin must be declared in the\nfunction that owns them with a `% external-access:` comment, e.g.\n function out = f()\n % external-access: x y\n x = 1; y = 2;\n ...\n end\nVariables not listed in `% external-access` are stored in a separate\ndynamic map and are only reachable through evalin/assignin. The\ndirective is a comment, so MATLAB ignores it."
|
|
48590
|
+
},
|
|
48591
|
+
assignin: {
|
|
48592
|
+
signatures: ["assignin(WS, NAME, VALUE)"],
|
|
48593
|
+
description: "Assign VALUE to variable NAME in workspace WS ('caller' or 'base'/'workspace').\n\nnumbl-specific note: variables written by assignin must be declared in\nthe function that owns them with a `% external-access:` comment, e.g.\n function out = f()\n % external-access: x y\n x = 1; y = 2;\n ...\n end\nVariables not listed in `% external-access` are stored in a separate\ndynamic map and are only reachable through evalin/assignin. The\ndirective is a comment, so MATLAB ignores it."
|
|
48594
|
+
},
|
|
47657
48595
|
// ── Misc ──────────────────────────────────────────────────────────────
|
|
47658
48596
|
disp: {
|
|
47659
48597
|
signatures: ["disp(X)"],
|
|
@@ -48551,7 +49489,7 @@ function getSourceLine(getSource, file, line) {
|
|
|
48551
49489
|
}
|
|
48552
49490
|
|
|
48553
49491
|
// src/numbl-core/version.ts
|
|
48554
|
-
var NUMBL_VERSION = "0.1.
|
|
49492
|
+
var NUMBL_VERSION = "0.1.5";
|
|
48555
49493
|
|
|
48556
49494
|
// src/cli-repl.ts
|
|
48557
49495
|
import { createInterface } from "readline";
|
|
@@ -50958,6 +51896,9 @@ function execStmt(stmt) {
|
|
|
50958
51896
|
case "ExprStmt": {
|
|
50959
51897
|
const val = this.evalExprNargout(stmt.expr, 0);
|
|
50960
51898
|
const singleVal = Array.isArray(val) ? val[0] : val;
|
|
51899
|
+
if (singleVal === void 0) {
|
|
51900
|
+
return null;
|
|
51901
|
+
}
|
|
50961
51902
|
const rv = ensureRuntimeValue(singleVal);
|
|
50962
51903
|
this.ans = rv;
|
|
50963
51904
|
this.env.set("ans", rv);
|
|
@@ -50981,19 +51922,25 @@ function execStmt(stmt) {
|
|
|
50981
51922
|
if (stmt.lvalues.length === 1 && stmt.lvalues[0].type === "IndexCell") {
|
|
50982
51923
|
const lv = stmt.lvalues[0];
|
|
50983
51924
|
const cellBase = lv.base.type === "Ident" ? this.env.get(lv.base.name) ?? RTV.cell([], [0, 0]) : this.evalExpr(lv.base);
|
|
50984
|
-
const indices =
|
|
50985
|
-
const idxVal = ensureRuntimeValue(indices[0]);
|
|
51925
|
+
const indices = this.evalIndicesWithEnd(cellBase, lv.indices);
|
|
50986
51926
|
let expandedCount = 1;
|
|
50987
|
-
|
|
50988
|
-
|
|
50989
|
-
|
|
50990
|
-
expandedCount =
|
|
51927
|
+
const idx0 = indices[0];
|
|
51928
|
+
if (idx0 === COLON_SENTINEL) {
|
|
51929
|
+
const baseRv = ensureRuntimeValue(cellBase);
|
|
51930
|
+
expandedCount = isRuntimeCell(baseRv) ? baseRv.data.length : 0;
|
|
51931
|
+
} else {
|
|
51932
|
+
const idxVal = ensureRuntimeValue(idx0);
|
|
51933
|
+
if (isRuntimeTensor(idxVal)) {
|
|
51934
|
+
expandedCount = idxVal.data.length;
|
|
51935
|
+
} else if (typeof idxVal === "number") {
|
|
51936
|
+
expandedCount = 1;
|
|
51937
|
+
}
|
|
50991
51938
|
}
|
|
50992
51939
|
const val2 = this.evalExprNargout(stmt.expr, expandedCount);
|
|
50993
51940
|
const values2 = Array.isArray(val2) ? val2 : [val2];
|
|
50994
51941
|
const result = this.rt.multiOutputCellAssign(
|
|
50995
51942
|
cellBase,
|
|
50996
|
-
|
|
51943
|
+
idx0,
|
|
50997
51944
|
values2.map((v) => ensureRuntimeValue(v))
|
|
50998
51945
|
);
|
|
50999
51946
|
if (lv.base.type === "Ident") {
|
|
@@ -51555,7 +52502,11 @@ function evalAnonFunc(expr) {
|
|
|
51555
52502
|
capturedMethodName,
|
|
51556
52503
|
() => {
|
|
51557
52504
|
try {
|
|
51558
|
-
|
|
52505
|
+
const result = this.evalExprNargout(bodyExpr, narg);
|
|
52506
|
+
if (narg > 1 && !(Array.isArray(result) && result.length >= narg)) {
|
|
52507
|
+
throw new RuntimeError("Too many output arguments.");
|
|
52508
|
+
}
|
|
52509
|
+
return result;
|
|
51559
52510
|
} finally {
|
|
51560
52511
|
this.env = savedEnv;
|
|
51561
52512
|
}
|
|
@@ -52035,6 +52986,17 @@ register("exist", (ctx, args) => {
|
|
|
52035
52986
|
}
|
|
52036
52987
|
return FALL_THROUGH;
|
|
52037
52988
|
});
|
|
52989
|
+
register("which", (ctx, args) => {
|
|
52990
|
+
if (args.length < 1) return FALL_THROUGH;
|
|
52991
|
+
const nameArg = toString(ensureRuntimeValue(args[0]));
|
|
52992
|
+
if (ctx.env.has(nameArg)) return RTV.char("variable");
|
|
52993
|
+
const filePath = ctx.lookupWorkspaceFile(nameArg);
|
|
52994
|
+
if (filePath) return RTV.char(filePath);
|
|
52995
|
+
if (ctx.rt.builtins[nameArg] || getIBuiltin(nameArg)) {
|
|
52996
|
+
return RTV.char("built-in");
|
|
52997
|
+
}
|
|
52998
|
+
return RTV.char("");
|
|
52999
|
+
});
|
|
52038
53000
|
register("isfolder", (ctx, args) => {
|
|
52039
53001
|
if (args.length < 1) return FALL_THROUGH;
|
|
52040
53002
|
const fio = ctx.rt.fileIO;
|
|
@@ -52137,6 +53099,9 @@ register("run", (ctx, args) => {
|
|
|
52137
53099
|
} catch {
|
|
52138
53100
|
throw new RuntimeError(`Cannot change directory to '${scriptDir}'`);
|
|
52139
53101
|
}
|
|
53102
|
+
if (ctx.rt.onCwdChange) {
|
|
53103
|
+
ctx.rt.onCwdChange(sys.cwd());
|
|
53104
|
+
}
|
|
52140
53105
|
}
|
|
52141
53106
|
const cwdAfterCd = sys?.cwd() ?? "/";
|
|
52142
53107
|
try {
|
|
@@ -52148,6 +53113,9 @@ register("run", (ctx, args) => {
|
|
|
52148
53113
|
sys.chdir(oldCwd);
|
|
52149
53114
|
} catch {
|
|
52150
53115
|
}
|
|
53116
|
+
if (ctx.rt.onCwdChange) {
|
|
53117
|
+
ctx.rt.onCwdChange(sys.cwd());
|
|
53118
|
+
}
|
|
52151
53119
|
}
|
|
52152
53120
|
}
|
|
52153
53121
|
return void 0;
|
|
@@ -52167,7 +53135,14 @@ function callFunction(name, args, nargout) {
|
|
|
52167
53135
|
workspaceEnv: this.workspaceEnv,
|
|
52168
53136
|
evalInLocalScope: (codeArg, fileName) => this.evalInLocalScope(codeArg, fileName),
|
|
52169
53137
|
callFunction: (n, a, no) => this.callFunction(n, a, no),
|
|
52170
|
-
rt: this.rt
|
|
53138
|
+
rt: this.rt,
|
|
53139
|
+
lookupWorkspaceFile: (n) => {
|
|
53140
|
+
const entry = this.ctx.registry.filesByFuncName.get(n);
|
|
53141
|
+
if (entry) return entry.fileName;
|
|
53142
|
+
const classInfo = this.ctx.getClassInfo(n);
|
|
53143
|
+
if (classInfo) return classInfo.fileName;
|
|
53144
|
+
return void 0;
|
|
53145
|
+
}
|
|
52171
53146
|
};
|
|
52172
53147
|
const result = specialHandler(ctx, args, nargout);
|
|
52173
53148
|
if (result !== FALL_THROUGH) return result;
|
|
@@ -52201,13 +53176,18 @@ function interpretTarget(target, args, nargout) {
|
|
|
52201
53176
|
const argTypes = margs.map(inferJitType);
|
|
52202
53177
|
const resolution = ib.resolve(argTypes, nargout);
|
|
52203
53178
|
if (resolution) {
|
|
53179
|
+
const isVoid = resolution.outputTypes.length === 0;
|
|
53180
|
+
if (isVoid && nargout > 0) {
|
|
53181
|
+
throw new RuntimeError("Too many output arguments.");
|
|
53182
|
+
}
|
|
52204
53183
|
if (this.rt.profilingEnabled) {
|
|
52205
53184
|
this.rt.profileEnter("builtin:interp:" + target.name);
|
|
52206
|
-
const
|
|
53185
|
+
const result2 = resolution.apply(margs, nargout);
|
|
52207
53186
|
this.rt.profileLeave();
|
|
52208
|
-
return
|
|
53187
|
+
return isVoid ? void 0 : result2;
|
|
52209
53188
|
}
|
|
52210
|
-
|
|
53189
|
+
const result = resolution.apply(margs, nargout);
|
|
53190
|
+
return isVoid ? void 0 : result;
|
|
52211
53191
|
}
|
|
52212
53192
|
}
|
|
52213
53193
|
const builtin = this.rt.builtins[target.name];
|
|
@@ -52299,7 +53279,19 @@ function interpretLocalFunction(target, args, nargout) {
|
|
|
52299
53279
|
function interpretWorkspaceFunction(target, args, nargout) {
|
|
52300
53280
|
const dotIdx = target.name.lastIndexOf(".");
|
|
52301
53281
|
const primaryName = dotIdx >= 0 ? target.name.slice(dotIdx + 1) : target.name;
|
|
52302
|
-
|
|
53282
|
+
let fn = this.findFunctionInWorkspaceFile(target.name, primaryName);
|
|
53283
|
+
if (!fn) {
|
|
53284
|
+
const entry = this.ctx.registry.filesByFuncName.get(target.name);
|
|
53285
|
+
if (entry) {
|
|
53286
|
+
const ast = this.ctx.getCachedAST(entry.fileName);
|
|
53287
|
+
for (const stmt of ast.body) {
|
|
53288
|
+
if (stmt.type === "Function") {
|
|
53289
|
+
fn = funcDefFromStmt(stmt);
|
|
53290
|
+
break;
|
|
53291
|
+
}
|
|
53292
|
+
}
|
|
53293
|
+
}
|
|
53294
|
+
}
|
|
52303
53295
|
if (!fn) {
|
|
52304
53296
|
const entry = this.ctx.registry.filesByFuncName.get(target.name);
|
|
52305
53297
|
if (entry) {
|
|
@@ -52443,6 +53435,11 @@ function interpretConstructor(classInfo, args, nargout) {
|
|
|
52443
53435
|
return args[0];
|
|
52444
53436
|
}
|
|
52445
53437
|
function callUserFunction(fn, args, nargout, narginOverride) {
|
|
53438
|
+
const hasVarargoutDecl = fn.outputs.length > 0 && fn.outputs[fn.outputs.length - 1] === "varargout";
|
|
53439
|
+
const declaredRegularOutputs = hasVarargoutDecl ? fn.outputs.length - 1 : fn.outputs.length;
|
|
53440
|
+
if (!hasVarargoutDecl && nargout > declaredRegularOutputs) {
|
|
53441
|
+
throw new RuntimeError("Too many output arguments.");
|
|
53442
|
+
}
|
|
52446
53443
|
if (this.optimization >= 1 && narginOverride === void 0) {
|
|
52447
53444
|
const jitResult = tryJitCall(this, fn, args, nargout);
|
|
52448
53445
|
if (jitResult !== JIT_SKIP) return jitResult;
|
|
@@ -52492,7 +53489,7 @@ function callUserFunction(fn, args, nargout, narginOverride) {
|
|
|
52492
53489
|
}
|
|
52493
53490
|
}
|
|
52494
53491
|
}
|
|
52495
|
-
const hasVarargout =
|
|
53492
|
+
const hasVarargout = hasVarargoutDecl;
|
|
52496
53493
|
const regularOutputs = hasVarargout ? fn.outputs.slice(0, -1) : fn.outputs;
|
|
52497
53494
|
const collectCount = nargout === 0 && regularOutputs.length > 0 ? 1 : Math.min(regularOutputs.length, nargout);
|
|
52498
53495
|
const outputs = [];
|
|
@@ -54097,6 +55094,31 @@ function executeCode(source, options = {}, workspaceFiles, mainFileName = "scrip
|
|
|
54097
55094
|
}
|
|
54098
55095
|
}
|
|
54099
55096
|
}
|
|
55097
|
+
let implicitCwdPath = null;
|
|
55098
|
+
if (options.implicitCwdPath !== null && options.system && options.fileIO?.scanDirectory) {
|
|
55099
|
+
try {
|
|
55100
|
+
const cwd = options.implicitCwdPath ?? options.system.cwd();
|
|
55101
|
+
const absCwd = options.fileIO.resolvePath?.(cwd) ?? cwd;
|
|
55102
|
+
const explicitPaths = searchPaths ?? [];
|
|
55103
|
+
if (!explicitPaths.includes(absCwd)) {
|
|
55104
|
+
implicitCwdPath = absCwd;
|
|
55105
|
+
const prefix = absCwd.endsWith("/") ? absCwd : absCwd + "/";
|
|
55106
|
+
const alreadyHave = mWorkspaceFiles.some(
|
|
55107
|
+
(f) => f.name === absCwd || f.name.startsWith(prefix)
|
|
55108
|
+
);
|
|
55109
|
+
if (!alreadyHave) {
|
|
55110
|
+
const cwdFiles = options.fileIO.scanDirectory(absCwd);
|
|
55111
|
+
for (const f of cwdFiles) {
|
|
55112
|
+
if (f.name.endsWith(".m")) {
|
|
55113
|
+
mWorkspaceFiles.push(f);
|
|
55114
|
+
}
|
|
55115
|
+
}
|
|
55116
|
+
}
|
|
55117
|
+
}
|
|
55118
|
+
} catch {
|
|
55119
|
+
implicitCwdPath = null;
|
|
55120
|
+
}
|
|
55121
|
+
}
|
|
54100
55122
|
const jsUserFunctions = loadJsUserFunctions(
|
|
54101
55123
|
jsWorkspaceFiles,
|
|
54102
55124
|
wasmWorkspaceFiles,
|
|
@@ -54114,6 +55136,9 @@ function executeCode(source, options = {}, workspaceFiles, mainFileName = "scrip
|
|
|
54114
55136
|
stdlibShimNames.add(shimName);
|
|
54115
55137
|
}
|
|
54116
55138
|
ctx.registry.searchPaths = [...searchPaths ?? [], SHIM_SEARCH_PATH];
|
|
55139
|
+
if (implicitCwdPath !== null) {
|
|
55140
|
+
ctx.registry.searchPaths.unshift(implicitCwdPath);
|
|
55141
|
+
}
|
|
54117
55142
|
ctx.fileASTCache.set(mainFileName, ast);
|
|
54118
55143
|
const skippedFiles = /* @__PURE__ */ new Set();
|
|
54119
55144
|
for (const f of mWorkspaceFiles) {
|
|
@@ -54147,6 +55172,11 @@ function executeCode(source, options = {}, workspaceFiles, mainFileName = "scrip
|
|
|
54147
55172
|
ctx.registerWorkspaceFiles(mWorkspaceFiles);
|
|
54148
55173
|
}
|
|
54149
55174
|
const functionIndex = ctx.buildFunctionIndex(jsUserFunctionNames);
|
|
55175
|
+
const savedSpecialBuiltins = /* @__PURE__ */ new Map();
|
|
55176
|
+
for (const name of SPECIAL_BUILTIN_NAMES) {
|
|
55177
|
+
const existing = getIBuiltin(name);
|
|
55178
|
+
if (existing) savedSpecialBuiltins.set(name, existing);
|
|
55179
|
+
}
|
|
54150
55180
|
const rt = new Runtime(options, options.initialVariableValues);
|
|
54151
55181
|
const savedIBuiltins = /* @__PURE__ */ new Map();
|
|
54152
55182
|
for (const ib of jsUserFunctions) {
|
|
@@ -54188,13 +55218,39 @@ ${jsCode}`
|
|
|
54188
55218
|
interpreter.installRuntimeCallbacks();
|
|
54189
55219
|
rt.searchPaths = ctx.registry.searchPaths;
|
|
54190
55220
|
let pathsModified = false;
|
|
55221
|
+
const rebuildWorkspace = () => {
|
|
55222
|
+
const paths = ctx.registry.searchPaths;
|
|
55223
|
+
const priorityOf = (name) => {
|
|
55224
|
+
let bestIdx = paths.length;
|
|
55225
|
+
let bestLen = -1;
|
|
55226
|
+
for (let i = 0; i < paths.length; i++) {
|
|
55227
|
+
const p2 = paths[i];
|
|
55228
|
+
const withSep = p2.endsWith("/") ? p2 : p2 + "/";
|
|
55229
|
+
if (name === p2 || name.startsWith(withSep)) {
|
|
55230
|
+
if (p2.length > bestLen) {
|
|
55231
|
+
bestLen = p2.length;
|
|
55232
|
+
bestIdx = i;
|
|
55233
|
+
}
|
|
55234
|
+
}
|
|
55235
|
+
}
|
|
55236
|
+
return bestIdx;
|
|
55237
|
+
};
|
|
55238
|
+
mWorkspaceFiles.sort((a, b) => priorityOf(a.name) - priorityOf(b.name));
|
|
55239
|
+
ctx.clearWorkspaceRegistrations();
|
|
55240
|
+
ctx.registerWorkspaceFiles(mWorkspaceFiles);
|
|
55241
|
+
const newIndex = ctx.buildFunctionIndex(jsUserFunctionNames);
|
|
55242
|
+
interpreter.functionIndex = newIndex;
|
|
55243
|
+
interpreter.clearAllCaches();
|
|
55244
|
+
pathsModified = true;
|
|
55245
|
+
};
|
|
54191
55246
|
rt.onPathChange = (action, dir, position) => {
|
|
54192
55247
|
const fileIO = options.fileIO;
|
|
54193
55248
|
const absDir = fileIO?.resolvePath?.(dir) ?? dir;
|
|
54194
55249
|
if (action === "add") {
|
|
54195
55250
|
if (ctx.registry.searchPaths.includes(absDir)) return;
|
|
54196
55251
|
if (position === "begin") {
|
|
54197
|
-
ctx.registry.searchPaths
|
|
55252
|
+
const cwdIsFirst = implicitCwdPath !== null && ctx.registry.searchPaths[0] === implicitCwdPath;
|
|
55253
|
+
ctx.registry.searchPaths.splice(cwdIsFirst ? 1 : 0, 0, absDir);
|
|
54198
55254
|
} else {
|
|
54199
55255
|
const shimIdx = ctx.registry.searchPaths.indexOf(SHIM_SEARCH_PATH);
|
|
54200
55256
|
if (shimIdx >= 0) {
|
|
@@ -54212,10 +55268,14 @@ ${jsCode}`
|
|
|
54212
55268
|
try {
|
|
54213
55269
|
ctx.fileASTCache.set(f.name, parseMFile(f.source, f.name));
|
|
54214
55270
|
} catch (e) {
|
|
54215
|
-
if (e instanceof SyntaxError
|
|
54216
|
-
|
|
55271
|
+
if (e instanceof SyntaxError) {
|
|
55272
|
+
console.warn(
|
|
55273
|
+
`Warning: skipping ${f.name} (syntax error at line ${e.line ?? "?"})`
|
|
55274
|
+
);
|
|
55275
|
+
} else {
|
|
55276
|
+
console.warn(`Warning: skipping ${f.name} (parse error)`);
|
|
54217
55277
|
}
|
|
54218
|
-
|
|
55278
|
+
continue;
|
|
54219
55279
|
}
|
|
54220
55280
|
interpreter.fileSources.set(f.name, f.source);
|
|
54221
55281
|
mWorkspaceFiles.push(f);
|
|
@@ -54255,26 +55315,76 @@ ${jsCode}`
|
|
|
54255
55315
|
}
|
|
54256
55316
|
}
|
|
54257
55317
|
}
|
|
54258
|
-
|
|
54259
|
-
|
|
54260
|
-
|
|
54261
|
-
|
|
54262
|
-
|
|
54263
|
-
|
|
54264
|
-
|
|
55318
|
+
rebuildWorkspace();
|
|
55319
|
+
};
|
|
55320
|
+
rt.onCwdChange = (newCwd) => {
|
|
55321
|
+
const fileIO = options.fileIO;
|
|
55322
|
+
const absNewCwd = fileIO?.resolvePath?.(newCwd) ?? newCwd;
|
|
55323
|
+
if (implicitCwdPath === absNewCwd) return;
|
|
55324
|
+
if (implicitCwdPath !== null) {
|
|
55325
|
+
const oldPrefix = implicitCwdPath.endsWith("/") ? implicitCwdPath : implicitCwdPath + "/";
|
|
55326
|
+
const deeperPaths = ctx.registry.searchPaths.filter(
|
|
55327
|
+
(p2) => p2 !== implicitCwdPath && p2 !== SHIM_SEARCH_PATH && (p2 === implicitCwdPath || p2.startsWith(oldPrefix))
|
|
54265
55328
|
);
|
|
54266
|
-
const
|
|
54267
|
-
|
|
54268
|
-
|
|
54269
|
-
|
|
54270
|
-
|
|
54271
|
-
|
|
54272
|
-
|
|
54273
|
-
|
|
54274
|
-
|
|
54275
|
-
|
|
55329
|
+
const fileBelongsToDeeperPath = (fname) => {
|
|
55330
|
+
for (const p2 of deeperPaths) {
|
|
55331
|
+
const withSep = p2.endsWith("/") ? p2 : p2 + "/";
|
|
55332
|
+
if (fname === p2 || fname.startsWith(withSep)) return true;
|
|
55333
|
+
}
|
|
55334
|
+
return false;
|
|
55335
|
+
};
|
|
55336
|
+
for (let i = mWorkspaceFiles.length - 1; i >= 0; i--) {
|
|
55337
|
+
const fname = mWorkspaceFiles[i].name;
|
|
55338
|
+
if ((fname === implicitCwdPath || fname.startsWith(oldPrefix)) && !fileBelongsToDeeperPath(fname)) {
|
|
55339
|
+
ctx.fileASTCache.delete(fname);
|
|
55340
|
+
interpreter.fileSources.delete(fname);
|
|
55341
|
+
mWorkspaceFiles.splice(i, 1);
|
|
55342
|
+
}
|
|
55343
|
+
}
|
|
55344
|
+
const oldIdx = ctx.registry.searchPaths.indexOf(implicitCwdPath);
|
|
55345
|
+
if (oldIdx >= 0) ctx.registry.searchPaths.splice(oldIdx, 1);
|
|
55346
|
+
implicitCwdPath = null;
|
|
55347
|
+
}
|
|
55348
|
+
if (ctx.registry.searchPaths.includes(absNewCwd)) {
|
|
55349
|
+
rebuildWorkspace();
|
|
55350
|
+
return;
|
|
55351
|
+
}
|
|
55352
|
+
ctx.registry.searchPaths.unshift(absNewCwd);
|
|
55353
|
+
implicitCwdPath = absNewCwd;
|
|
55354
|
+
if (fileIO?.scanDirectory) {
|
|
55355
|
+
let newFiles = [];
|
|
55356
|
+
try {
|
|
55357
|
+
newFiles = fileIO.scanDirectory(absNewCwd);
|
|
55358
|
+
} catch {
|
|
55359
|
+
}
|
|
55360
|
+
for (const f of newFiles) {
|
|
55361
|
+
if (f.name.endsWith(".m") && !ctx.fileASTCache.has(f.name)) {
|
|
55362
|
+
try {
|
|
55363
|
+
ctx.fileASTCache.set(f.name, parseMFile(f.source, f.name));
|
|
55364
|
+
} catch (e) {
|
|
55365
|
+
if (e instanceof SyntaxError) {
|
|
55366
|
+
console.warn(
|
|
55367
|
+
`Warning: skipping ${f.name} (syntax error at line ${e.line ?? "?"})`
|
|
55368
|
+
);
|
|
55369
|
+
} else {
|
|
55370
|
+
console.warn(`Warning: skipping ${f.name} (parse error)`);
|
|
55371
|
+
}
|
|
55372
|
+
continue;
|
|
55373
|
+
}
|
|
55374
|
+
interpreter.fileSources.set(f.name, f.source);
|
|
55375
|
+
mWorkspaceFiles.push(f);
|
|
55376
|
+
}
|
|
55377
|
+
}
|
|
55378
|
+
}
|
|
55379
|
+
rebuildWorkspace();
|
|
54276
55380
|
};
|
|
54277
55381
|
rt.evalLocalCallback = (code, initialVars, onOutput, fileName) => {
|
|
55382
|
+
const nestedSearchPaths = ctx.registry.searchPaths.filter(
|
|
55383
|
+
(p2) => p2 !== SHIM_SEARCH_PATH && p2 !== implicitCwdPath
|
|
55384
|
+
);
|
|
55385
|
+
const nestedWorkspaceFiles = mWorkspaceFiles.filter(
|
|
55386
|
+
(f) => !stdlibShimNames.has(f.name)
|
|
55387
|
+
);
|
|
54278
55388
|
const evalResult = executeCode(
|
|
54279
55389
|
code,
|
|
54280
55390
|
{
|
|
@@ -54282,11 +55392,18 @@ ${jsCode}`
|
|
|
54282
55392
|
displayResults: false,
|
|
54283
55393
|
initialVariableValues: initialVars,
|
|
54284
55394
|
fileIO: options.fileIO,
|
|
54285
|
-
|
|
55395
|
+
system: options.system,
|
|
55396
|
+
onInput: options.onInput,
|
|
55397
|
+
implicitCwdPath
|
|
54286
55398
|
},
|
|
54287
|
-
|
|
54288
|
-
fileName
|
|
55399
|
+
nestedWorkspaceFiles,
|
|
55400
|
+
fileName,
|
|
55401
|
+
nestedSearchPaths,
|
|
55402
|
+
nativeBridge2
|
|
54289
55403
|
);
|
|
55404
|
+
if (evalResult.implicitCwdPath !== void 0) {
|
|
55405
|
+
implicitCwdPath = evalResult.implicitCwdPath;
|
|
55406
|
+
}
|
|
54290
55407
|
return {
|
|
54291
55408
|
returnValue: evalResult.returnValue,
|
|
54292
55409
|
variableValues: evalResult.variableValues,
|
|
@@ -54318,12 +55435,13 @@ ${jitSections.join("\n\n")}` : "// No JS generated",
|
|
|
54318
55435
|
}
|
|
54319
55436
|
if (pathsModified) {
|
|
54320
55437
|
result.searchPaths = ctx.registry.searchPaths.filter(
|
|
54321
|
-
(p2) => p2 !== SHIM_SEARCH_PATH
|
|
55438
|
+
(p2) => p2 !== SHIM_SEARCH_PATH && p2 !== implicitCwdPath
|
|
54322
55439
|
);
|
|
54323
55440
|
result.workspaceFiles = mWorkspaceFiles.filter(
|
|
54324
55441
|
(f) => !stdlibShimNames.has(f.name)
|
|
54325
55442
|
);
|
|
54326
55443
|
}
|
|
55444
|
+
result.implicitCwdPath = implicitCwdPath;
|
|
54327
55445
|
return result;
|
|
54328
55446
|
} catch (e) {
|
|
54329
55447
|
const generatedJS = jitSections.length > 0 ? `// Interpreter mode \u2014 JIT compiled sections:
|
|
@@ -54359,6 +55477,9 @@ ${jitSections.join("\n\n")}` : "// No JS generated";
|
|
|
54359
55477
|
unregisterIBuiltin(ib.name);
|
|
54360
55478
|
}
|
|
54361
55479
|
}
|
|
55480
|
+
for (const [, ib] of savedSpecialBuiltins) {
|
|
55481
|
+
registerDynamicIBuiltin(ib);
|
|
55482
|
+
}
|
|
54362
55483
|
}
|
|
54363
55484
|
}
|
|
54364
55485
|
|
|
@@ -54376,7 +55497,9 @@ import {
|
|
|
54376
55497
|
unlinkSync,
|
|
54377
55498
|
readdirSync as readdirSync2,
|
|
54378
55499
|
rmSync,
|
|
54379
|
-
rmdirSync
|
|
55500
|
+
rmdirSync,
|
|
55501
|
+
renameSync,
|
|
55502
|
+
chmodSync
|
|
54380
55503
|
} from "fs";
|
|
54381
55504
|
import { unzipSync } from "fflate";
|
|
54382
55505
|
import { execFileSync } from "child_process";
|
|
@@ -54435,6 +55558,18 @@ function expandTilde(filepath) {
|
|
|
54435
55558
|
}
|
|
54436
55559
|
return filepath;
|
|
54437
55560
|
}
|
|
55561
|
+
function copyDirRecursive(src, dst) {
|
|
55562
|
+
mkdirSync(dst, { recursive: true });
|
|
55563
|
+
for (const entry of readdirSync2(src, { withFileTypes: true })) {
|
|
55564
|
+
const s = join3(src, entry.name);
|
|
55565
|
+
const d = join3(dst, entry.name);
|
|
55566
|
+
if (entry.isDirectory()) {
|
|
55567
|
+
copyDirRecursive(s, d);
|
|
55568
|
+
} else {
|
|
55569
|
+
writeFileSync(d, readFileSync3(s));
|
|
55570
|
+
}
|
|
55571
|
+
}
|
|
55572
|
+
}
|
|
54438
55573
|
function permissionToFlags(permission) {
|
|
54439
55574
|
switch (permission) {
|
|
54440
55575
|
case "r":
|
|
@@ -54700,6 +55835,59 @@ var NodeFileIOAdapter = class {
|
|
|
54700
55835
|
return false;
|
|
54701
55836
|
}
|
|
54702
55837
|
}
|
|
55838
|
+
movefile(source, destination, force) {
|
|
55839
|
+
try {
|
|
55840
|
+
const src = expandTilde(source);
|
|
55841
|
+
const srcStat = statSync2(src);
|
|
55842
|
+
let dst = expandTilde(destination);
|
|
55843
|
+
let dstType = null;
|
|
55844
|
+
try {
|
|
55845
|
+
const s = statSync2(dst);
|
|
55846
|
+
dstType = s.isDirectory() ? "dir" : "file";
|
|
55847
|
+
} catch {
|
|
55848
|
+
dstType = null;
|
|
55849
|
+
}
|
|
55850
|
+
if (dstType === "dir") {
|
|
55851
|
+
dst = join3(dst, basename(src));
|
|
55852
|
+
try {
|
|
55853
|
+
dstType = statSync2(dst).isDirectory() ? "dir" : "file";
|
|
55854
|
+
} catch {
|
|
55855
|
+
dstType = null;
|
|
55856
|
+
}
|
|
55857
|
+
}
|
|
55858
|
+
if (dstType === "file" && force) {
|
|
55859
|
+
try {
|
|
55860
|
+
chmodSync(dst, 438);
|
|
55861
|
+
} catch {
|
|
55862
|
+
}
|
|
55863
|
+
}
|
|
55864
|
+
if (srcStat.isDirectory() && dstType === "file") {
|
|
55865
|
+
return false;
|
|
55866
|
+
}
|
|
55867
|
+
const parent = dirname(dst);
|
|
55868
|
+
if (parent && parent !== "." && parent !== "/") {
|
|
55869
|
+
try {
|
|
55870
|
+
mkdirSync(parent, { recursive: true });
|
|
55871
|
+
} catch {
|
|
55872
|
+
}
|
|
55873
|
+
}
|
|
55874
|
+
try {
|
|
55875
|
+
renameSync(src, dst);
|
|
55876
|
+
return true;
|
|
55877
|
+
} catch {
|
|
55878
|
+
if (srcStat.isDirectory()) {
|
|
55879
|
+
copyDirRecursive(src, dst);
|
|
55880
|
+
rmSync(src, { recursive: true });
|
|
55881
|
+
} else {
|
|
55882
|
+
writeFileSync(dst, readFileSync3(src));
|
|
55883
|
+
unlinkSync(src);
|
|
55884
|
+
}
|
|
55885
|
+
return true;
|
|
55886
|
+
}
|
|
55887
|
+
} catch {
|
|
55888
|
+
return false;
|
|
55889
|
+
}
|
|
55890
|
+
}
|
|
54703
55891
|
deleteFile(pattern) {
|
|
54704
55892
|
const p2 = expandTilde(pattern);
|
|
54705
55893
|
if (p2.includes("*") || p2.includes("?")) {
|
|
@@ -55027,6 +56215,7 @@ function saveHistoryEntry(entry, hist) {
|
|
|
55027
56215
|
async function runRepl(initialWorkspaceFiles, onDrawnow, initialSearchPaths, nativeBridge2, optimization) {
|
|
55028
56216
|
let variableValues = {};
|
|
55029
56217
|
let holdState = false;
|
|
56218
|
+
let implicitCwdPath;
|
|
55030
56219
|
const workspaceFiles = [...initialWorkspaceFiles];
|
|
55031
56220
|
const searchPaths = [...initialSearchPaths ?? []];
|
|
55032
56221
|
const fileIO = new NodeFileIOAdapter();
|
|
@@ -55079,7 +56268,8 @@ async function runRepl(initialWorkspaceFiles, onDrawnow, initialSearchPaths, nat
|
|
|
55079
56268
|
initialHoldState: holdState,
|
|
55080
56269
|
optimization,
|
|
55081
56270
|
fileIO,
|
|
55082
|
-
system
|
|
56271
|
+
system,
|
|
56272
|
+
implicitCwdPath
|
|
55083
56273
|
},
|
|
55084
56274
|
workspaceFiles,
|
|
55085
56275
|
"repl",
|
|
@@ -55094,6 +56284,9 @@ async function runRepl(initialWorkspaceFiles, onDrawnow, initialSearchPaths, nat
|
|
|
55094
56284
|
workspaceFiles.length = 0;
|
|
55095
56285
|
workspaceFiles.push(...result.workspaceFiles ?? []);
|
|
55096
56286
|
}
|
|
56287
|
+
if (result.implicitCwdPath !== void 0) {
|
|
56288
|
+
implicitCwdPath = result.implicitCwdPath;
|
|
56289
|
+
}
|
|
55097
56290
|
if (result.plotInstructions.length > 0 && onDrawnow) {
|
|
55098
56291
|
onDrawnow(result.plotInstructions);
|
|
55099
56292
|
}
|
|
@@ -55192,7 +56385,8 @@ async function runRepl(initialWorkspaceFiles, onDrawnow, initialSearchPaths, nat
|
|
|
55192
56385
|
initialHoldState: holdState,
|
|
55193
56386
|
optimization,
|
|
55194
56387
|
fileIO,
|
|
55195
|
-
system
|
|
56388
|
+
system,
|
|
56389
|
+
implicitCwdPath
|
|
55196
56390
|
},
|
|
55197
56391
|
workspaceFiles,
|
|
55198
56392
|
"repl",
|
|
@@ -55207,6 +56401,9 @@ async function runRepl(initialWorkspaceFiles, onDrawnow, initialSearchPaths, nat
|
|
|
55207
56401
|
workspaceFiles.length = 0;
|
|
55208
56402
|
workspaceFiles.push(...result.workspaceFiles ?? []);
|
|
55209
56403
|
}
|
|
56404
|
+
if (result.implicitCwdPath !== void 0) {
|
|
56405
|
+
implicitCwdPath = result.implicitCwdPath;
|
|
56406
|
+
}
|
|
55210
56407
|
if (result.plotInstructions.length > 0 && onDrawnow) {
|
|
55211
56408
|
onDrawnow(result.plotInstructions);
|
|
55212
56409
|
}
|
|
@@ -55708,7 +56905,6 @@ Options (for run and eval):
|
|
|
55708
56905
|
--path <dir> Add extra workspace directory
|
|
55709
56906
|
--plot Enable plot server
|
|
55710
56907
|
--plot-port <port> Set plot server port (implies --plot)
|
|
55711
|
-
--add-script-path Add the script's directory to the workspace (run only)
|
|
55712
56908
|
--opt <level> Optimization level (0=none, 1=JIT scalar functions; default: 1)
|
|
55713
56909
|
|
|
55714
56910
|
Environment variables:
|
|
@@ -55722,7 +56918,6 @@ function parseOptions(args) {
|
|
|
55722
56918
|
stream: false,
|
|
55723
56919
|
plot: false,
|
|
55724
56920
|
plotPort: void 0,
|
|
55725
|
-
addScriptPath: false,
|
|
55726
56921
|
extraPaths: [],
|
|
55727
56922
|
positional: [],
|
|
55728
56923
|
profileOutput: void 0,
|
|
@@ -55762,9 +56957,6 @@ function parseOptions(args) {
|
|
|
55762
56957
|
case "--plot":
|
|
55763
56958
|
opts.plot = true;
|
|
55764
56959
|
break;
|
|
55765
|
-
case "--add-script-path":
|
|
55766
|
-
opts.addScriptPath = true;
|
|
55767
|
-
break;
|
|
55768
56960
|
case "--plot-port":
|
|
55769
56961
|
i++;
|
|
55770
56962
|
if (i >= args.length) {
|
|
@@ -55830,13 +57022,9 @@ async function cmdRun(args) {
|
|
|
55830
57022
|
const filepath = resolve2(process.cwd(), opts.positional[0]);
|
|
55831
57023
|
const code = readFileSync5(filepath, "utf-8");
|
|
55832
57024
|
const mainFileName = filepath;
|
|
57025
|
+
process.chdir(dirname2(filepath));
|
|
55833
57026
|
const searchPaths = [];
|
|
55834
|
-
|
|
55835
|
-
if (opts.addScriptPath) {
|
|
55836
|
-
const scriptDir = dirname2(filepath);
|
|
55837
|
-
searchPaths.push(scriptDir);
|
|
55838
|
-
workspaceFiles = scanMFiles(scriptDir, filepath);
|
|
55839
|
-
}
|
|
57027
|
+
const workspaceFiles = [];
|
|
55840
57028
|
for (const p2 of opts.extraPaths) {
|
|
55841
57029
|
searchPaths.push(p2);
|
|
55842
57030
|
workspaceFiles.push(...scanMFiles(p2));
|