numbl 0.0.13 → 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
@@ -9,7 +9,7 @@ import {
9
9
  writeFileSync as writeFileSync3,
10
10
  appendFileSync as appendFileSync2
11
11
  } from "fs";
12
- import { delimiter, dirname as dirname3, join as join5, relative, resolve } from "path";
12
+ import { delimiter, dirname as dirname3, join as join6, relative, resolve } from "path";
13
13
  import { fileURLToPath as fileURLToPath2 } from "url";
14
14
  import { createRequire } from "module";
15
15
  import { execSync as execSync2 } from "child_process";
@@ -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 exact = index2.packages.find(
162
- (p) => p.name === packageName && p.architecture === arch
163
- );
164
- if (exact) return exact;
165
- return index2.packages.find(
166
- (p) => p.name === packageName && p.architecture === "any"
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 === "any"
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(`Package "${name}" not found for architecture "${arch}"`);
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}/packages`;
215
+ return `${mipDir}/numbl_packages`;
214
216
  }
215
217
  function packageDir(mipDir, name) {
216
- return `${mipDir}/packages/${name}`;
218
+ return `${mipDir}/numbl_packages/${name}`;
217
219
  }
218
220
  function directlyInstalledPath(mipDir) {
219
- return `${mipDir}/packages/directly_installed.txt`;
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, (aRe, aIm, bRe, bIm) => {
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, (aRe, aIm, bRe, bIm) => {
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
- const node = this.parsePostfix();
20969
- const tok = this.peekToken();
20970
- let op;
20971
- if (tok === 36 /* Caret */) {
20972
- op = "Pow" /* Pow */;
20973
- } else if (tok === 58 /* DotCaret */) {
20974
- op = "ElemPow" /* ElemPow */;
20975
- } else {
20976
- return node;
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);
20977
20989
  }
20978
- this.pos++;
20979
- const rhs = this.parseUnary();
20980
- return this.makeBinary(node, op, rhs);
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);
21008
+ }
21009
+ return this.parsePostfix();
20981
21010
  }
20982
21011
  parsePostfixWithBase(expr) {
20983
21012
  while (true) {
@@ -21437,7 +21466,11 @@ var ExpressionParser = class extends ParserBase {
21437
21466
  const nameSpan = this.spanFrom(nameToken.position, nameToken.end);
21438
21467
  this.pos++;
21439
21468
  this.pos++;
21440
- args.push({ type: "Char", value: `'${nameToken.lexeme}'`, span: nameSpan });
21469
+ args.push({
21470
+ type: "Char",
21471
+ value: `'${nameToken.lexeme}'`,
21472
+ span: nameSpan
21473
+ });
21441
21474
  args.push(this.parseExpr());
21442
21475
  } else {
21443
21476
  args.push(this.parseExpr());
@@ -21556,25 +21589,32 @@ var CommandParser = class extends ExpressionParser {
21556
21589
  }
21557
21590
  return args;
21558
21591
  }
21559
- if (args.length > 1) {
21592
+ if (args.length > 1 && !command.argKind.multiKeyword) {
21560
21593
  throw this.error(
21561
21594
  `'${command.name}' command syntax accepts only one argument`
21562
21595
  );
21563
21596
  }
21564
- const keyword = extractKeyword(args[0]);
21565
- if (!keyword) {
21566
- throw this.error(
21567
- `'${command.name}' command syntax expects a keyword argument`
21568
- );
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);
21569
21611
  }
21570
- if (allowed === void 0 || allowed.some((a) => a.toLowerCase() === keyword.toLowerCase())) {
21571
- const span = args[0].span;
21572
- return [{ type: "String", value: `"${keyword}"`, span }];
21573
- } else {
21574
- throw this.error(
21575
- `'${command.name}' command syntax does not support '${keyword}'`
21576
- );
21612
+ if (keywords.length === 1) {
21613
+ const span2 = args[0].span;
21614
+ return [{ type: "String", value: `"${keywords[0]}"`, span: span2 }];
21577
21615
  }
21616
+ const span = args[0].span;
21617
+ return [{ type: "String", value: `"${keywords.join(" ")}"`, span }];
21578
21618
  }
21579
21619
  return args;
21580
21620
  }
@@ -25093,6 +25133,125 @@ function registerMathFunctions() {
25093
25133
  return buildResult(snArr, cnArr, dnArr, uT.shape);
25094
25134
  })
25095
25135
  );
25136
+ register(
25137
+ "legendre",
25138
+ builtinSingle((args) => {
25139
+ if (args.length < 2 || args.length > 3) {
25140
+ throw new RuntimeError("legendre requires 2 or 3 arguments");
25141
+ }
25142
+ const n = Math.round(toNumber(args[0]));
25143
+ if (n < 0 || !isFinite(n)) {
25144
+ throw new RuntimeError("Degree n must be a non-negative integer");
25145
+ }
25146
+ let normalization = "unnorm";
25147
+ if (args.length === 3) {
25148
+ const normArg = args[2];
25149
+ if (isRuntimeChar(normArg)) {
25150
+ normalization = normArg.value;
25151
+ } else if (typeof normArg === "string") {
25152
+ normalization = normArg;
25153
+ } else {
25154
+ throw new RuntimeError(
25155
+ "Third argument must be a normalization string"
25156
+ );
25157
+ }
25158
+ if (normalization !== "unnorm" && normalization !== "sch" && normalization !== "norm") {
25159
+ throw new RuntimeError(
25160
+ "Normalization must be 'unnorm', 'sch', or 'norm'"
25161
+ );
25162
+ }
25163
+ }
25164
+ const xArg = args[1];
25165
+ let xValues;
25166
+ let xShape;
25167
+ if (isRuntimeNumber(xArg)) {
25168
+ xValues = [xArg];
25169
+ xShape = [1, 1];
25170
+ } else if (isRuntimeLogical(xArg)) {
25171
+ xValues = [xArg ? 1 : 0];
25172
+ xShape = [1, 1];
25173
+ } else if (isRuntimeTensor(xArg)) {
25174
+ const t = xArg;
25175
+ xValues = Array.from(t.data);
25176
+ xShape = t.shape;
25177
+ } else {
25178
+ throw new RuntimeError("X must be a numeric value");
25179
+ }
25180
+ const numX = xValues.length;
25181
+ const numOrders = n + 1;
25182
+ const outSize = numOrders * numX;
25183
+ const result = new FloatXArray(outSize);
25184
+ for (let xi = 0; xi < numX; xi++) {
25185
+ const x = xValues[xi];
25186
+ const pmn = legendreAllOrders(n, x);
25187
+ for (let m = 0; m <= n; m++) {
25188
+ let val = pmn[m];
25189
+ if (normalization === "sch") {
25190
+ if (m > 0) {
25191
+ const scale = Math.pow(-1, m) * Math.sqrt(2 * factorialVal(n - m) / factorialVal(n + m));
25192
+ val = scale * val;
25193
+ }
25194
+ } else if (normalization === "norm") {
25195
+ const scale = Math.pow(-1, m) * Math.sqrt(
25196
+ (n + 0.5) * factorialVal(n - m) / factorialVal(n + m)
25197
+ );
25198
+ val = scale * val;
25199
+ }
25200
+ result[xi * numOrders + m] = val;
25201
+ }
25202
+ }
25203
+ if (isRuntimeNumber(xArg) || isRuntimeLogical(xArg)) {
25204
+ return RTV.tensor(result, [numOrders, 1]);
25205
+ }
25206
+ if (xShape.length === 2 && (xShape[0] === 1 || xShape[1] === 1)) {
25207
+ return RTV.tensor(result, [numOrders, numX]);
25208
+ }
25209
+ return RTV.tensor(result, [numOrders, ...xShape]);
25210
+ })
25211
+ );
25212
+ }
25213
+ function factorialVal(n) {
25214
+ if (n <= 1) return 1;
25215
+ let r = 1;
25216
+ for (let i = 2; i <= n; i++) r *= i;
25217
+ return r;
25218
+ }
25219
+ function legendreAllOrders(n, x) {
25220
+ const result = new Array(n + 1);
25221
+ if (n === 0) {
25222
+ result[0] = 1;
25223
+ return result;
25224
+ }
25225
+ const sqrtFactor = Math.sqrt(1 - x * x);
25226
+ for (let m = 0; m <= n; m++) {
25227
+ let pmm = 1;
25228
+ if (m > 0) {
25229
+ let dblFact = 1;
25230
+ for (let i = 1; i <= m; i++) {
25231
+ dblFact *= 2 * i - 1;
25232
+ }
25233
+ pmm = Math.pow(-1, m) * dblFact * Math.pow(sqrtFactor, m);
25234
+ }
25235
+ if (m === n) {
25236
+ result[m] = pmm;
25237
+ continue;
25238
+ }
25239
+ const pmm1 = x * (2 * m + 1) * pmm;
25240
+ if (m + 1 === n) {
25241
+ result[m] = pmm1;
25242
+ continue;
25243
+ }
25244
+ let pPrev2 = pmm;
25245
+ let pPrev1 = pmm1;
25246
+ let pCurr = 0;
25247
+ for (let l = m + 2; l <= n; l++) {
25248
+ pCurr = (x * (2 * l - 1) * pPrev1 - (l + m - 1) * pPrev2) / (l - m);
25249
+ pPrev2 = pPrev1;
25250
+ pPrev1 = pCurr;
25251
+ }
25252
+ result[m] = pCurr;
25253
+ }
25254
+ return result;
25096
25255
  }
25097
25256
 
25098
25257
  // src/numbl-core/builtins/shape-utils.ts
@@ -33686,6 +33845,12 @@ function registerMiscFunctions() {
33686
33845
  return RTV.num(0);
33687
33846
  })
33688
33847
  );
33848
+ register(
33849
+ "clc",
33850
+ builtinSingle(() => {
33851
+ return RTV.num(0);
33852
+ })
33853
+ );
33689
33854
  register(
33690
33855
  "clf",
33691
33856
  builtinSingle(() => {
@@ -34118,6 +34283,78 @@ function registerGraphicsFunctions() {
34118
34283
  "close",
34119
34284
  builtinSingle(() => RTV.num(0))
34120
34285
  );
34286
+ register(
34287
+ "title",
34288
+ builtinSingle(() => RTV.num(0))
34289
+ );
34290
+ register(
34291
+ "xlabel",
34292
+ builtinSingle(() => RTV.num(0))
34293
+ );
34294
+ register(
34295
+ "ylabel",
34296
+ builtinSingle(() => RTV.num(0))
34297
+ );
34298
+ register(
34299
+ "shading",
34300
+ builtinSingle(() => RTV.num(0))
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
+ );
34121
34358
  register(
34122
34359
  "drawnow",
34123
34360
  builtinSingle(() => RTV.num(0))
@@ -34126,6 +34363,45 @@ function registerGraphicsFunctions() {
34126
34363
  "pause",
34127
34364
  builtinSingle(() => RTV.num(0))
34128
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
+ );
34129
34405
  }
34130
34406
 
34131
34407
  // src/numbl-core/builtins/validators.ts
@@ -34297,7 +34573,7 @@ function registerDummyStringFunctions() {
34297
34573
  register(name, fn);
34298
34574
  }
34299
34575
  }
34300
- var returnEmptyArrayFunctions = ["who", "xlim", "ylim", "jet", "hot"];
34576
+ var returnEmptyArrayFunctions = ["who", "xlim", "ylim"];
34301
34577
  function registerDummyArrayFunctions() {
34302
34578
  const fn = builtinSingle(() => RTV.tensor([], [0, 0]), {
34303
34579
  outputType: IType.tensor()
@@ -36159,6 +36435,30 @@ function dispatch(rt, name, nargout, args, targetClassName) {
36159
36435
  if (name === "surf") {
36160
36436
  return rt.surf_call(args.map((a) => ensureRuntimeValue(a)));
36161
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
+ }
36162
36462
  }
36163
36463
  if (rt.compileSpecialized) {
36164
36464
  const argTypes = args.map(
@@ -36206,6 +36506,30 @@ function callBuiltin(rt, name, nargout, args) {
36206
36506
  if (name === "surf") {
36207
36507
  return rt.surf_call(args.map((a) => ensureRuntimeValue(a)));
36208
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
+ }
36209
36533
  const builtin = rt.builtins[name];
36210
36534
  if (builtin) return builtin(nargout, args);
36211
36535
  throw new RuntimeError(`'${name}' is not a builtin function`);
@@ -36220,6 +36544,30 @@ function callBuiltinSync(rt, name, nargout, args) {
36220
36544
  if (name === "surf") {
36221
36545
  return rt.surf_call(args.map((a) => ensureRuntimeValue(a)));
36222
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
+ }
36223
36571
  const builtin = rt.builtins[name];
36224
36572
  if (builtin) return builtin(nargout, args);
36225
36573
  throw new RuntimeError(`'${name}' is not a builtin function`);
@@ -38099,6 +38447,88 @@ function getStringValueIfString(v) {
38099
38447
  if (isRuntimeChar(v)) return v.value;
38100
38448
  return void 0;
38101
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
+ }
38102
38532
  function applyNameValue(traces, key, value) {
38103
38533
  switch (key) {
38104
38534
  case "color": {
@@ -38143,6 +38573,95 @@ function applyNameValue(traces, key, value) {
38143
38573
  }
38144
38574
  }
38145
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
+ }
38146
38665
 
38147
38666
  // src/numbl-core/runtime/syncChannel.ts
38148
38667
  var syncSleepWarned = false;
@@ -38168,10 +38687,17 @@ function syncSleep(ms) {
38168
38687
  // src/numbl-core/runtime/runtimePlot.ts
38169
38688
  function plotInstr(plotInstructions, instr) {
38170
38689
  if (instr.type === "set_figure_handle") {
38171
- plotInstructions.push({
38172
- type: "set_figure_handle",
38173
- handle: typeof instr.handle === "number" ? instr.handle : toNumber(ensureRuntimeValue(instr.handle))
38174
- });
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 });
38175
38701
  } else if (instr.type === "plot") {
38176
38702
  plotInstructions.push({
38177
38703
  type: "plot",
@@ -38191,13 +38717,82 @@ function plotInstr(plotInstructions, instr) {
38191
38717
  on = toString(mv) === "on";
38192
38718
  }
38193
38719
  plotInstructions.push({ type: "set_hold", value: on });
38720
+ } else if (instr.type === "set_title") {
38721
+ const text = typeof instr.text === "string" ? instr.text : toString(ensureRuntimeValue(instr.text));
38722
+ plotInstructions.push({ type: "set_title", text });
38723
+ } else if (instr.type === "set_xlabel") {
38724
+ const text = typeof instr.text === "string" ? instr.text : toString(ensureRuntimeValue(instr.text));
38725
+ plotInstructions.push({ type: "set_xlabel", text });
38726
+ } else if (instr.type === "set_ylabel") {
38727
+ const text = typeof instr.text === "string" ? instr.text : toString(ensureRuntimeValue(instr.text));
38728
+ plotInstructions.push({ type: "set_ylabel", text });
38729
+ } else if (instr.type === "set_shading") {
38730
+ const raw = typeof instr.shading === "string" ? instr.shading : toString(ensureRuntimeValue(instr.shading));
38731
+ const shading = raw.replace(/^'|'$/g, "");
38732
+ plotInstructions.push({ type: "set_shading", shading });
38194
38733
  } else if (instr.type === "close") {
38195
38734
  plotInstructions.push({ type: "close" });
38196
38735
  } else if (instr.type === "close_all") {
38197
38736
  plotInstructions.push({ type: "close_all" });
38198
38737
  } else if (instr.type === "clf") {
38199
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;
38200
38794
  }
38795
+ plotInstructions.push({ type: "set_view", az, el });
38201
38796
  }
38202
38797
  function plotCall(plotInstructions, args) {
38203
38798
  const traces = parsePlotArgs(args);
@@ -38215,6 +38810,38 @@ function surfCall(plotInstructions, args) {
38215
38810
  const trace = parseSurfArgs(args);
38216
38811
  plotInstructions.push({ type: "surf", trace });
38217
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
+ }
38218
38845
  function drawnow(plotInstructions, options) {
38219
38846
  if (options.onDrawnow && plotInstructions.length > 0) {
38220
38847
  options.onDrawnow([...plotInstructions]);
@@ -38323,6 +38950,61 @@ var Runtime = class _Runtime {
38323
38950
  this.builtins["surf"] = (_nargout, args) => {
38324
38951
  this.surf_call(args.map((a) => ensureRuntimeValue(a)));
38325
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
+ };
38326
39008
  }
38327
39009
  profileEnter(key) {
38328
39010
  if (!this.profilingEnabled) return;
@@ -38913,6 +39595,24 @@ var Runtime = class _Runtime {
38913
39595
  surf_call(args) {
38914
39596
  surfCall(this.plotInstructions, args);
38915
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
+ }
38916
39616
  // ── Drawnow / Pause ─────────────────────────────────────────────────
38917
39617
  drawnow() {
38918
39618
  return drawnow(this.plotInstructions, this.options);
@@ -39147,6 +39847,61 @@ function getEffectiveDir(fileName, searchPaths) {
39147
39847
  }
39148
39848
  return parts.length > 0 ? parts.join("/") + "/" : "";
39149
39849
  }
39850
+ function resolveViaImports(name, argTypes, callSite, index2, wildcardOnly) {
39851
+ const imports = index2.fileImports.get(callSite.file);
39852
+ if (!imports) return null;
39853
+ for (const imp of imports) {
39854
+ if (imp.wildcard !== wildcardOnly) continue;
39855
+ if (imp.wildcard) {
39856
+ const candidateName = `${imp.namespace}.${name}`;
39857
+ if (index2.workspaceFunctions.has(candidateName)) {
39858
+ return { kind: "workspaceFunction", name: candidateName, argTypes };
39859
+ }
39860
+ if (index2.workspaceClasses.has(candidateName)) {
39861
+ return {
39862
+ kind: "workspaceClassConstructor",
39863
+ className: candidateName,
39864
+ argTypes
39865
+ };
39866
+ }
39867
+ if (index2.classStaticMethods.get(imp.namespace)?.has(name)) {
39868
+ return {
39869
+ kind: "classMethod",
39870
+ className: imp.namespace,
39871
+ methodName: name,
39872
+ compileArgTypes: argTypes,
39873
+ stripInstance: false
39874
+ };
39875
+ }
39876
+ } else {
39877
+ if (name !== imp.shortName) continue;
39878
+ if (imp.staticMethod) {
39879
+ return {
39880
+ kind: "classMethod",
39881
+ className: imp.staticMethod.className,
39882
+ methodName: imp.staticMethod.methodName,
39883
+ compileArgTypes: argTypes,
39884
+ stripInstance: false
39885
+ };
39886
+ }
39887
+ if (index2.workspaceFunctions.has(imp.qualifiedName)) {
39888
+ return {
39889
+ kind: "workspaceFunction",
39890
+ name: imp.qualifiedName,
39891
+ argTypes
39892
+ };
39893
+ }
39894
+ if (index2.workspaceClasses.has(imp.qualifiedName)) {
39895
+ return {
39896
+ kind: "workspaceClassConstructor",
39897
+ className: imp.qualifiedName,
39898
+ argTypes
39899
+ };
39900
+ }
39901
+ }
39902
+ }
39903
+ return null;
39904
+ }
39150
39905
  function resolveFunction(name, argTypes, callSite, index2) {
39151
39906
  if (callSite.targetClassName) {
39152
39907
  const className = callSite.targetClassName;
@@ -39161,6 +39916,10 @@ function resolveFunction(name, argTypes, callSite, index2) {
39161
39916
  stripInstance
39162
39917
  };
39163
39918
  }
39919
+ {
39920
+ const imported = resolveViaImports(name, argTypes, callSite, index2, false);
39921
+ if (imported) return imported;
39922
+ }
39164
39923
  if (callSite.className) {
39165
39924
  const className = callSite.className;
39166
39925
  const isClassMethod = index2.classInstanceMethods.get(className)?.has(name) || index2.classConstructors.get(className) === name || index2.classStaticMethods.get(className)?.has(name);
@@ -39209,6 +39968,10 @@ function resolveFunction(name, argTypes, callSite, index2) {
39209
39968
  }
39210
39969
  }
39211
39970
  }
39971
+ {
39972
+ const imported = resolveViaImports(name, argTypes, callSite, index2, true);
39973
+ if (imported) return imported;
39974
+ }
39212
39975
  if (callSite.file) {
39213
39976
  const dir = getEffectiveDir(callSite.file, index2.searchPaths);
39214
39977
  if (index2.privateFunctions.get(dir)?.has(name)) {
@@ -39263,6 +40026,9 @@ function resolveFunction(name, argTypes, callSite, index2) {
39263
40026
  argTypes
39264
40027
  };
39265
40028
  }
40029
+ if (index2.jsUserFunctions.has(name)) {
40030
+ return { kind: "builtin", name };
40031
+ }
39266
40032
  if (index2.workspaceClasses.has(name)) {
39267
40033
  return {
39268
40034
  kind: "workspaceClassConstructor",
@@ -39328,12 +40094,17 @@ function resolveFuncCall(ctx, name, args, nargout, span) {
39328
40094
  { type: "userFunction", functionId: `private:${name}` }
39329
40095
  ]);
39330
40096
  case "workspaceFunction":
39331
- return makeFuncCallExpr(ctx, name, args, nargout, span, [
39332
- { type: "userFunction", functionId: name }
40097
+ return makeFuncCallExpr(ctx, target.name, args, nargout, span, [
40098
+ { type: "userFunction", functionId: target.name }
39333
40099
  ]);
39334
40100
  case "workspaceClassConstructor":
39335
40101
  return {
39336
- kind: { type: "ClassInstantiation", className: name, args, nargout },
40102
+ kind: {
40103
+ type: "ClassInstantiation",
40104
+ className: target.className,
40105
+ args,
40106
+ nargout
40107
+ },
39337
40108
  span
39338
40109
  };
39339
40110
  case "builtin":
@@ -40414,13 +41185,6 @@ var LoweringContext = class _LoweringContext {
40414
41185
  }
40415
41186
  for (const [className, group] of classFolderGroups) {
40416
41187
  if (!group.classDefFile) {
40417
- for (const mf of group.methodFiles) {
40418
- const baseName = mf.name.split("/").pop().replace(/\.m$/, "");
40419
- this.registry.filesByFuncName.set(baseName, {
40420
- fileName: mf.name,
40421
- source: mf.source
40422
- });
40423
- }
40424
41188
  continue;
40425
41189
  }
40426
41190
  this.registerWorkspaceClass(className, group.classDefFile);
@@ -40555,7 +41319,9 @@ var LoweringContext = class _LoweringContext {
40555
41319
  file.name,
40556
41320
  file.source
40557
41321
  );
40558
- this.registry.classesByName.set(qualifiedName, info);
41322
+ if (!this.registry.classesByName.has(qualifiedName)) {
41323
+ this.registry.classesByName.set(qualifiedName, info);
41324
+ }
40559
41325
  }
40560
41326
  /**
40561
41327
  * Register a classdef statement found in the local (main) file.
@@ -40720,8 +41486,17 @@ var LoweringContext = class _LoweringContext {
40720
41486
  * Should be called once after registerWorkspaceFiles() and registerLocalFunctionAST().
40721
41487
  * Parses all workspace files eagerly to discover subfunctions.
40722
41488
  */
40723
- buildFunctionIndex() {
41489
+ buildFunctionIndex(jsUserFunctionNames) {
40724
41490
  const builtins2 = new Set(getAllBuiltinNames());
41491
+ const jsUserFunctions = /* @__PURE__ */ new Set();
41492
+ if (jsUserFunctionNames) {
41493
+ for (const name of jsUserFunctionNames) {
41494
+ if (builtins2.has(name)) {
41495
+ builtins2.delete(name);
41496
+ jsUserFunctions.add(name);
41497
+ }
41498
+ }
41499
+ }
40725
41500
  const mainLocalFunctions = new Set(this.localFunctionASTs.keys());
40726
41501
  const workspaceFunctions = new Set(this.registry.filesByFuncName.keys());
40727
41502
  const workspaceClasses = /* @__PURE__ */ new Set([
@@ -40832,11 +41607,55 @@ var LoweringContext = class _LoweringContext {
40832
41607
  classInferiorClasses.set(className, new Set(info.inferiorClasses));
40833
41608
  }
40834
41609
  }
41610
+ const fileImports = /* @__PURE__ */ new Map();
41611
+ const collectImportsFromBody = (body, fileName) => {
41612
+ const entries = [];
41613
+ for (const stmt of body) {
41614
+ if (stmt.type !== "Import") continue;
41615
+ if (stmt.wildcard) {
41616
+ entries.push({ wildcard: true, namespace: stmt.path.join(".") });
41617
+ } else {
41618
+ const qualifiedName = stmt.path.join(".");
41619
+ const shortName = stmt.path[stmt.path.length - 1];
41620
+ const prefix = stmt.path.slice(0, -1).join(".");
41621
+ const isStaticMethod = prefix.length > 0 && classStaticMethods.get(prefix)?.has(shortName);
41622
+ entries.push({
41623
+ wildcard: false,
41624
+ qualifiedName,
41625
+ shortName,
41626
+ ...isStaticMethod ? { staticMethod: { className: prefix, methodName: shortName } } : {}
41627
+ });
41628
+ }
41629
+ }
41630
+ if (entries.length > 0) {
41631
+ fileImports.set(fileName, entries);
41632
+ }
41633
+ };
41634
+ try {
41635
+ const mainAst = this.getCachedAST(this.mainFileName);
41636
+ collectImportsFromBody(mainAst.body, this.mainFileName);
41637
+ } catch {
41638
+ }
41639
+ for (const [, entry] of this.registry.filesByFuncName) {
41640
+ const ast = this.getCachedAST(entry.fileName);
41641
+ collectImportsFromBody(ast.body, entry.fileName);
41642
+ }
41643
+ for (const [, info] of this.registry.classesByName) {
41644
+ const ast = this.getCachedAST(info.fileName);
41645
+ collectImportsFromBody(ast.body, info.fileName);
41646
+ }
41647
+ for (const [, entries] of this.registry.privateFilesByDir) {
41648
+ for (const [, entry] of entries) {
41649
+ const ast = this.getCachedAST(entry.fileName);
41650
+ collectImportsFromBody(ast.body, entry.fileName);
41651
+ }
41652
+ }
40835
41653
  const index2 = {
40836
41654
  builtins: builtins2,
40837
41655
  mainFileName: this.mainFileName,
40838
41656
  mainLocalFunctions,
40839
41657
  workspaceFunctions,
41658
+ jsUserFunctions,
40840
41659
  workspaceClasses,
40841
41660
  workspaceFileSubfunctions,
40842
41661
  classFileSubfunctions,
@@ -40847,7 +41666,8 @@ var LoweringContext = class _LoweringContext {
40847
41666
  privateFileSubfunctions,
40848
41667
  classInferiorClasses,
40849
41668
  searchPaths: this.registry.searchPaths,
40850
- fileToFuncName: this.registry.fileToFuncName
41669
+ fileToFuncName: this.registry.fileToFuncName,
41670
+ fileImports
40851
41671
  };
40852
41672
  this.registry.functionIndex = index2;
40853
41673
  return index2;
@@ -41604,12 +42424,36 @@ function genFuncCall(cg, kind) {
41604
42424
  return `$rt.plot_instr({type: "set_hold", value: ${args[0]}})`;
41605
42425
  if (kind.name === "ishold") return `$rt.ishold()`;
41606
42426
  if (kind.name === "clf") return `$rt.plot_instr({type: "clf"})`;
42427
+ if (kind.name === "title")
42428
+ return `$rt.plot_instr({type: "set_title", text: ${args[0] ?? '""'}})`;
42429
+ if (kind.name === "xlabel")
42430
+ return `$rt.plot_instr({type: "set_xlabel", text: ${args[0] ?? '""'}})`;
42431
+ if (kind.name === "ylabel")
42432
+ return `$rt.plot_instr({type: "set_ylabel", text: ${args[0] ?? '""'}})`;
42433
+ if (kind.name === "shading")
42434
+ return `$rt.plot_instr({type: "set_shading", shading: ${args[0] ?? '"faceted"'}})`;
41607
42435
  if (kind.name === "close") {
41608
42436
  if (args.length > 0) {
41609
42437
  return `$rt.plot_instr({type: "close_all"})`;
41610
42438
  }
41611
42439
  return `$rt.plot_instr({type: "close"})`;
41612
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(", ")}])`;
41613
42457
  if (cg.nestedFunctionNames.has(kind.name)) {
41614
42458
  return buildSpecializedCall(
41615
42459
  cg,
@@ -41715,13 +42559,18 @@ function genFuncCall(cg, kind) {
41715
42559
  break;
41716
42560
  }
41717
42561
  case "builtin": {
41718
- const nativeMath = tryNativeMathCodegen(
41719
- kind.name,
41720
- kind.nargout,
41721
- kind.args,
41722
- args
42562
+ const isJsUserFunc = cg.loweringCtx.functionIndex.jsUserFunctions.has(
42563
+ kind.name
41723
42564
  );
41724
- if (nativeMath !== null) return nativeMath;
42565
+ if (!isJsUserFunc) {
42566
+ const nativeMath = tryNativeMathCodegen(
42567
+ kind.name,
42568
+ kind.nargout,
42569
+ kind.args,
42570
+ args
42571
+ );
42572
+ if (nativeMath !== null) return nativeMath;
42573
+ }
41725
42574
  if (hasUnknown) {
41726
42575
  return emitDispatchUnknown(
41727
42576
  cg,
@@ -43327,8 +44176,80 @@ var defaultCheck = (_argTypes, nargout) => ({
43327
44176
  kind: "Unknown"
43328
44177
  })
43329
44178
  });
43330
- function loadJsUserFunctions(jsFiles) {
44179
+ function buildWasmMap(wasmFiles) {
44180
+ const map = /* @__PURE__ */ new Map();
44181
+ for (const f of wasmFiles) {
44182
+ if (!f.data) continue;
44183
+ const base = f.name.split("/").pop().replace(/\.wasm$/, "");
44184
+ map.set(base, f.data);
44185
+ }
44186
+ return map;
44187
+ }
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
+ }
44210
+ }
44211
+ function instantiateWasm(wasmData) {
44212
+ const wasmModule = new WebAssembly.Module(wasmData);
44213
+ const moduleImports = WebAssembly.Module.imports(wasmModule);
44214
+ const importObject = {};
44215
+ const neededModules = new Set(moduleImports.map((i) => i.module));
44216
+ if (neededModules.has("wasi_snapshot_preview1")) {
44217
+ importObject.wasi_snapshot_preview1 = {
44218
+ fd_write: () => 0,
44219
+ fd_read: () => 0,
44220
+ fd_close: () => 0,
44221
+ fd_seek: () => 0,
44222
+ fd_fdstat_get: () => 0,
44223
+ proc_exit: () => {
44224
+ },
44225
+ environ_sizes_get: () => 0,
44226
+ environ_get: () => 0,
44227
+ clock_time_get: () => 0,
44228
+ args_sizes_get: () => 0,
44229
+ args_get: () => 0
44230
+ };
44231
+ }
44232
+ if (neededModules.has("env")) {
44233
+ importObject.env = {
44234
+ emscripten_notify_memory_growth: () => {
44235
+ }
44236
+ };
44237
+ }
44238
+ return new WebAssembly.Instance(wasmModule, importObject);
44239
+ }
44240
+ function loadJsUserFunctions(jsFiles, wasmFiles, nativeBridge2) {
43331
44241
  const result = /* @__PURE__ */ new Map();
44242
+ const wasmMap = wasmFiles ? buildWasmMap(wasmFiles) : /* @__PURE__ */ new Map();
44243
+ const wasmInstanceCache = /* @__PURE__ */ new Map();
44244
+ function getWasmInstance(name) {
44245
+ const cached = wasmInstanceCache.get(name);
44246
+ if (cached) return cached;
44247
+ const data = wasmMap.get(name);
44248
+ if (!data) return void 0;
44249
+ const instance = instantiateWasm(data);
44250
+ wasmInstanceCache.set(name, instance);
44251
+ return instance;
44252
+ }
43332
44253
  for (const file of jsFiles) {
43333
44254
  const funcName = funcNameFromFile(file.name);
43334
44255
  try {
@@ -43342,19 +44263,63 @@ function loadJsUserFunctions(jsFiles) {
43342
44263
  apply: branch.apply
43343
44264
  });
43344
44265
  };
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
+ }
43345
44278
  const factory = new Function(
43346
44279
  "RTV",
43347
44280
  "RuntimeError",
43348
44281
  "FloatXArray",
44282
+ "IType",
43349
44283
  "register",
44284
+ "wasm",
44285
+ "native",
43350
44286
  file.source
43351
44287
  );
43352
- factory(RTV, RuntimeError, FloatXArray, registerFn);
44288
+ factory(
44289
+ RTV,
44290
+ RuntimeError,
44291
+ FloatXArray,
44292
+ IType,
44293
+ registerFn,
44294
+ wasmInstance,
44295
+ nativeLib
44296
+ );
43353
44297
  if (branches.length === 0) {
43354
44298
  throw new Error(
43355
44299
  `JS user function '${funcName}' (${file.name}) must call register() at least once`
43356
44300
  );
43357
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
+ }
43358
44323
  result.set(funcName, branches);
43359
44324
  } catch (e) {
43360
44325
  const msg = e instanceof Error ? e.message : String(e);
@@ -43445,10 +44410,13 @@ function generateMainScriptCode(source, mainFileName = "script.m", workspaceFile
43445
44410
  const ctx = new LoweringContext(source, mainFileName);
43446
44411
  const mWorkspaceFiles = [];
43447
44412
  const jsWorkspaceFiles = [];
44413
+ const wasmWorkspaceFiles = [];
43448
44414
  if (workspaceFiles) {
43449
44415
  for (const f of workspaceFiles) {
43450
44416
  if (f.name.endsWith(".js")) {
43451
44417
  jsWorkspaceFiles.push(f);
44418
+ } else if (f.name.endsWith(".wasm")) {
44419
+ wasmWorkspaceFiles.push(f);
43452
44420
  } else {
43453
44421
  mWorkspaceFiles.push(f);
43454
44422
  }
@@ -43465,7 +44433,11 @@ function generateMainScriptCode(source, mainFileName = "script.m", workspaceFile
43465
44433
  }
43466
44434
  ctx.registry.searchPaths = [...searchPaths ?? [], SHIM_SEARCH_PATH];
43467
44435
  _t0 = performance.now();
43468
- const jsUserFunctions = loadJsUserFunctions(jsWorkspaceFiles);
44436
+ const jsUserFunctions = loadJsUserFunctions(
44437
+ jsWorkspaceFiles,
44438
+ wasmWorkspaceFiles,
44439
+ opts?.nativeBridge
44440
+ );
43469
44441
  const _loadJsUserFunctionsMs = performance.now() - _t0;
43470
44442
  _t0 = performance.now();
43471
44443
  ctx.fileASTCache.set(mainFileName, ast);
@@ -43491,12 +44463,15 @@ function generateMainScriptCode(source, mainFileName = "script.m", workspaceFile
43491
44463
  ctx.registerWorkspaceFiles(mWorkspaceFiles);
43492
44464
  }
43493
44465
  const jsUserFuncNames = [...jsUserFunctions.keys()];
44466
+ const savedBuiltins = /* @__PURE__ */ new Map();
43494
44467
  for (const name of jsUserFuncNames) {
44468
+ const existing = getBuiltin(name);
44469
+ if (existing) savedBuiltins.set(name, existing);
43495
44470
  register(name, jsUserFunctions.get(name));
43496
44471
  }
43497
44472
  const _registrationMs = performance.now() - _t0;
43498
44473
  _t0 = performance.now();
43499
- const functionIndex = ctx.buildFunctionIndex();
44474
+ const functionIndex = ctx.buildFunctionIndex(jsUserFuncNames);
43500
44475
  const _buildFunctionIndexMs = performance.now() - _t0;
43501
44476
  ctx.isTopLevel = true;
43502
44477
  const initialVarIRVars = [];
@@ -43575,7 +44550,12 @@ function generateMainScriptCode(source, mainFileName = "script.m", workspaceFile
43575
44550
  codegen.emit(`return $ret;`);
43576
44551
  const _codegenMs = performance.now() - _t0;
43577
44552
  for (const name of jsUserFuncNames) {
43578
- unregister(name);
44553
+ const original = savedBuiltins.get(name);
44554
+ if (original) {
44555
+ register(name, original);
44556
+ } else {
44557
+ unregister(name);
44558
+ }
43579
44559
  }
43580
44560
  return {
43581
44561
  jsCode: codegen.getCode(),
@@ -43598,7 +44578,7 @@ function generateMainScriptCode(source, mainFileName = "script.m", workspaceFile
43598
44578
  }
43599
44579
 
43600
44580
  // src/numbl-core/executeCode.ts
43601
- function executeCode(source, options = {}, workspaceFiles, mainFileName = "script.m", searchPaths) {
44581
+ function executeCode(source, options = {}, workspaceFiles, mainFileName = "script.m", searchPaths, nativeBridge2) {
43602
44582
  const initialVariableNames = options.initialVariableValues ? Object.keys(options.initialVariableValues) : void 0;
43603
44583
  const codegenStart = performance.now();
43604
44584
  const {
@@ -43622,7 +44602,7 @@ function executeCode(source, options = {}, workspaceFiles, mainFileName = "scrip
43622
44602
  workspaceFiles,
43623
44603
  initialVariableNames,
43624
44604
  searchPaths,
43625
- { noLineTracking: options.noLineTracking }
44605
+ { noLineTracking: options.noLineTracking, nativeBridge: nativeBridge2 }
43626
44606
  );
43627
44607
  const codegenTimeMs = performance.now() - codegenStart;
43628
44608
  if (options.log) {
@@ -43765,7 +44745,7 @@ function processMipLoad(packageName, _visited) {
43765
44745
  if (visited.has(packageName)) return [];
43766
44746
  visited.add(packageName);
43767
44747
  const mipDir = process.env.MIP_DIR || join3(homedir2(), ".mip");
43768
- const pkgDir = join3(mipDir, "packages", packageName);
44748
+ const pkgDir = join3(mipDir, "numbl_packages", packageName);
43769
44749
  const loadScript = join3(pkgDir, "load_package.m");
43770
44750
  if (!existsSync3(loadScript)) {
43771
44751
  throw new Error(
@@ -43779,7 +44759,7 @@ function processMipLoad(packageName, _visited) {
43779
44759
  const mipJson = JSON.parse(readFileSync3(mipJsonPath, "utf-8"));
43780
44760
  const deps = mipJson.dependencies ?? [];
43781
44761
  for (const dep of deps) {
43782
- const depPkgDir = join3(mipDir, "packages", dep);
44762
+ const depPkgDir = join3(mipDir, "numbl_packages", dep);
43783
44763
  if (!existsSync3(depPkgDir)) {
43784
44764
  console.warn(
43785
44765
  `Warning: dependency "${dep}" of "${packageName}" is not installed; skipping`
@@ -44019,7 +44999,7 @@ function saveHistoryEntry(entry, hist) {
44019
44999
  } catch {
44020
45000
  }
44021
45001
  }
44022
- async function runRepl(initialWorkspaceFiles, onDrawnow, initialSearchPaths) {
45002
+ async function runRepl(initialWorkspaceFiles, onDrawnow, initialSearchPaths, nativeBridge2) {
44023
45003
  let variableValues = {};
44024
45004
  let holdState = false;
44025
45005
  const workspaceFiles = [...initialWorkspaceFiles];
@@ -44078,7 +45058,8 @@ async function runRepl(initialWorkspaceFiles, onDrawnow, initialSearchPaths) {
44078
45058
  },
44079
45059
  workspaceFiles,
44080
45060
  "repl",
44081
- searchPaths
45061
+ searchPaths,
45062
+ nativeBridge2
44082
45063
  );
44083
45064
  variableValues = result.variableValues;
44084
45065
  holdState = result.holdState;
@@ -44186,7 +45167,8 @@ async function runRepl(initialWorkspaceFiles, onDrawnow, initialSearchPaths) {
44186
45167
  },
44187
45168
  workspaceFiles,
44188
45169
  "repl",
44189
- searchPaths
45170
+ searchPaths,
45171
+ nativeBridge2
44190
45172
  );
44191
45173
  variableValues = result.variableValues;
44192
45174
  holdState = result.holdState;
@@ -44455,6 +45437,14 @@ async function runRepl(initialWorkspaceFiles, onDrawnow, initialSearchPaths) {
44455
45437
 
44456
45438
  // src/cli-fileio.ts
44457
45439
  import { openSync, closeSync, readSync, writeSync, readFileSync as readFileSync5 } from "fs";
45440
+ import { homedir as homedir4 } from "os";
45441
+ import { join as join5 } from "path";
45442
+ function expandTilde(filepath) {
45443
+ if (filepath.startsWith("~/")) {
45444
+ return join5(homedir4(), filepath.slice(2));
45445
+ }
45446
+ return filepath;
45447
+ }
44458
45448
  function permissionToFlags(permission) {
44459
45449
  switch (permission) {
44460
45450
  case "r":
@@ -44481,7 +45471,7 @@ var NodeFileIOAdapter = class {
44481
45471
  fopen(filename, permission) {
44482
45472
  try {
44483
45473
  const flags = permissionToFlags(permission);
44484
- const fd = openSync(filename, flags);
45474
+ const fd = openSync(expandTilde(filename), flags);
44485
45475
  const fid = this.nextFid++;
44486
45476
  this.openFiles.set(fid, {
44487
45477
  fd,
@@ -44527,7 +45517,7 @@ var NodeFileIOAdapter = class {
44527
45517
  return this.readLine(entry, true);
44528
45518
  }
44529
45519
  fileread(filename) {
44530
- return readFileSync5(filename, "utf-8");
45520
+ return readFileSync5(expandTilde(filename), "utf-8");
44531
45521
  }
44532
45522
  feof(fid) {
44533
45523
  const entry = this.getEntry(fid);
@@ -44609,8 +45599,8 @@ var NodeFileIOAdapter = class {
44609
45599
  // src/cli.ts
44610
45600
  var __filename = fileURLToPath2(import.meta.url);
44611
45601
  var __dirname = dirname3(__filename);
44612
- var packageDir2 = join5(__dirname, "..");
44613
- var addonPath = join5(packageDir2, "build", "Release", "lapack_addon.node");
45602
+ var packageDir2 = join6(__dirname, "..");
45603
+ var addonPath = join6(packageDir2, "build", "Release", "lapack_addon.node");
44614
45604
  var nativeAddonLoaded = false;
44615
45605
  try {
44616
45606
  const req = createRequire(import.meta.url);
@@ -44620,15 +45610,27 @@ try {
44620
45610
  nativeAddonLoaded = true;
44621
45611
  } catch {
44622
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
+ }
44623
45620
  function scanMFiles(dirPath, excludeFile) {
44624
45621
  const files = [];
45622
+ let entries;
44625
45623
  try {
44626
- const entries = readdirSync2(dirPath);
44627
- for (const entry of entries) {
44628
- const fullPath = join5(dirPath, entry);
44629
- if (excludeFile && fullPath === excludeFile) {
44630
- continue;
44631
- }
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 {
44632
45634
  const stat = statSync2(fullPath);
44633
45635
  if (stat.isDirectory()) {
44634
45636
  if (entry.startsWith("@") || entry.startsWith("+") || entry === "private") {
@@ -44640,9 +45642,19 @@ function scanMFiles(dirPath, excludeFile) {
44640
45642
  name: fullPath,
44641
45643
  source
44642
45644
  });
45645
+ } else if (stat.isFile() && entry.endsWith(".wasm")) {
45646
+ const data = readFileSync6(fullPath);
45647
+ files.push({
45648
+ name: fullPath,
45649
+ source: "",
45650
+ data: new Uint8Array(data)
45651
+ });
44643
45652
  }
45653
+ } catch (err) {
45654
+ console.warn(
45655
+ `Warning: could not read ${fullPath}: ${err instanceof Error ? err.message : String(err)}`
45656
+ );
44644
45657
  }
44645
- } catch {
44646
45658
  }
44647
45659
  return files;
44648
45660
  }
@@ -44657,7 +45669,7 @@ function findTestFiles(dir) {
44657
45669
  }
44658
45670
  entries.sort();
44659
45671
  for (const entry of entries) {
44660
- const fullPath = join5(current, entry);
45672
+ const fullPath = join6(current, entry);
44661
45673
  let stat;
44662
45674
  try {
44663
45675
  stat = statSync2(fullPath);
@@ -44665,7 +45677,7 @@ function findTestFiles(dir) {
44665
45677
  continue;
44666
45678
  }
44667
45679
  if (stat.isDirectory()) {
44668
- if (!entry.startsWith("@") && !entry.startsWith("+")) {
45680
+ if (!entry.startsWith("@") && !entry.startsWith("+") && entry !== "wasm") {
44669
45681
  walk(fullPath);
44670
45682
  }
44671
45683
  } else if (stat.isFile() && entry.endsWith(".m")) {
@@ -44702,7 +45714,8 @@ async function runTests(dir) {
44702
45714
  { displayResults: true },
44703
45715
  workspaceFiles,
44704
45716
  mainFileName,
44705
- searchPaths
45717
+ searchPaths,
45718
+ nativeBridge
44706
45719
  );
44707
45720
  const outputText = result.output.join("");
44708
45721
  const lines = outputText.split("\n").filter((l) => l.length > 0);
@@ -45001,7 +46014,8 @@ async function executeWithOptions(code, mainFileName, workspaceFiles, opts, sear
45001
46014
  },
45002
46015
  workspaceFiles,
45003
46016
  mainFileName,
45004
- searchPaths
46017
+ searchPaths,
46018
+ nativeBridge
45005
46019
  );
45006
46020
  if (result.plotInstructions.length > 0) {
45007
46021
  streamLine({
@@ -45049,7 +46063,8 @@ async function executeWithOptions(code, mainFileName, workspaceFiles, opts, sear
45049
46063
  },
45050
46064
  workspaceFiles,
45051
46065
  mainFileName,
45052
- searchPaths
46066
+ searchPaths,
46067
+ nativeBridge
45053
46068
  );
45054
46069
  writeProfileIfNeeded(result);
45055
46070
  if (opts.dumpJs) {
@@ -45077,7 +46092,8 @@ async function executeWithOptions(code, mainFileName, workspaceFiles, opts, sear
45077
46092
  },
45078
46093
  workspaceFiles,
45079
46094
  mainFileName,
45080
- searchPaths
46095
+ searchPaths,
46096
+ nativeBridge
45081
46097
  );
45082
46098
  writeProfileIfNeeded(result);
45083
46099
  if (opts.dumpJs) {
@@ -45110,7 +46126,7 @@ function finalizeDumpFile(dumpFile, mainFileName, jsCode) {
45110
46126
  writeFileSync3(dumpFile, header + jsCode + "\n" + jitContent);
45111
46127
  }
45112
46128
  async function cmdBuildAddon() {
45113
- const bindingGyp = join5(packageDir2, "binding.gyp");
46129
+ const bindingGyp = join6(packageDir2, "binding.gyp");
45114
46130
  if (!existsSync4(bindingGyp)) {
45115
46131
  console.error(
45116
46132
  "Error: binding.gyp not found in package directory: " + packageDir2
@@ -45162,7 +46178,7 @@ async function cmdRepl(args) {
45162
46178
  !opts.plot,
45163
46179
  replPlotOpts
45164
46180
  );
45165
- await runRepl(replFiles, replDrawnow, replSearchPaths);
46181
+ await runRepl(replFiles, replDrawnow, replSearchPaths, nativeBridge);
45166
46182
  }
45167
46183
  function createPlotHandler(disabled, plotOpts) {
45168
46184
  if (disabled) {
@@ -45317,7 +46333,7 @@ async function main() {
45317
46333
  await cmdEval(rest);
45318
46334
  break;
45319
46335
  case "run-tests": {
45320
- const dir = rest.length > 0 ? rest[0] : join5(packageDir2, "numbl_test_scripts");
46336
+ const dir = rest.length > 0 ? rest[0] : join6(packageDir2, "numbl_test_scripts");
45321
46337
  await runTests(dir);
45322
46338
  break;
45323
46339
  }