numbl 0.0.15 → 0.0.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist-cli/cli.js
CHANGED
|
@@ -158,17 +158,17 @@ async function fetchPackageIndex(backend, indexUrl = DEFAULT_INDEX_URL) {
|
|
|
158
158
|
return backend.fetchJson(indexUrl);
|
|
159
159
|
}
|
|
160
160
|
function findPackageEntry(index2, packageName, arch) {
|
|
161
|
-
const
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
161
|
+
for (const candidate of ["numbl_" + arch, "numbl_wasm", "all"]) {
|
|
162
|
+
const entry = index2.packages.find(
|
|
163
|
+
(p) => p.name === packageName && p.architecture === candidate
|
|
164
|
+
);
|
|
165
|
+
if (entry) return entry;
|
|
166
|
+
}
|
|
167
|
+
return void 0;
|
|
168
168
|
}
|
|
169
169
|
function listAvailablePackages(index2, arch) {
|
|
170
170
|
return index2.packages.filter(
|
|
171
|
-
(p) => p.architecture === arch || p.architecture === "
|
|
171
|
+
(p) => p.architecture === arch || p.architecture === "wasm" || p.architecture === "all"
|
|
172
172
|
);
|
|
173
173
|
}
|
|
174
174
|
|
|
@@ -181,7 +181,9 @@ function resolveDependencies(index2, packageName, arch) {
|
|
|
181
181
|
visited.add(name);
|
|
182
182
|
const entry = findPackageEntry(index2, name, arch);
|
|
183
183
|
if (!entry) {
|
|
184
|
-
throw new Error(
|
|
184
|
+
throw new Error(
|
|
185
|
+
`Package "${name}" not found for architecture "${arch}" (tried ${arch}, wasm, all)`
|
|
186
|
+
);
|
|
185
187
|
}
|
|
186
188
|
for (const dep of entry.dependencies) {
|
|
187
189
|
visit(dep);
|
|
@@ -210,13 +212,13 @@ function computeRequiredPackages(directlyInstalled, index2, arch) {
|
|
|
210
212
|
|
|
211
213
|
// src/mip/mip-manager.ts
|
|
212
214
|
function packagesDir(mipDir) {
|
|
213
|
-
return `${mipDir}/
|
|
215
|
+
return `${mipDir}/numbl_packages`;
|
|
214
216
|
}
|
|
215
217
|
function packageDir(mipDir, name) {
|
|
216
|
-
return `${mipDir}/
|
|
218
|
+
return `${mipDir}/numbl_packages/${name}`;
|
|
217
219
|
}
|
|
218
220
|
function directlyInstalledPath(mipDir) {
|
|
219
|
-
return `${mipDir}/
|
|
221
|
+
return `${mipDir}/numbl_packages/directly_installed.txt`;
|
|
220
222
|
}
|
|
221
223
|
var MipManager = class {
|
|
222
224
|
constructor(backend) {
|
|
@@ -17600,6 +17602,22 @@ function complexComparisonOp(a, b, op) {
|
|
|
17600
17602
|
`Matrix dimensions must agree for comparison: [${at.shape.join(",")}] vs [${bt.shape.join(",")}]`
|
|
17601
17603
|
);
|
|
17602
17604
|
}
|
|
17605
|
+
function signedInf(x) {
|
|
17606
|
+
return x > 0 ? Infinity : x < 0 ? -Infinity : 0;
|
|
17607
|
+
}
|
|
17608
|
+
function complexDivide(aRe, aIm, bRe, bIm) {
|
|
17609
|
+
const denom = bRe * bRe + bIm * bIm;
|
|
17610
|
+
if (denom === 0) {
|
|
17611
|
+
if (aRe === 0 && aIm === 0) {
|
|
17612
|
+
return { re: NaN, im: 0 };
|
|
17613
|
+
}
|
|
17614
|
+
return { re: signedInf(aRe), im: signedInf(aIm) };
|
|
17615
|
+
}
|
|
17616
|
+
return {
|
|
17617
|
+
re: (aRe * bRe + aIm * bIm) / denom,
|
|
17618
|
+
im: (aIm * bRe - aRe * bIm) / denom
|
|
17619
|
+
};
|
|
17620
|
+
}
|
|
17603
17621
|
function complexBinaryOp(a, b, op) {
|
|
17604
17622
|
const ac = toComplexParts(a);
|
|
17605
17623
|
const bc = toComplexParts(b);
|
|
@@ -17702,25 +17720,13 @@ function mDiv(a, b) {
|
|
|
17702
17720
|
return mConjugateTranspose(result);
|
|
17703
17721
|
}
|
|
17704
17722
|
if (isComplexOrMixed(a, b)) {
|
|
17705
|
-
return complexBinaryOp(a, b,
|
|
17706
|
-
const denom = bRe * bRe + bIm * bIm;
|
|
17707
|
-
return {
|
|
17708
|
-
re: (aRe * bRe + aIm * bIm) / denom,
|
|
17709
|
-
im: (aIm * bRe - aRe * bIm) / denom
|
|
17710
|
-
};
|
|
17711
|
-
});
|
|
17723
|
+
return complexBinaryOp(a, b, complexDivide);
|
|
17712
17724
|
}
|
|
17713
17725
|
return binaryOp(a, b, (x, y) => x / y);
|
|
17714
17726
|
}
|
|
17715
17727
|
function mElemDiv(a, b) {
|
|
17716
17728
|
if (isComplexOrMixed(a, b)) {
|
|
17717
|
-
return complexBinaryOp(a, b,
|
|
17718
|
-
const denom = bRe * bRe + bIm * bIm;
|
|
17719
|
-
return {
|
|
17720
|
-
re: (aRe * bRe + aIm * bIm) / denom,
|
|
17721
|
-
im: (aIm * bRe - aRe * bIm) / denom
|
|
17722
|
-
};
|
|
17723
|
-
});
|
|
17729
|
+
return complexBinaryOp(a, b, complexDivide);
|
|
17724
17730
|
}
|
|
17725
17731
|
return binaryOp(a, b, (x, y) => x / y);
|
|
17726
17732
|
}
|
|
@@ -20603,7 +20609,8 @@ var COMMAND_VERBS = [
|
|
|
20603
20609
|
"square",
|
|
20604
20610
|
"vis3d"
|
|
20605
20611
|
],
|
|
20606
|
-
optional: false
|
|
20612
|
+
optional: false,
|
|
20613
|
+
multiKeyword: true
|
|
20607
20614
|
}
|
|
20608
20615
|
},
|
|
20609
20616
|
{ name: "clear", argKind: { type: "Any" } },
|
|
@@ -20965,19 +20972,41 @@ var ExpressionParser = class extends ParserBase {
|
|
|
20965
20972
|
}
|
|
20966
20973
|
}
|
|
20967
20974
|
parsePow() {
|
|
20968
|
-
|
|
20969
|
-
|
|
20970
|
-
|
|
20971
|
-
|
|
20972
|
-
|
|
20973
|
-
|
|
20974
|
-
|
|
20975
|
-
|
|
20976
|
-
|
|
20975
|
+
let node = this.parsePostfix();
|
|
20976
|
+
while (true) {
|
|
20977
|
+
const tok = this.peekToken();
|
|
20978
|
+
let op;
|
|
20979
|
+
if (tok === 36 /* Caret */) {
|
|
20980
|
+
op = "Pow" /* Pow */;
|
|
20981
|
+
} else if (tok === 58 /* DotCaret */) {
|
|
20982
|
+
op = "ElemPow" /* ElemPow */;
|
|
20983
|
+
} else {
|
|
20984
|
+
return node;
|
|
20985
|
+
}
|
|
20986
|
+
this.pos++;
|
|
20987
|
+
const rhs = this.parsePowRHS();
|
|
20988
|
+
node = this.makeBinary(node, op, rhs);
|
|
20989
|
+
}
|
|
20990
|
+
}
|
|
20991
|
+
/** Parse the right-hand side of a ^ or .^ operator: unary prefixes then postfix. */
|
|
20992
|
+
parsePowRHS() {
|
|
20993
|
+
if (this.peekToken() === 31 /* Plus */) {
|
|
20994
|
+
const start = this.tokens[this.pos].position;
|
|
20995
|
+
this.pos++;
|
|
20996
|
+
const expr = this.parsePowRHS();
|
|
20997
|
+
return this.makeUnary("Plus" /* Plus */, expr, start);
|
|
20998
|
+
} else if (this.peekToken() === 32 /* Minus */) {
|
|
20999
|
+
const start = this.tokens[this.pos].position;
|
|
21000
|
+
this.pos++;
|
|
21001
|
+
const expr = this.parsePowRHS();
|
|
21002
|
+
return this.makeUnary("Minus" /* Minus */, expr, start);
|
|
21003
|
+
} else if (this.peekToken() === 39 /* Tilde */) {
|
|
21004
|
+
const start = this.tokens[this.pos].position;
|
|
21005
|
+
this.pos++;
|
|
21006
|
+
const expr = this.parsePowRHS();
|
|
21007
|
+
return this.makeUnary("Not" /* Not */, expr, start);
|
|
20977
21008
|
}
|
|
20978
|
-
this.
|
|
20979
|
-
const rhs = this.parseUnary();
|
|
20980
|
-
return this.makeBinary(node, op, rhs);
|
|
21009
|
+
return this.parsePostfix();
|
|
20981
21010
|
}
|
|
20982
21011
|
parsePostfixWithBase(expr) {
|
|
20983
21012
|
while (true) {
|
|
@@ -21560,25 +21589,32 @@ var CommandParser = class extends ExpressionParser {
|
|
|
21560
21589
|
}
|
|
21561
21590
|
return args;
|
|
21562
21591
|
}
|
|
21563
|
-
if (args.length > 1) {
|
|
21592
|
+
if (args.length > 1 && !command.argKind.multiKeyword) {
|
|
21564
21593
|
throw this.error(
|
|
21565
21594
|
`'${command.name}' command syntax accepts only one argument`
|
|
21566
21595
|
);
|
|
21567
21596
|
}
|
|
21568
|
-
const
|
|
21569
|
-
|
|
21570
|
-
|
|
21571
|
-
|
|
21572
|
-
|
|
21597
|
+
const keywords = [];
|
|
21598
|
+
for (const arg of args) {
|
|
21599
|
+
const keyword = extractKeyword(arg);
|
|
21600
|
+
if (!keyword) {
|
|
21601
|
+
throw this.error(
|
|
21602
|
+
`'${command.name}' command syntax expects a keyword argument`
|
|
21603
|
+
);
|
|
21604
|
+
}
|
|
21605
|
+
if (allowed !== void 0 && !allowed.some((a) => a.toLowerCase() === keyword.toLowerCase())) {
|
|
21606
|
+
throw this.error(
|
|
21607
|
+
`'${command.name}' command syntax does not support '${keyword}'`
|
|
21608
|
+
);
|
|
21609
|
+
}
|
|
21610
|
+
keywords.push(keyword);
|
|
21573
21611
|
}
|
|
21574
|
-
if (
|
|
21575
|
-
const
|
|
21576
|
-
return [{ type: "String", value: `"${
|
|
21577
|
-
} else {
|
|
21578
|
-
throw this.error(
|
|
21579
|
-
`'${command.name}' command syntax does not support '${keyword}'`
|
|
21580
|
-
);
|
|
21612
|
+
if (keywords.length === 1) {
|
|
21613
|
+
const span2 = args[0].span;
|
|
21614
|
+
return [{ type: "String", value: `"${keywords[0]}"`, span: span2 }];
|
|
21581
21615
|
}
|
|
21616
|
+
const span = args[0].span;
|
|
21617
|
+
return [{ type: "String", value: `"${keywords.join(" ")}"`, span }];
|
|
21582
21618
|
}
|
|
21583
21619
|
return args;
|
|
21584
21620
|
}
|
|
@@ -33809,6 +33845,12 @@ function registerMiscFunctions() {
|
|
|
33809
33845
|
return RTV.num(0);
|
|
33810
33846
|
})
|
|
33811
33847
|
);
|
|
33848
|
+
register(
|
|
33849
|
+
"clc",
|
|
33850
|
+
builtinSingle(() => {
|
|
33851
|
+
return RTV.num(0);
|
|
33852
|
+
})
|
|
33853
|
+
);
|
|
33812
33854
|
register(
|
|
33813
33855
|
"clf",
|
|
33814
33856
|
builtinSingle(() => {
|
|
@@ -34257,6 +34299,62 @@ function registerGraphicsFunctions() {
|
|
|
34257
34299
|
"shading",
|
|
34258
34300
|
builtinSingle(() => RTV.num(0))
|
|
34259
34301
|
);
|
|
34302
|
+
register(
|
|
34303
|
+
"subplot",
|
|
34304
|
+
builtinSingle(() => RTV.num(0))
|
|
34305
|
+
);
|
|
34306
|
+
register(
|
|
34307
|
+
"legend",
|
|
34308
|
+
builtinSingle(() => RTV.num(0))
|
|
34309
|
+
);
|
|
34310
|
+
register(
|
|
34311
|
+
"sgtitle",
|
|
34312
|
+
builtinSingle(() => RTV.num(0))
|
|
34313
|
+
);
|
|
34314
|
+
register(
|
|
34315
|
+
"zlabel",
|
|
34316
|
+
builtinSingle(() => RTV.num(0))
|
|
34317
|
+
);
|
|
34318
|
+
register(
|
|
34319
|
+
"colorbar",
|
|
34320
|
+
builtinSingle(() => RTV.num(0))
|
|
34321
|
+
);
|
|
34322
|
+
register(
|
|
34323
|
+
"colormap",
|
|
34324
|
+
builtinSingle(() => RTV.num(0))
|
|
34325
|
+
);
|
|
34326
|
+
register(
|
|
34327
|
+
"axis",
|
|
34328
|
+
builtinSingle(() => RTV.num(0))
|
|
34329
|
+
);
|
|
34330
|
+
register(
|
|
34331
|
+
"view",
|
|
34332
|
+
builtinSingle(() => RTV.num(0))
|
|
34333
|
+
);
|
|
34334
|
+
register(
|
|
34335
|
+
"imagesc",
|
|
34336
|
+
builtinSingle(() => RTV.num(0))
|
|
34337
|
+
);
|
|
34338
|
+
register(
|
|
34339
|
+
"contour",
|
|
34340
|
+
builtinSingle(() => RTV.num(0))
|
|
34341
|
+
);
|
|
34342
|
+
register(
|
|
34343
|
+
"contourf",
|
|
34344
|
+
builtinSingle(() => RTV.num(0))
|
|
34345
|
+
);
|
|
34346
|
+
register(
|
|
34347
|
+
"mesh",
|
|
34348
|
+
builtinSingle(() => RTV.num(0))
|
|
34349
|
+
);
|
|
34350
|
+
register(
|
|
34351
|
+
"waterfall",
|
|
34352
|
+
builtinSingle(() => RTV.num(0))
|
|
34353
|
+
);
|
|
34354
|
+
register(
|
|
34355
|
+
"scatter",
|
|
34356
|
+
builtinSingle(() => RTV.num(0))
|
|
34357
|
+
);
|
|
34260
34358
|
register(
|
|
34261
34359
|
"drawnow",
|
|
34262
34360
|
builtinSingle(() => RTV.num(0))
|
|
@@ -34265,6 +34363,45 @@ function registerGraphicsFunctions() {
|
|
|
34265
34363
|
"pause",
|
|
34266
34364
|
builtinSingle(() => RTV.num(0))
|
|
34267
34365
|
);
|
|
34366
|
+
const colormapNames = [
|
|
34367
|
+
"parula",
|
|
34368
|
+
"jet",
|
|
34369
|
+
"hsv",
|
|
34370
|
+
"hot",
|
|
34371
|
+
"cool",
|
|
34372
|
+
"spring",
|
|
34373
|
+
"summer",
|
|
34374
|
+
"autumn",
|
|
34375
|
+
"winter",
|
|
34376
|
+
"gray",
|
|
34377
|
+
"bone",
|
|
34378
|
+
"copper",
|
|
34379
|
+
"pink"
|
|
34380
|
+
];
|
|
34381
|
+
for (const cm of colormapNames) {
|
|
34382
|
+
register(
|
|
34383
|
+
cm,
|
|
34384
|
+
builtinSingle(() => RTV.char(cm))
|
|
34385
|
+
);
|
|
34386
|
+
}
|
|
34387
|
+
register(
|
|
34388
|
+
"peaks",
|
|
34389
|
+
builtinSingle((args) => {
|
|
34390
|
+
const n = args.length > 0 ? isRuntimeNumber(args[0]) ? args[0] : toNumber(args[0]) : 49;
|
|
34391
|
+
const data = new FloatXArray(n * n);
|
|
34392
|
+
for (let j = 0; j < n; j++) {
|
|
34393
|
+
const y = -3 + 6 * j / (n - 1);
|
|
34394
|
+
for (let i = 0; i < n; i++) {
|
|
34395
|
+
const x = -3 + 6 * i / (n - 1);
|
|
34396
|
+
const x2 = x * x;
|
|
34397
|
+
const y2 = y * y;
|
|
34398
|
+
const z = 3 * Math.pow(1 - x, 2) * Math.exp(-x2 - Math.pow(y + 1, 2)) - 10 * (x / 5 - x * x2 - Math.pow(y, 5)) * Math.exp(-x2 - y2) - 1 / 3 * Math.exp(-Math.pow(x + 1, 2) - y2);
|
|
34399
|
+
data[j * n + i] = z;
|
|
34400
|
+
}
|
|
34401
|
+
}
|
|
34402
|
+
return RTV.tensor(data, [n, n]);
|
|
34403
|
+
})
|
|
34404
|
+
);
|
|
34268
34405
|
}
|
|
34269
34406
|
|
|
34270
34407
|
// src/numbl-core/builtins/validators.ts
|
|
@@ -34436,7 +34573,7 @@ function registerDummyStringFunctions() {
|
|
|
34436
34573
|
register(name, fn);
|
|
34437
34574
|
}
|
|
34438
34575
|
}
|
|
34439
|
-
var returnEmptyArrayFunctions = ["who", "xlim", "ylim"
|
|
34576
|
+
var returnEmptyArrayFunctions = ["who", "xlim", "ylim"];
|
|
34440
34577
|
function registerDummyArrayFunctions() {
|
|
34441
34578
|
const fn = builtinSingle(() => RTV.tensor([], [0, 0]), {
|
|
34442
34579
|
outputType: IType.tensor()
|
|
@@ -36298,6 +36435,30 @@ function dispatch(rt, name, nargout, args, targetClassName) {
|
|
|
36298
36435
|
if (name === "surf") {
|
|
36299
36436
|
return rt.surf_call(args.map((a) => ensureRuntimeValue(a)));
|
|
36300
36437
|
}
|
|
36438
|
+
if (name === "scatter") {
|
|
36439
|
+
return rt.scatter_call(args.map((a) => ensureRuntimeValue(a)));
|
|
36440
|
+
}
|
|
36441
|
+
if (name === "imagesc") {
|
|
36442
|
+
return rt.imagesc_call(args.map((a) => ensureRuntimeValue(a)));
|
|
36443
|
+
}
|
|
36444
|
+
if (name === "contour") {
|
|
36445
|
+
return rt.contour_call(
|
|
36446
|
+
args.map((a) => ensureRuntimeValue(a)),
|
|
36447
|
+
false
|
|
36448
|
+
);
|
|
36449
|
+
}
|
|
36450
|
+
if (name === "contourf") {
|
|
36451
|
+
return rt.contour_call(
|
|
36452
|
+
args.map((a) => ensureRuntimeValue(a)),
|
|
36453
|
+
true
|
|
36454
|
+
);
|
|
36455
|
+
}
|
|
36456
|
+
if (name === "mesh") {
|
|
36457
|
+
return rt.mesh_call(args.map((a) => ensureRuntimeValue(a)));
|
|
36458
|
+
}
|
|
36459
|
+
if (name === "waterfall") {
|
|
36460
|
+
return rt.mesh_call(args.map((a) => ensureRuntimeValue(a)));
|
|
36461
|
+
}
|
|
36301
36462
|
}
|
|
36302
36463
|
if (rt.compileSpecialized) {
|
|
36303
36464
|
const argTypes = args.map(
|
|
@@ -36345,6 +36506,30 @@ function callBuiltin(rt, name, nargout, args) {
|
|
|
36345
36506
|
if (name === "surf") {
|
|
36346
36507
|
return rt.surf_call(args.map((a) => ensureRuntimeValue(a)));
|
|
36347
36508
|
}
|
|
36509
|
+
if (name === "scatter") {
|
|
36510
|
+
return rt.scatter_call(args.map((a) => ensureRuntimeValue(a)));
|
|
36511
|
+
}
|
|
36512
|
+
if (name === "imagesc") {
|
|
36513
|
+
return rt.imagesc_call(args.map((a) => ensureRuntimeValue(a)));
|
|
36514
|
+
}
|
|
36515
|
+
if (name === "contour") {
|
|
36516
|
+
return rt.contour_call(
|
|
36517
|
+
args.map((a) => ensureRuntimeValue(a)),
|
|
36518
|
+
false
|
|
36519
|
+
);
|
|
36520
|
+
}
|
|
36521
|
+
if (name === "contourf") {
|
|
36522
|
+
return rt.contour_call(
|
|
36523
|
+
args.map((a) => ensureRuntimeValue(a)),
|
|
36524
|
+
true
|
|
36525
|
+
);
|
|
36526
|
+
}
|
|
36527
|
+
if (name === "mesh") {
|
|
36528
|
+
return rt.mesh_call(args.map((a) => ensureRuntimeValue(a)));
|
|
36529
|
+
}
|
|
36530
|
+
if (name === "waterfall") {
|
|
36531
|
+
return rt.mesh_call(args.map((a) => ensureRuntimeValue(a)));
|
|
36532
|
+
}
|
|
36348
36533
|
const builtin = rt.builtins[name];
|
|
36349
36534
|
if (builtin) return builtin(nargout, args);
|
|
36350
36535
|
throw new RuntimeError(`'${name}' is not a builtin function`);
|
|
@@ -36359,6 +36544,30 @@ function callBuiltinSync(rt, name, nargout, args) {
|
|
|
36359
36544
|
if (name === "surf") {
|
|
36360
36545
|
return rt.surf_call(args.map((a) => ensureRuntimeValue(a)));
|
|
36361
36546
|
}
|
|
36547
|
+
if (name === "scatter") {
|
|
36548
|
+
return rt.scatter_call(args.map((a) => ensureRuntimeValue(a)));
|
|
36549
|
+
}
|
|
36550
|
+
if (name === "imagesc") {
|
|
36551
|
+
return rt.imagesc_call(args.map((a) => ensureRuntimeValue(a)));
|
|
36552
|
+
}
|
|
36553
|
+
if (name === "contour") {
|
|
36554
|
+
return rt.contour_call(
|
|
36555
|
+
args.map((a) => ensureRuntimeValue(a)),
|
|
36556
|
+
false
|
|
36557
|
+
);
|
|
36558
|
+
}
|
|
36559
|
+
if (name === "contourf") {
|
|
36560
|
+
return rt.contour_call(
|
|
36561
|
+
args.map((a) => ensureRuntimeValue(a)),
|
|
36562
|
+
true
|
|
36563
|
+
);
|
|
36564
|
+
}
|
|
36565
|
+
if (name === "mesh") {
|
|
36566
|
+
return rt.mesh_call(args.map((a) => ensureRuntimeValue(a)));
|
|
36567
|
+
}
|
|
36568
|
+
if (name === "waterfall") {
|
|
36569
|
+
return rt.mesh_call(args.map((a) => ensureRuntimeValue(a)));
|
|
36570
|
+
}
|
|
36362
36571
|
const builtin = rt.builtins[name];
|
|
36363
36572
|
if (builtin) return builtin(nargout, args);
|
|
36364
36573
|
throw new RuntimeError(`'${name}' is not a builtin function`);
|
|
@@ -38238,6 +38447,88 @@ function getStringValueIfString(v) {
|
|
|
38238
38447
|
if (isRuntimeChar(v)) return v.value;
|
|
38239
38448
|
return void 0;
|
|
38240
38449
|
}
|
|
38450
|
+
function parseScatterArgs(args) {
|
|
38451
|
+
if (args.length < 2) throw new Error("scatter requires at least 2 arguments");
|
|
38452
|
+
const xData = toNumberArray(args[0]);
|
|
38453
|
+
const yData = toNumberArray(args[1]);
|
|
38454
|
+
const trace = {
|
|
38455
|
+
x: xData,
|
|
38456
|
+
y: yData,
|
|
38457
|
+
marker: "o",
|
|
38458
|
+
lineStyle: "none"
|
|
38459
|
+
};
|
|
38460
|
+
let pos = 2;
|
|
38461
|
+
let filled = false;
|
|
38462
|
+
if (pos < args.length && isNumericArg(args[pos])) {
|
|
38463
|
+
const sz = args[pos];
|
|
38464
|
+
if (isRuntimeNumber(sz)) {
|
|
38465
|
+
trace.markerSize = Math.sqrt(sz) * 0.5;
|
|
38466
|
+
} else if (isRuntimeTensor(sz)) {
|
|
38467
|
+
const sArr = toNumberArray(sz);
|
|
38468
|
+
if (sArr.length === 1 || new Set(sArr).size === 1) {
|
|
38469
|
+
trace.markerSize = Math.sqrt(sArr[0]) * 0.5;
|
|
38470
|
+
}
|
|
38471
|
+
}
|
|
38472
|
+
pos++;
|
|
38473
|
+
}
|
|
38474
|
+
if (pos < args.length && !isNameValueKey(args[pos])) {
|
|
38475
|
+
if (isStringArg(args[pos])) {
|
|
38476
|
+
const s = getStringValue(args[pos]);
|
|
38477
|
+
if (s === "filled") {
|
|
38478
|
+
filled = true;
|
|
38479
|
+
pos++;
|
|
38480
|
+
} else {
|
|
38481
|
+
const c = resolveColor(s);
|
|
38482
|
+
if (c) {
|
|
38483
|
+
trace.color = c;
|
|
38484
|
+
pos++;
|
|
38485
|
+
} else {
|
|
38486
|
+
const spec = parseLineSpec(s);
|
|
38487
|
+
if (spec?.marker) {
|
|
38488
|
+
trace.marker = spec.marker;
|
|
38489
|
+
if (spec.color) trace.color = COLOR_SHORT[spec.color];
|
|
38490
|
+
pos++;
|
|
38491
|
+
}
|
|
38492
|
+
}
|
|
38493
|
+
}
|
|
38494
|
+
} else if (isNumericArg(args[pos])) {
|
|
38495
|
+
const c = resolveColor(args[pos]);
|
|
38496
|
+
if (c) {
|
|
38497
|
+
trace.color = c;
|
|
38498
|
+
pos++;
|
|
38499
|
+
}
|
|
38500
|
+
}
|
|
38501
|
+
}
|
|
38502
|
+
while (pos < args.length && isStringArg(args[pos]) && !isNameValueKey(args[pos])) {
|
|
38503
|
+
const s = getStringValue(args[pos]);
|
|
38504
|
+
if (s === "filled") {
|
|
38505
|
+
filled = true;
|
|
38506
|
+
pos++;
|
|
38507
|
+
} else {
|
|
38508
|
+
const spec = parseLineSpec(s);
|
|
38509
|
+
if (spec?.marker) {
|
|
38510
|
+
trace.marker = spec.marker;
|
|
38511
|
+
if (spec.color) trace.color = COLOR_SHORT[spec.color];
|
|
38512
|
+
pos++;
|
|
38513
|
+
} else {
|
|
38514
|
+
break;
|
|
38515
|
+
}
|
|
38516
|
+
}
|
|
38517
|
+
}
|
|
38518
|
+
if (filled) {
|
|
38519
|
+
trace.markerFaceColor = trace.color || [0, 0, 1];
|
|
38520
|
+
}
|
|
38521
|
+
while (pos < args.length) {
|
|
38522
|
+
const key = isNameValueKey(args[pos]);
|
|
38523
|
+
if (!key) break;
|
|
38524
|
+
pos++;
|
|
38525
|
+
if (pos >= args.length) break;
|
|
38526
|
+
const value = args[pos];
|
|
38527
|
+
pos++;
|
|
38528
|
+
applyNameValue([trace], key, value);
|
|
38529
|
+
}
|
|
38530
|
+
return [trace];
|
|
38531
|
+
}
|
|
38241
38532
|
function applyNameValue(traces, key, value) {
|
|
38242
38533
|
switch (key) {
|
|
38243
38534
|
case "color": {
|
|
@@ -38282,6 +38573,95 @@ function applyNameValue(traces, key, value) {
|
|
|
38282
38573
|
}
|
|
38283
38574
|
}
|
|
38284
38575
|
}
|
|
38576
|
+
function parseImagescArgs(args) {
|
|
38577
|
+
if (args.length === 1) {
|
|
38578
|
+
const info = getMatrixInfo(args[0]);
|
|
38579
|
+
return {
|
|
38580
|
+
x: [1, info.cols],
|
|
38581
|
+
y: [1, info.rows],
|
|
38582
|
+
z: info.data,
|
|
38583
|
+
rows: info.rows,
|
|
38584
|
+
cols: info.cols
|
|
38585
|
+
};
|
|
38586
|
+
}
|
|
38587
|
+
if (args.length >= 3) {
|
|
38588
|
+
const xArr = toNumberArray(args[0]);
|
|
38589
|
+
const yArr = toNumberArray(args[1]);
|
|
38590
|
+
const info = getMatrixInfo(args[2]);
|
|
38591
|
+
return {
|
|
38592
|
+
x: [xArr[0], xArr[xArr.length - 1]],
|
|
38593
|
+
y: [yArr[0], yArr[yArr.length - 1]],
|
|
38594
|
+
z: info.data,
|
|
38595
|
+
rows: info.rows,
|
|
38596
|
+
cols: info.cols
|
|
38597
|
+
};
|
|
38598
|
+
}
|
|
38599
|
+
throw new Error("imagesc requires 1 or 3+ arguments");
|
|
38600
|
+
}
|
|
38601
|
+
function parseContourArgs(args, filled) {
|
|
38602
|
+
let pos = 0;
|
|
38603
|
+
let numericCount = 0;
|
|
38604
|
+
for (let i = pos; i < args.length; i++) {
|
|
38605
|
+
if (isNumericArg(args[i])) numericCount++;
|
|
38606
|
+
else break;
|
|
38607
|
+
}
|
|
38608
|
+
let xData;
|
|
38609
|
+
let yData;
|
|
38610
|
+
let zData;
|
|
38611
|
+
let rows;
|
|
38612
|
+
let cols;
|
|
38613
|
+
let nLevels = 10;
|
|
38614
|
+
if (numericCount === 1) {
|
|
38615
|
+
const info = getMatrixInfo(args[pos++]);
|
|
38616
|
+
rows = info.rows;
|
|
38617
|
+
cols = info.cols;
|
|
38618
|
+
zData = info.data;
|
|
38619
|
+
const gen = generateMeshgrid(rows, cols);
|
|
38620
|
+
xData = gen.x;
|
|
38621
|
+
yData = gen.y;
|
|
38622
|
+
} else if (numericCount === 2) {
|
|
38623
|
+
const info = getMatrixInfo(args[pos++]);
|
|
38624
|
+
rows = info.rows;
|
|
38625
|
+
cols = info.cols;
|
|
38626
|
+
zData = info.data;
|
|
38627
|
+
nLevels = typeof args[pos] === "number" ? args[pos] : toNumber(args[pos]);
|
|
38628
|
+
pos++;
|
|
38629
|
+
const gen = generateMeshgrid(rows, cols);
|
|
38630
|
+
xData = gen.x;
|
|
38631
|
+
yData = gen.y;
|
|
38632
|
+
} else if (numericCount === 3) {
|
|
38633
|
+
const x = args[pos++];
|
|
38634
|
+
const y = args[pos++];
|
|
38635
|
+
const zInfo = getMatrixInfo(args[pos++]);
|
|
38636
|
+
rows = zInfo.rows;
|
|
38637
|
+
cols = zInfo.cols;
|
|
38638
|
+
zData = zInfo.data;
|
|
38639
|
+
const expanded = expandXY(x, y, rows, cols);
|
|
38640
|
+
xData = expanded.x;
|
|
38641
|
+
yData = expanded.y;
|
|
38642
|
+
} else if (numericCount >= 4) {
|
|
38643
|
+
const x = args[pos++];
|
|
38644
|
+
const y = args[pos++];
|
|
38645
|
+
const zInfo = getMatrixInfo(args[pos++]);
|
|
38646
|
+
rows = zInfo.rows;
|
|
38647
|
+
cols = zInfo.cols;
|
|
38648
|
+
zData = zInfo.data;
|
|
38649
|
+
nLevels = typeof args[pos] === "number" ? args[pos] : toNumber(args[pos]);
|
|
38650
|
+
pos++;
|
|
38651
|
+
const expanded = expandXY(x, y, rows, cols);
|
|
38652
|
+
xData = expanded.x;
|
|
38653
|
+
yData = expanded.y;
|
|
38654
|
+
} else {
|
|
38655
|
+
throw new Error("contour requires at least 1 argument");
|
|
38656
|
+
}
|
|
38657
|
+
return { x: xData, y: yData, z: zData, rows, cols, nLevels, filled };
|
|
38658
|
+
}
|
|
38659
|
+
function parseMeshArgs(args) {
|
|
38660
|
+
const trace = parseSurfArgs(args);
|
|
38661
|
+
if (!trace.edgeColor) trace.edgeColor = "flat";
|
|
38662
|
+
if (!trace.faceColor) trace.faceColor = "none";
|
|
38663
|
+
return trace;
|
|
38664
|
+
}
|
|
38285
38665
|
|
|
38286
38666
|
// src/numbl-core/runtime/syncChannel.ts
|
|
38287
38667
|
var syncSleepWarned = false;
|
|
@@ -38307,10 +38687,17 @@ function syncSleep(ms) {
|
|
|
38307
38687
|
// src/numbl-core/runtime/runtimePlot.ts
|
|
38308
38688
|
function plotInstr(plotInstructions, instr) {
|
|
38309
38689
|
if (instr.type === "set_figure_handle") {
|
|
38310
|
-
|
|
38311
|
-
|
|
38312
|
-
handle
|
|
38313
|
-
}
|
|
38690
|
+
let handle;
|
|
38691
|
+
if (typeof instr.handle === "number") {
|
|
38692
|
+
handle = instr.handle;
|
|
38693
|
+
} else {
|
|
38694
|
+
try {
|
|
38695
|
+
handle = toNumber(ensureRuntimeValue(instr.handle));
|
|
38696
|
+
} catch {
|
|
38697
|
+
handle = 1;
|
|
38698
|
+
}
|
|
38699
|
+
}
|
|
38700
|
+
plotInstructions.push({ type: "set_figure_handle", handle });
|
|
38314
38701
|
} else if (instr.type === "plot") {
|
|
38315
38702
|
plotInstructions.push({
|
|
38316
38703
|
type: "plot",
|
|
@@ -38349,7 +38736,63 @@ function plotInstr(plotInstructions, instr) {
|
|
|
38349
38736
|
plotInstructions.push({ type: "close_all" });
|
|
38350
38737
|
} else if (instr.type === "clf") {
|
|
38351
38738
|
plotInstructions.push({ type: "clf" });
|
|
38739
|
+
} else if (instr.type === "set_subplot") {
|
|
38740
|
+
const rows = typeof instr.rows === "number" ? instr.rows : toNumber(ensureRuntimeValue(instr.rows));
|
|
38741
|
+
const cols = typeof instr.cols === "number" ? instr.cols : toNumber(ensureRuntimeValue(instr.cols));
|
|
38742
|
+
const index2 = typeof instr.index === "number" ? instr.index : toNumber(ensureRuntimeValue(instr.index));
|
|
38743
|
+
plotInstructions.push({ type: "set_subplot", rows, cols, index: index2 });
|
|
38744
|
+
} else if (instr.type === "set_sgtitle") {
|
|
38745
|
+
const text = typeof instr.text === "string" ? instr.text : toString(ensureRuntimeValue(instr.text));
|
|
38746
|
+
plotInstructions.push({ type: "set_sgtitle", text });
|
|
38747
|
+
} else if (instr.type === "set_grid") {
|
|
38748
|
+
const val = instr.value;
|
|
38749
|
+
let on;
|
|
38750
|
+
if (typeof val === "string") on = val === "on";
|
|
38751
|
+
else if (typeof val === "boolean") on = val;
|
|
38752
|
+
else {
|
|
38753
|
+
const mv = ensureRuntimeValue(val);
|
|
38754
|
+
on = toString(mv) === "on";
|
|
38755
|
+
}
|
|
38756
|
+
plotInstructions.push({ type: "set_grid", value: on });
|
|
38757
|
+
} else if (instr.type === "set_zlabel") {
|
|
38758
|
+
const text = typeof instr.text === "string" ? instr.text : toString(ensureRuntimeValue(instr.text));
|
|
38759
|
+
plotInstructions.push({ type: "set_zlabel", text });
|
|
38760
|
+
} else if (instr.type === "set_colorbar") {
|
|
38761
|
+
const val = typeof instr.value === "string" ? instr.value : toString(ensureRuntimeValue(instr.value));
|
|
38762
|
+
plotInstructions.push({ type: "set_colorbar", value: val });
|
|
38763
|
+
} else if (instr.type === "set_colormap") {
|
|
38764
|
+
const name = typeof instr.name === "string" ? instr.name : toString(ensureRuntimeValue(instr.name));
|
|
38765
|
+
plotInstructions.push({
|
|
38766
|
+
type: "set_colormap",
|
|
38767
|
+
name: name.replace(/^"|"$/g, "")
|
|
38768
|
+
});
|
|
38769
|
+
} else if (instr.type === "set_axis") {
|
|
38770
|
+
const val = typeof instr.value === "string" ? instr.value : toString(ensureRuntimeValue(instr.value));
|
|
38771
|
+
plotInstructions.push({
|
|
38772
|
+
type: "set_axis",
|
|
38773
|
+
value: val.replace(/^"|"$/g, "")
|
|
38774
|
+
});
|
|
38775
|
+
}
|
|
38776
|
+
}
|
|
38777
|
+
function viewCall(plotInstructions, args) {
|
|
38778
|
+
let az;
|
|
38779
|
+
let el;
|
|
38780
|
+
if (args.length === 1) {
|
|
38781
|
+
const n = typeof args[0] === "number" ? args[0] : toNumber(args[0]);
|
|
38782
|
+
if (n === 2) {
|
|
38783
|
+
az = 0;
|
|
38784
|
+
el = 90;
|
|
38785
|
+
} else {
|
|
38786
|
+
az = -37.5;
|
|
38787
|
+
el = 30;
|
|
38788
|
+
}
|
|
38789
|
+
} else if (args.length >= 2) {
|
|
38790
|
+
az = typeof args[0] === "number" ? args[0] : toNumber(args[0]);
|
|
38791
|
+
el = typeof args[1] === "number" ? args[1] : toNumber(args[1]);
|
|
38792
|
+
} else {
|
|
38793
|
+
return;
|
|
38352
38794
|
}
|
|
38795
|
+
plotInstructions.push({ type: "set_view", az, el });
|
|
38353
38796
|
}
|
|
38354
38797
|
function plotCall(plotInstructions, args) {
|
|
38355
38798
|
const traces = parsePlotArgs(args);
|
|
@@ -38367,6 +38810,38 @@ function surfCall(plotInstructions, args) {
|
|
|
38367
38810
|
const trace = parseSurfArgs(args);
|
|
38368
38811
|
plotInstructions.push({ type: "surf", trace });
|
|
38369
38812
|
}
|
|
38813
|
+
function imagescCall(plotInstructions, args) {
|
|
38814
|
+
const trace = parseImagescArgs(args);
|
|
38815
|
+
plotInstructions.push({ type: "imagesc", trace });
|
|
38816
|
+
}
|
|
38817
|
+
function contourCall(plotInstructions, args, filled) {
|
|
38818
|
+
const trace = parseContourArgs(args, filled);
|
|
38819
|
+
plotInstructions.push({ type: "contour", trace });
|
|
38820
|
+
}
|
|
38821
|
+
function meshCall(plotInstructions, args) {
|
|
38822
|
+
const trace = parseMeshArgs(args);
|
|
38823
|
+
plotInstructions.push({ type: "mesh", trace });
|
|
38824
|
+
}
|
|
38825
|
+
function scatterCall(plotInstructions, args) {
|
|
38826
|
+
const traces = parseScatterArgs(args);
|
|
38827
|
+
if (traces.length > 0) {
|
|
38828
|
+
plotInstructions.push({ type: "plot", traces });
|
|
38829
|
+
}
|
|
38830
|
+
}
|
|
38831
|
+
function legendCall(plotInstructions, args) {
|
|
38832
|
+
const labels = [];
|
|
38833
|
+
for (let i = 0; i < args.length; i++) {
|
|
38834
|
+
const s = toString(args[i]);
|
|
38835
|
+
if (s === "Location" || s === "Orientation" || s === "FontSize" || s === "Box" || s === "Color" || s === "EdgeColor" || s === "TextColor") {
|
|
38836
|
+
i++;
|
|
38837
|
+
continue;
|
|
38838
|
+
}
|
|
38839
|
+
labels.push(s);
|
|
38840
|
+
}
|
|
38841
|
+
if (labels.length > 0) {
|
|
38842
|
+
plotInstructions.push({ type: "set_legend", labels });
|
|
38843
|
+
}
|
|
38844
|
+
}
|
|
38370
38845
|
function drawnow(plotInstructions, options) {
|
|
38371
38846
|
if (options.onDrawnow && plotInstructions.length > 0) {
|
|
38372
38847
|
options.onDrawnow([...plotInstructions]);
|
|
@@ -38475,6 +38950,61 @@ var Runtime = class _Runtime {
|
|
|
38475
38950
|
this.builtins["surf"] = (_nargout, args) => {
|
|
38476
38951
|
this.surf_call(args.map((a) => ensureRuntimeValue(a)));
|
|
38477
38952
|
};
|
|
38953
|
+
this.builtins["scatter"] = (_nargout, args) => {
|
|
38954
|
+
this.scatter_call(args.map((a) => ensureRuntimeValue(a)));
|
|
38955
|
+
};
|
|
38956
|
+
this.builtins["imagesc"] = (_nargout, args) => {
|
|
38957
|
+
this.imagesc_call(args.map((a) => ensureRuntimeValue(a)));
|
|
38958
|
+
};
|
|
38959
|
+
this.builtins["contour"] = (_nargout, args) => {
|
|
38960
|
+
this.contour_call(
|
|
38961
|
+
args.map((a) => ensureRuntimeValue(a)),
|
|
38962
|
+
false
|
|
38963
|
+
);
|
|
38964
|
+
};
|
|
38965
|
+
this.builtins["contourf"] = (_nargout, args) => {
|
|
38966
|
+
this.contour_call(
|
|
38967
|
+
args.map((a) => ensureRuntimeValue(a)),
|
|
38968
|
+
true
|
|
38969
|
+
);
|
|
38970
|
+
};
|
|
38971
|
+
this.builtins["mesh"] = (_nargout, args) => {
|
|
38972
|
+
this.mesh_call(args.map((a) => ensureRuntimeValue(a)));
|
|
38973
|
+
};
|
|
38974
|
+
this.builtins["waterfall"] = (_nargout, args) => {
|
|
38975
|
+
this.mesh_call(args.map((a) => ensureRuntimeValue(a)));
|
|
38976
|
+
};
|
|
38977
|
+
this.builtins["colormap"] = (_nargout, args) => {
|
|
38978
|
+
if (args.length > 0) {
|
|
38979
|
+
const rv = ensureRuntimeValue(args[0]);
|
|
38980
|
+
const name = toString(rv).replace(/^"|"$/g, "");
|
|
38981
|
+
plotInstr(this.plotInstructions, { type: "set_colormap", name });
|
|
38982
|
+
}
|
|
38983
|
+
};
|
|
38984
|
+
this.builtins["view"] = (_nargout, args) => {
|
|
38985
|
+
this.view_call(args.map((a) => ensureRuntimeValue(a)));
|
|
38986
|
+
};
|
|
38987
|
+
this.builtins["zlabel"] = (_nargout, args) => {
|
|
38988
|
+
if (args.length > 0) {
|
|
38989
|
+
plotInstr(this.plotInstructions, {
|
|
38990
|
+
type: "set_zlabel",
|
|
38991
|
+
text: args[0]
|
|
38992
|
+
});
|
|
38993
|
+
}
|
|
38994
|
+
};
|
|
38995
|
+
this.builtins["colorbar"] = (_nargout, args) => {
|
|
38996
|
+
const val = args.length > 0 ? toString(ensureRuntimeValue(args[0])) : "on";
|
|
38997
|
+
plotInstr(this.plotInstructions, { type: "set_colorbar", value: val });
|
|
38998
|
+
};
|
|
38999
|
+
this.builtins["axis"] = (_nargout, args) => {
|
|
39000
|
+
if (args.length > 0) {
|
|
39001
|
+
const val = toString(ensureRuntimeValue(args[0])).replace(
|
|
39002
|
+
/^"|"$/g,
|
|
39003
|
+
""
|
|
39004
|
+
);
|
|
39005
|
+
plotInstr(this.plotInstructions, { type: "set_axis", value: val });
|
|
39006
|
+
}
|
|
39007
|
+
};
|
|
38478
39008
|
}
|
|
38479
39009
|
profileEnter(key) {
|
|
38480
39010
|
if (!this.profilingEnabled) return;
|
|
@@ -39065,6 +39595,24 @@ var Runtime = class _Runtime {
|
|
|
39065
39595
|
surf_call(args) {
|
|
39066
39596
|
surfCall(this.plotInstructions, args);
|
|
39067
39597
|
}
|
|
39598
|
+
scatter_call(args) {
|
|
39599
|
+
scatterCall(this.plotInstructions, args);
|
|
39600
|
+
}
|
|
39601
|
+
imagesc_call(args) {
|
|
39602
|
+
imagescCall(this.plotInstructions, args);
|
|
39603
|
+
}
|
|
39604
|
+
contour_call(args, filled) {
|
|
39605
|
+
contourCall(this.plotInstructions, args, filled);
|
|
39606
|
+
}
|
|
39607
|
+
mesh_call(args) {
|
|
39608
|
+
meshCall(this.plotInstructions, args);
|
|
39609
|
+
}
|
|
39610
|
+
view_call(args) {
|
|
39611
|
+
viewCall(this.plotInstructions, args);
|
|
39612
|
+
}
|
|
39613
|
+
legend_call(args) {
|
|
39614
|
+
legendCall(this.plotInstructions, args);
|
|
39615
|
+
}
|
|
39068
39616
|
// ── Drawnow / Pause ─────────────────────────────────────────────────
|
|
39069
39617
|
drawnow() {
|
|
39070
39618
|
return drawnow(this.plotInstructions, this.options);
|
|
@@ -40637,13 +41185,6 @@ var LoweringContext = class _LoweringContext {
|
|
|
40637
41185
|
}
|
|
40638
41186
|
for (const [className, group] of classFolderGroups) {
|
|
40639
41187
|
if (!group.classDefFile) {
|
|
40640
|
-
for (const mf of group.methodFiles) {
|
|
40641
|
-
const baseName = mf.name.split("/").pop().replace(/\.m$/, "");
|
|
40642
|
-
this.registry.filesByFuncName.set(baseName, {
|
|
40643
|
-
fileName: mf.name,
|
|
40644
|
-
source: mf.source
|
|
40645
|
-
});
|
|
40646
|
-
}
|
|
40647
41188
|
continue;
|
|
40648
41189
|
}
|
|
40649
41190
|
this.registerWorkspaceClass(className, group.classDefFile);
|
|
@@ -40778,7 +41319,9 @@ var LoweringContext = class _LoweringContext {
|
|
|
40778
41319
|
file.name,
|
|
40779
41320
|
file.source
|
|
40780
41321
|
);
|
|
40781
|
-
this.registry.classesByName.
|
|
41322
|
+
if (!this.registry.classesByName.has(qualifiedName)) {
|
|
41323
|
+
this.registry.classesByName.set(qualifiedName, info);
|
|
41324
|
+
}
|
|
40782
41325
|
}
|
|
40783
41326
|
/**
|
|
40784
41327
|
* Register a classdef statement found in the local (main) file.
|
|
@@ -41895,6 +42438,22 @@ function genFuncCall(cg, kind) {
|
|
|
41895
42438
|
}
|
|
41896
42439
|
return `$rt.plot_instr({type: "close"})`;
|
|
41897
42440
|
}
|
|
42441
|
+
if (kind.name === "subplot")
|
|
42442
|
+
return `$rt.plot_instr({type: "set_subplot", rows: ${args[0] ?? "1"}, cols: ${args[1] ?? "1"}, index: ${args[2] ?? "1"}})`;
|
|
42443
|
+
if (kind.name === "legend") return `$rt.legend_call([${args.join(", ")}])`;
|
|
42444
|
+
if (kind.name === "sgtitle")
|
|
42445
|
+
return `$rt.plot_instr({type: "set_sgtitle", text: ${args[0] ?? '""'}})`;
|
|
42446
|
+
if (kind.name === "grid")
|
|
42447
|
+
return `$rt.plot_instr({type: "set_grid", value: ${args[0] ?? "true"}})`;
|
|
42448
|
+
if (kind.name === "zlabel")
|
|
42449
|
+
return `$rt.plot_instr({type: "set_zlabel", text: ${args[0] ?? '""'}})`;
|
|
42450
|
+
if (kind.name === "colorbar")
|
|
42451
|
+
return `$rt.plot_instr({type: "set_colorbar", value: ${args[0] ?? '"on"'}})`;
|
|
42452
|
+
if (kind.name === "colormap")
|
|
42453
|
+
return `$rt.plot_instr({type: "set_colormap", name: ${args[0] ?? '"parula"'}})`;
|
|
42454
|
+
if (kind.name === "axis")
|
|
42455
|
+
return `$rt.plot_instr({type: "set_axis", value: ${args[0] ?? '"auto"'}})`;
|
|
42456
|
+
if (kind.name === "view") return `$rt.view_call([${args.join(", ")}])`;
|
|
41898
42457
|
if (cg.nestedFunctionNames.has(kind.name)) {
|
|
41899
42458
|
return buildSpecializedCall(
|
|
41900
42459
|
cg,
|
|
@@ -43626,9 +44185,28 @@ function buildWasmMap(wasmFiles) {
|
|
|
43626
44185
|
}
|
|
43627
44186
|
return map;
|
|
43628
44187
|
}
|
|
43629
|
-
function
|
|
43630
|
-
const
|
|
43631
|
-
|
|
44188
|
+
function parseDirectives(source) {
|
|
44189
|
+
const directives = {};
|
|
44190
|
+
const lines = source.split("\n");
|
|
44191
|
+
for (const line of lines) {
|
|
44192
|
+
const match = line.match(/^\s*\/\/\s*(\w+):\s*(\S+)/);
|
|
44193
|
+
if (!match) break;
|
|
44194
|
+
const key = match[1];
|
|
44195
|
+
const value = match[2];
|
|
44196
|
+
if (key === "wasm") directives.wasm = value;
|
|
44197
|
+
else if (key === "native") directives.native = value;
|
|
44198
|
+
}
|
|
44199
|
+
return directives;
|
|
44200
|
+
}
|
|
44201
|
+
function nativeLibFilename(baseName) {
|
|
44202
|
+
switch (process.platform) {
|
|
44203
|
+
case "win32":
|
|
44204
|
+
return `${baseName}.dll`;
|
|
44205
|
+
case "darwin":
|
|
44206
|
+
return `${baseName}.dylib`;
|
|
44207
|
+
default:
|
|
44208
|
+
return `${baseName}.so`;
|
|
44209
|
+
}
|
|
43632
44210
|
}
|
|
43633
44211
|
function instantiateWasm(wasmData) {
|
|
43634
44212
|
const wasmModule = new WebAssembly.Module(wasmData);
|
|
@@ -43659,7 +44237,7 @@ function instantiateWasm(wasmData) {
|
|
|
43659
44237
|
}
|
|
43660
44238
|
return new WebAssembly.Instance(wasmModule, importObject);
|
|
43661
44239
|
}
|
|
43662
|
-
function loadJsUserFunctions(jsFiles, wasmFiles) {
|
|
44240
|
+
function loadJsUserFunctions(jsFiles, wasmFiles, nativeBridge2) {
|
|
43663
44241
|
const result = /* @__PURE__ */ new Map();
|
|
43664
44242
|
const wasmMap = wasmFiles ? buildWasmMap(wasmFiles) : /* @__PURE__ */ new Map();
|
|
43665
44243
|
const wasmInstanceCache = /* @__PURE__ */ new Map();
|
|
@@ -43667,7 +44245,7 @@ function loadJsUserFunctions(jsFiles, wasmFiles) {
|
|
|
43667
44245
|
const cached = wasmInstanceCache.get(name);
|
|
43668
44246
|
if (cached) return cached;
|
|
43669
44247
|
const data = wasmMap.get(name);
|
|
43670
|
-
if (!data) return
|
|
44248
|
+
if (!data) return void 0;
|
|
43671
44249
|
const instance = instantiateWasm(data);
|
|
43672
44250
|
wasmInstanceCache.set(name, instance);
|
|
43673
44251
|
return instance;
|
|
@@ -43685,8 +44263,18 @@ function loadJsUserFunctions(jsFiles, wasmFiles) {
|
|
|
43685
44263
|
apply: branch.apply
|
|
43686
44264
|
});
|
|
43687
44265
|
};
|
|
43688
|
-
const
|
|
43689
|
-
const wasmInstance = getWasmInstance(
|
|
44266
|
+
const directives = parseDirectives(file.source);
|
|
44267
|
+
const wasmInstance = directives.wasm ? getWasmInstance(directives.wasm) : void 0;
|
|
44268
|
+
let nativeLib;
|
|
44269
|
+
if (directives.native && nativeBridge2) {
|
|
44270
|
+
const libFile = nativeLibFilename(directives.native);
|
|
44271
|
+
const dir = file.name.substring(0, file.name.lastIndexOf("/") + 1);
|
|
44272
|
+
const libPath = dir + libFile;
|
|
44273
|
+
try {
|
|
44274
|
+
nativeLib = nativeBridge2.load(libPath);
|
|
44275
|
+
} catch {
|
|
44276
|
+
}
|
|
44277
|
+
}
|
|
43690
44278
|
const factory = new Function(
|
|
43691
44279
|
"RTV",
|
|
43692
44280
|
"RuntimeError",
|
|
@@ -43694,14 +44282,44 @@ function loadJsUserFunctions(jsFiles, wasmFiles) {
|
|
|
43694
44282
|
"IType",
|
|
43695
44283
|
"register",
|
|
43696
44284
|
"wasm",
|
|
44285
|
+
"native",
|
|
43697
44286
|
file.source
|
|
43698
44287
|
);
|
|
43699
|
-
factory(
|
|
44288
|
+
factory(
|
|
44289
|
+
RTV,
|
|
44290
|
+
RuntimeError,
|
|
44291
|
+
FloatXArray,
|
|
44292
|
+
IType,
|
|
44293
|
+
registerFn,
|
|
44294
|
+
wasmInstance,
|
|
44295
|
+
nativeLib
|
|
44296
|
+
);
|
|
43700
44297
|
if (branches.length === 0) {
|
|
43701
44298
|
throw new Error(
|
|
43702
44299
|
`JS user function '${funcName}' (${file.name}) must call register() at least once`
|
|
43703
44300
|
);
|
|
43704
44301
|
}
|
|
44302
|
+
if (directives.native || directives.wasm) {
|
|
44303
|
+
const parts = [];
|
|
44304
|
+
if (directives.native) {
|
|
44305
|
+
parts.push(nativeLib ? "native: loaded" : "native: not found");
|
|
44306
|
+
}
|
|
44307
|
+
if (directives.wasm) {
|
|
44308
|
+
parts.push(wasmInstance ? "wasm: loaded" : "wasm: not found");
|
|
44309
|
+
}
|
|
44310
|
+
const statusMsg = `${funcName}: ${parts.join(", ")}`;
|
|
44311
|
+
let logged = false;
|
|
44312
|
+
for (const branch of branches) {
|
|
44313
|
+
const origApply = branch.apply;
|
|
44314
|
+
branch.apply = (...applyArgs) => {
|
|
44315
|
+
if (!logged) {
|
|
44316
|
+
logged = true;
|
|
44317
|
+
console.log(statusMsg);
|
|
44318
|
+
}
|
|
44319
|
+
return origApply(...applyArgs);
|
|
44320
|
+
};
|
|
44321
|
+
}
|
|
44322
|
+
}
|
|
43705
44323
|
result.set(funcName, branches);
|
|
43706
44324
|
} catch (e) {
|
|
43707
44325
|
const msg = e instanceof Error ? e.message : String(e);
|
|
@@ -43817,7 +44435,8 @@ function generateMainScriptCode(source, mainFileName = "script.m", workspaceFile
|
|
|
43817
44435
|
_t0 = performance.now();
|
|
43818
44436
|
const jsUserFunctions = loadJsUserFunctions(
|
|
43819
44437
|
jsWorkspaceFiles,
|
|
43820
|
-
wasmWorkspaceFiles
|
|
44438
|
+
wasmWorkspaceFiles,
|
|
44439
|
+
opts?.nativeBridge
|
|
43821
44440
|
);
|
|
43822
44441
|
const _loadJsUserFunctionsMs = performance.now() - _t0;
|
|
43823
44442
|
_t0 = performance.now();
|
|
@@ -43959,7 +44578,7 @@ function generateMainScriptCode(source, mainFileName = "script.m", workspaceFile
|
|
|
43959
44578
|
}
|
|
43960
44579
|
|
|
43961
44580
|
// src/numbl-core/executeCode.ts
|
|
43962
|
-
function executeCode(source, options = {}, workspaceFiles, mainFileName = "script.m", searchPaths) {
|
|
44581
|
+
function executeCode(source, options = {}, workspaceFiles, mainFileName = "script.m", searchPaths, nativeBridge2) {
|
|
43963
44582
|
const initialVariableNames = options.initialVariableValues ? Object.keys(options.initialVariableValues) : void 0;
|
|
43964
44583
|
const codegenStart = performance.now();
|
|
43965
44584
|
const {
|
|
@@ -43983,7 +44602,7 @@ function executeCode(source, options = {}, workspaceFiles, mainFileName = "scrip
|
|
|
43983
44602
|
workspaceFiles,
|
|
43984
44603
|
initialVariableNames,
|
|
43985
44604
|
searchPaths,
|
|
43986
|
-
{ noLineTracking: options.noLineTracking }
|
|
44605
|
+
{ noLineTracking: options.noLineTracking, nativeBridge: nativeBridge2 }
|
|
43987
44606
|
);
|
|
43988
44607
|
const codegenTimeMs = performance.now() - codegenStart;
|
|
43989
44608
|
if (options.log) {
|
|
@@ -44126,7 +44745,7 @@ function processMipLoad(packageName, _visited) {
|
|
|
44126
44745
|
if (visited.has(packageName)) return [];
|
|
44127
44746
|
visited.add(packageName);
|
|
44128
44747
|
const mipDir = process.env.MIP_DIR || join3(homedir2(), ".mip");
|
|
44129
|
-
const pkgDir = join3(mipDir, "
|
|
44748
|
+
const pkgDir = join3(mipDir, "numbl_packages", packageName);
|
|
44130
44749
|
const loadScript = join3(pkgDir, "load_package.m");
|
|
44131
44750
|
if (!existsSync3(loadScript)) {
|
|
44132
44751
|
throw new Error(
|
|
@@ -44140,7 +44759,7 @@ function processMipLoad(packageName, _visited) {
|
|
|
44140
44759
|
const mipJson = JSON.parse(readFileSync3(mipJsonPath, "utf-8"));
|
|
44141
44760
|
const deps = mipJson.dependencies ?? [];
|
|
44142
44761
|
for (const dep of deps) {
|
|
44143
|
-
const depPkgDir = join3(mipDir, "
|
|
44762
|
+
const depPkgDir = join3(mipDir, "numbl_packages", dep);
|
|
44144
44763
|
if (!existsSync3(depPkgDir)) {
|
|
44145
44764
|
console.warn(
|
|
44146
44765
|
`Warning: dependency "${dep}" of "${packageName}" is not installed; skipping`
|
|
@@ -44380,7 +44999,7 @@ function saveHistoryEntry(entry, hist) {
|
|
|
44380
44999
|
} catch {
|
|
44381
45000
|
}
|
|
44382
45001
|
}
|
|
44383
|
-
async function runRepl(initialWorkspaceFiles, onDrawnow, initialSearchPaths) {
|
|
45002
|
+
async function runRepl(initialWorkspaceFiles, onDrawnow, initialSearchPaths, nativeBridge2) {
|
|
44384
45003
|
let variableValues = {};
|
|
44385
45004
|
let holdState = false;
|
|
44386
45005
|
const workspaceFiles = [...initialWorkspaceFiles];
|
|
@@ -44439,7 +45058,8 @@ async function runRepl(initialWorkspaceFiles, onDrawnow, initialSearchPaths) {
|
|
|
44439
45058
|
},
|
|
44440
45059
|
workspaceFiles,
|
|
44441
45060
|
"repl",
|
|
44442
|
-
searchPaths
|
|
45061
|
+
searchPaths,
|
|
45062
|
+
nativeBridge2
|
|
44443
45063
|
);
|
|
44444
45064
|
variableValues = result.variableValues;
|
|
44445
45065
|
holdState = result.holdState;
|
|
@@ -44547,7 +45167,8 @@ async function runRepl(initialWorkspaceFiles, onDrawnow, initialSearchPaths) {
|
|
|
44547
45167
|
},
|
|
44548
45168
|
workspaceFiles,
|
|
44549
45169
|
"repl",
|
|
44550
|
-
searchPaths
|
|
45170
|
+
searchPaths,
|
|
45171
|
+
nativeBridge2
|
|
44551
45172
|
);
|
|
44552
45173
|
variableValues = result.variableValues;
|
|
44553
45174
|
holdState = result.holdState;
|
|
@@ -44989,15 +45610,27 @@ try {
|
|
|
44989
45610
|
nativeAddonLoaded = true;
|
|
44990
45611
|
} catch {
|
|
44991
45612
|
}
|
|
45613
|
+
var nativeBridge;
|
|
45614
|
+
try {
|
|
45615
|
+
const req = createRequire(import.meta.url);
|
|
45616
|
+
const koffi = req("koffi");
|
|
45617
|
+
nativeBridge = { load: (path) => koffi.load(path) };
|
|
45618
|
+
} catch {
|
|
45619
|
+
}
|
|
44992
45620
|
function scanMFiles(dirPath, excludeFile) {
|
|
44993
45621
|
const files = [];
|
|
45622
|
+
let entries;
|
|
44994
45623
|
try {
|
|
44995
|
-
|
|
44996
|
-
|
|
44997
|
-
|
|
44998
|
-
|
|
44999
|
-
|
|
45000
|
-
|
|
45624
|
+
entries = readdirSync2(dirPath);
|
|
45625
|
+
} catch {
|
|
45626
|
+
return files;
|
|
45627
|
+
}
|
|
45628
|
+
for (const entry of entries) {
|
|
45629
|
+
const fullPath = join6(dirPath, entry);
|
|
45630
|
+
if (excludeFile && fullPath === excludeFile) {
|
|
45631
|
+
continue;
|
|
45632
|
+
}
|
|
45633
|
+
try {
|
|
45001
45634
|
const stat = statSync2(fullPath);
|
|
45002
45635
|
if (stat.isDirectory()) {
|
|
45003
45636
|
if (entry.startsWith("@") || entry.startsWith("+") || entry === "private") {
|
|
@@ -45017,8 +45650,11 @@ function scanMFiles(dirPath, excludeFile) {
|
|
|
45017
45650
|
data: new Uint8Array(data)
|
|
45018
45651
|
});
|
|
45019
45652
|
}
|
|
45653
|
+
} catch (err) {
|
|
45654
|
+
console.warn(
|
|
45655
|
+
`Warning: could not read ${fullPath}: ${err instanceof Error ? err.message : String(err)}`
|
|
45656
|
+
);
|
|
45020
45657
|
}
|
|
45021
|
-
} catch {
|
|
45022
45658
|
}
|
|
45023
45659
|
return files;
|
|
45024
45660
|
}
|
|
@@ -45078,7 +45714,8 @@ async function runTests(dir) {
|
|
|
45078
45714
|
{ displayResults: true },
|
|
45079
45715
|
workspaceFiles,
|
|
45080
45716
|
mainFileName,
|
|
45081
|
-
searchPaths
|
|
45717
|
+
searchPaths,
|
|
45718
|
+
nativeBridge
|
|
45082
45719
|
);
|
|
45083
45720
|
const outputText = result.output.join("");
|
|
45084
45721
|
const lines = outputText.split("\n").filter((l) => l.length > 0);
|
|
@@ -45377,7 +46014,8 @@ async function executeWithOptions(code, mainFileName, workspaceFiles, opts, sear
|
|
|
45377
46014
|
},
|
|
45378
46015
|
workspaceFiles,
|
|
45379
46016
|
mainFileName,
|
|
45380
|
-
searchPaths
|
|
46017
|
+
searchPaths,
|
|
46018
|
+
nativeBridge
|
|
45381
46019
|
);
|
|
45382
46020
|
if (result.plotInstructions.length > 0) {
|
|
45383
46021
|
streamLine({
|
|
@@ -45425,7 +46063,8 @@ async function executeWithOptions(code, mainFileName, workspaceFiles, opts, sear
|
|
|
45425
46063
|
},
|
|
45426
46064
|
workspaceFiles,
|
|
45427
46065
|
mainFileName,
|
|
45428
|
-
searchPaths
|
|
46066
|
+
searchPaths,
|
|
46067
|
+
nativeBridge
|
|
45429
46068
|
);
|
|
45430
46069
|
writeProfileIfNeeded(result);
|
|
45431
46070
|
if (opts.dumpJs) {
|
|
@@ -45453,7 +46092,8 @@ async function executeWithOptions(code, mainFileName, workspaceFiles, opts, sear
|
|
|
45453
46092
|
},
|
|
45454
46093
|
workspaceFiles,
|
|
45455
46094
|
mainFileName,
|
|
45456
|
-
searchPaths
|
|
46095
|
+
searchPaths,
|
|
46096
|
+
nativeBridge
|
|
45457
46097
|
);
|
|
45458
46098
|
writeProfileIfNeeded(result);
|
|
45459
46099
|
if (opts.dumpJs) {
|
|
@@ -45538,7 +46178,7 @@ async function cmdRepl(args) {
|
|
|
45538
46178
|
!opts.plot,
|
|
45539
46179
|
replPlotOpts
|
|
45540
46180
|
);
|
|
45541
|
-
await runRepl(replFiles, replDrawnow, replSearchPaths);
|
|
46181
|
+
await runRepl(replFiles, replDrawnow, replSearchPaths, nativeBridge);
|
|
45542
46182
|
}
|
|
45543
46183
|
function createPlotHandler(disabled, plotOpts) {
|
|
45544
46184
|
if (disabled) {
|