@tilua/compiler 5.0.0 → 6.0.0

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.cjs CHANGED
@@ -262,7 +262,29 @@ var standardLowering = { plugin: plugin2, from: "tilua (standard library)" };
262
262
 
263
263
  // src/lower.ts
264
264
  function lower(program2, scopes, options = {}) {
265
- return new Lowerer(program2, scopes, options).run();
265
+ const result2 = new Lowerer(program2, scopes, options).run();
266
+ dropUnreachable(result2.statements);
267
+ return result2;
268
+ }
269
+ function dropUnreachable(statements) {
270
+ const exit = statements.findIndex((s) => s.type === "ReturnStatement" || s.type === "BreakStatement" || s.type === "ContinueStatement");
271
+ if (exit >= 0) statements.length = exit + 1;
272
+ for (const statement of statements) visitBlocks(statement);
273
+ }
274
+ function visitBlocks(node) {
275
+ if (!node || typeof node !== "object") return;
276
+ if (Array.isArray(node)) {
277
+ for (const item of node) visitBlocks(item);
278
+ return;
279
+ }
280
+ const record = node;
281
+ if (record.type === "Block" && Array.isArray(record.statements)) {
282
+ dropUnreachable(record.statements);
283
+ return;
284
+ }
285
+ for (const key in record) {
286
+ if (key !== "line" && key !== "column") visitBlocks(record[key]);
287
+ }
266
288
  }
267
289
  var Lowerer = class {
268
290
  constructor(source, scopes, options) {
@@ -275,6 +297,18 @@ var Lowerer = class {
275
297
  for (const binding of scopes.bindings.values()) {
276
298
  if (binding.declarationNode) this.bindingByDeclaration.set(binding.declarationNode, binding);
277
299
  }
300
+ const visit = (value) => {
301
+ if (!value || typeof value !== "object") return;
302
+ if (Array.isArray(value)) return void value.forEach(visit);
303
+ const node = value;
304
+ if (node.type === "VariableDeclaration" && node.name?.type === "IdentifierPattern" && node.name.name) {
305
+ let init = node.init;
306
+ while (init?.type === "ParenthesizedExpression") init = init.expression;
307
+ if (init?.type === "ClassExpression") this.classExpressionNames.set(init, node.name.name);
308
+ }
309
+ for (const [key, child] of Object.entries(value)) if (key !== "line" && key !== "column") visit(child);
310
+ };
311
+ visit(source.body);
278
312
  }
279
313
  source;
280
314
  scopes;
@@ -292,10 +326,17 @@ var Lowerer = class {
292
326
  exportsName;
293
327
  /** Globals generated code calls, renamed where the source shadows them. */
294
328
  builtins = /* @__PURE__ */ new Map();
329
+ /** The `try` blocks being lowered in the current function, innermost
330
+ * last; see `tryStatement`. A function written inside one starts afresh. */
331
+ tryFrames = [];
332
+ /** The loops being lowered in the current function, innermost last. */
333
+ loops = [];
295
334
  /** Whether the output has to be plain Lua 5.1 rather than Luau. */
296
335
  lua51;
297
336
  /** The source line each emitted statement came from. */
298
337
  origins = /* @__PURE__ */ new WeakMap();
338
+ /** The name each class written as a value is known by. */
339
+ classExpressionNames = /* @__PURE__ */ new WeakMap();
299
340
  run() {
300
341
  const body = this.options.module ? this.module(this.options.module) : this.topLevel(this.source.body.statements);
301
342
  const scriptArgs = this.usesScriptArgs && !this.options.module ? [local(["scriptArgs"], [this.array(table([{ type: "TableFieldPositional", value: vararg() }]))])] : [];
@@ -655,6 +696,16 @@ local function ${typeOf}(value, known)
655
696
  end`).body.statements);
656
697
  }
657
698
  }
699
+ const add = this.helpers.get("add");
700
+ if (add) {
701
+ out2.push(...(0, import_luau_parser.parse)(`
702
+ local function ${add}(a, b)
703
+ if ${this.builtin("type").name}(a) == "string" or ${this.builtin("type").name}(b) == "string" then
704
+ return ${this.builtin("tostring").name}(a) .. ${this.builtin("tostring").name}(b)
705
+ end
706
+ return a + b
707
+ end`).body.statements);
708
+ }
658
709
  const instanceOf = this.helpers.get("instanceof");
659
710
  if (instanceOf) {
660
711
  out2.push(...(0, import_luau_parser.parse)(`
@@ -677,6 +728,8 @@ end`).body.statements);
677
728
  out2.push(...(0, import_luau_parser.parse)(`
678
729
  local function ${accessors}(target, getters, setters)
679
730
  return ${this.builtin("setmetatable").name}(target, {
731
+ -- Read by a spread, which copies what the getters give.
732
+ __tiluaGetters = getters,
680
733
  __index = function(self, key)
681
734
  local get = getters[key]
682
735
  if get ~= nil then
@@ -700,17 +753,25 @@ end`).body.statements);
700
753
  }
701
754
  const assign2 = this.helpers.get("assign");
702
755
  if (assign2) {
703
- out2.push(localFunction(assign2, functionBody(["target"], [
704
- numericFor("i", number(1), selectCount(this.builtin("select")), [
705
- local(["source"], [call(this.builtin("select"), [identifier("i"), vararg()])]),
706
- ifThen(binary("~=", identifier("source"), nil()), [
707
- genericFor(["key", "value"], [call(this.builtin("pairs"), [identifier("source")])], [
708
- assign([index(identifier("target"), identifier("key"))], [identifier("value")])
709
- ])
710
- ])
711
- ]),
712
- returns([identifier("target")])
713
- ], true)));
756
+ out2.push(...(0, import_luau_parser.parse)(`
757
+ local function ${assign2}(target, ...)
758
+ for i = 1, ${this.builtin("select").name}("#", ...) do
759
+ local source = (${this.builtin("select").name}(i, ...))
760
+ if source ~= nil then
761
+ for key, value in ${this.builtin("pairs").name}(source) do
762
+ target[key] = value
763
+ end
764
+ local meta = ${this.builtin("type").name}(source) == "table" and ${this.builtin("getmetatable").name}(source) or nil
765
+ local getters = ${this.builtin("type").name}(meta) == "table" and ${this.builtin("rawget").name}(meta, "__tiluaGetters") or nil
766
+ if getters ~= nil then
767
+ for key, get in ${this.builtin("pairs").name}(getters) do
768
+ target[key] = get(source)
769
+ end
770
+ end
771
+ end
772
+ end
773
+ return target
774
+ end`).body.statements);
714
775
  }
715
776
  out2.push(...runtimes);
716
777
  const concat = this.helpers.get("concat");
@@ -1069,7 +1130,49 @@ end`).body.statements);
1069
1130
  if (!this.origins.has(statement)) this.origins.set(statement, node.line.start);
1070
1131
  return statement;
1071
1132
  }
1133
+ /** A statement; a loop with what its labels need around it.
1134
+ *
1135
+ * Luau has no labels, and no `goto` to stand in for them. `break outer`
1136
+ * in a loop inside `outer` sets a flag `outer` declares and breaks the
1137
+ * loop it is in; right after that loop, the flag is checked, and the
1138
+ * check breaks again — or, once it is `outer` that would be left, does
1139
+ * what was asked of `outer` itself. `continue outer` is the same, with
1140
+ * `continue` done there and the flag lowered for the next time round. */
1072
1141
  statementOf(node) {
1142
+ if (!LOOPS.has(node.type)) return this.statementKind(node);
1143
+ const loop = {
1144
+ label: node.label?.name,
1145
+ tryDepth: this.tryFrames.length,
1146
+ leaving: /* @__PURE__ */ new Set()
1147
+ };
1148
+ this.loops.push(loop);
1149
+ let lowered;
1150
+ try {
1151
+ lowered = this.statementKind(node);
1152
+ } finally {
1153
+ this.loops.pop();
1154
+ }
1155
+ const flags = [loop.breakFlag, loop.continueFlag].filter((f) => f !== void 0);
1156
+ const out2 = [...flags.length ? [local(flags, flags.map(() => boolean(false)))] : [], ...lowered];
1157
+ const enclosing = this.loops[this.loops.length - 1];
1158
+ for (const target of loop.leaving) {
1159
+ if (target === enclosing) {
1160
+ if (target.breakFlag) out2.push(ifThen(identifier(target.breakFlag), this.jump("break", void 0)));
1161
+ if (target.continueFlag) {
1162
+ out2.push(ifThen(identifier(target.continueFlag), [
1163
+ assign([identifier(target.continueFlag)], [boolean(false)]),
1164
+ ...this.jump("continue", void 0)
1165
+ ]));
1166
+ }
1167
+ continue;
1168
+ }
1169
+ enclosing?.leaving.add(target);
1170
+ const raised = [target.breakFlag, target.continueFlag].filter((f) => f !== void 0).map((f) => identifier(f)).reduce((a, b) => binary("or", a, b));
1171
+ out2.push(ifThen(raised, this.jump("break", void 0)));
1172
+ }
1173
+ return out2;
1174
+ }
1175
+ statementKind(node) {
1073
1176
  switch (node.type) {
1074
1177
  // Types, and what exists only for them.
1075
1178
  case "TypeAliasStatement":
@@ -1089,15 +1192,20 @@ end`).body.statements);
1089
1192
  return this.classDeclaration(node, "declare");
1090
1193
  case "AssignmentStatement":
1091
1194
  return this.assignment(node);
1092
- case "CompoundAssignmentStatement":
1093
- if (this.lua51) return this.compoundAssignment51(node);
1195
+ case "CompoundAssignmentStatement": {
1196
+ if (node.operator === "??=") return this.nullishAssignment(node);
1197
+ const join2 = node.operator === "+=" ? this.options.types?.joins.get(node) : void 0;
1198
+ if (join2 === "dynamic") return this.dynamicAddition(node);
1199
+ const operator = join2 === "concat" ? "..=" : node.operator;
1200
+ if (this.lua51) return this.compoundAssignment51(node, operator);
1094
1201
  return [{
1095
1202
  type: "CompoundAssignmentStatement",
1096
- operator: node.operator,
1203
+ operator,
1097
1204
  target: this.expression(node.target),
1098
1205
  value: this.expression(node.value),
1099
1206
  ...spanOf(node)
1100
1207
  }];
1208
+ }
1101
1209
  case "CallStatement": {
1102
1210
  const chain = optionalChain(node.expression);
1103
1211
  if (chain) return [this.optionalCallStatement(chain)];
@@ -1183,11 +1291,20 @@ end`).body.statements);
1183
1291
  )];
1184
1292
  }
1185
1293
  case "ReturnStatement":
1186
- return [returns(node.argument ? [this.keptToOne(this.expression(node.argument))] : [])];
1294
+ return this.jump("return", node.argument && this.keptToOne(this.expression(node.argument)), node);
1187
1295
  case "BreakStatement":
1188
- return [{ type: "BreakStatement", ...spanOf(node) }];
1296
+ return this.jump("break", void 0, node, node.label?.name);
1189
1297
  case "ContinueStatement":
1190
- return [{ type: "ContinueStatement", ...spanOf(node) }];
1298
+ return this.jump("continue", void 0, node, node.label?.name);
1299
+ // Level 0: what is thrown is what a `catch` is handed, with no
1300
+ // position put in front of a string.
1301
+ case "ThrowStatement":
1302
+ return [callStatement(call(
1303
+ this.builtin("error"),
1304
+ [this.keptToOne(this.expression(node.argument)), number(0)]
1305
+ ))];
1306
+ case "TryStatement":
1307
+ return this.tryStatement(node);
1191
1308
  case "ImportStatement":
1192
1309
  if (node.isTypeOnly) return [];
1193
1310
  this.report(node, this.options.module ? "Imports and exports belong at the top level of a module" : "Imports and exports need a bundle: build the project with @tilua/compiler");
@@ -1200,6 +1317,90 @@ end`).body.statements);
1200
1317
  return [];
1201
1318
  }
1202
1319
  }
1320
+ /** A `return`, `break` or `continue`. Inside a `try` that it leaves, it
1321
+ * is the `try`'s function returning a code saying which — and the value
1322
+ * — for the code after the `pcall` to do it there. */
1323
+ jump(kind, value, node, label) {
1324
+ const at = node ? spanOf(node) : {};
1325
+ const frame = this.tryFrames[this.tryFrames.length - 1];
1326
+ const target = kind === "return" ? void 0 : label === void 0 ? this.loops[this.loops.length - 1] : this.loops.findLast((loop) => loop.label === label);
1327
+ if (frame && (kind === "return" || target && target.tryDepth < this.tryFrames.length)) {
1328
+ const key = `${kind}:${label ?? ""}`;
1329
+ let exit = frame.exits.get(key);
1330
+ if (!exit) {
1331
+ exit = { kind, label, code: kind === "return" ? 1 : frame.exits.size + 2 };
1332
+ frame.exits.set(key, exit);
1333
+ }
1334
+ if (value) frame.returnsValue = true;
1335
+ return [returns([number(exit.code), ...value ? [value] : []])];
1336
+ }
1337
+ if (kind === "return") return [{ ...returns(value ? [value] : []), ...at }];
1338
+ const plain = () => kind === "break" ? { ...breakStatement(), ...at } : { ...breakStatement(), type: "ContinueStatement", ...at };
1339
+ const innermost = this.loops[this.loops.length - 1];
1340
+ if (!target || target === innermost) return [plain()];
1341
+ const flag = kind === "break" ? target.breakFlag ??= this.names.fresh(`${target.label}Broke`) : target.continueFlag ??= this.names.fresh(`${target.label}Continued`);
1342
+ innermost.leaving.add(target);
1343
+ return [assign([identifier(flag)], [boolean(true)]), { ...breakStatement(), ...at }];
1344
+ }
1345
+ /** `try { a } catch (e) { b } finally { c }`:
1346
+ *
1347
+ * local ok, result, value = pcall(function() a end)
1348
+ * if not ok then
1349
+ * ok, result, value = pcall(function(e) b end, result)
1350
+ * end
1351
+ * do c end
1352
+ * if not ok then error(result, 0) end
1353
+ * if result == 1 then return value elseif ... end
1354
+ *
1355
+ * Without a `finally`, the `catch` runs in place of the second `pcall`:
1356
+ * nothing has to run after it. A `return`, `break` or `continue` that
1357
+ * leaves the `try` cannot be written inside its function; it returns a
1358
+ * code instead (see `jump`), and the last `if` does what it says. */
1359
+ tryStatement(node) {
1360
+ const ok = this.names.fresh("ok");
1361
+ const result2 = this.names.fresh("result");
1362
+ const value = this.names.fresh("value");
1363
+ const frame = { exits: /* @__PURE__ */ new Map(), returnsValue: false };
1364
+ const guarded = (block2, params, args2) => {
1365
+ this.tryFrames.push(frame);
1366
+ let statements;
1367
+ try {
1368
+ statements = this.block(block2).statements;
1369
+ } finally {
1370
+ this.tryFrames.pop();
1371
+ }
1372
+ const passesVarargs = statements.some(usesVararg);
1373
+ const func = functionExpression(functionBody(params, statements, passesVarargs));
1374
+ return call(this.builtin("pcall"), [func, ...args2, ...passesVarargs ? [vararg()] : []]);
1375
+ };
1376
+ const attempt = guarded(node.block, [], []);
1377
+ const param = node.handler?.param && this.name(node.handler.param.name);
1378
+ const inPlace = node.handler && !node.finalizer ? this.block(node.handler.body, param ? [local([param], [identifier(result2)])] : []) : void 0;
1379
+ const caught = node.handler && node.finalizer ? guarded(node.handler.body, [param ?? "_"], [identifier(result2)]) : void 0;
1380
+ const finalizer = node.finalizer && this.block(node.finalizer);
1381
+ const returnsValue = frame.returnsValue;
1382
+ const usesResult = returnsValue || frame.exits.size > 0 || !!param || !!node.finalizer;
1383
+ const names = [ok, ...usesResult ? [result2] : [], ...returnsValue ? [value] : []];
1384
+ const failed = () => unary("not", identifier(ok));
1385
+ const out2 = [this.from(local(names, [attempt]), node)];
1386
+ const clauses = [];
1387
+ if (inPlace) clauses.push({ type: "IfClause", condition: failed(), body: inPlace, ...spanOf(node.handler) });
1388
+ if (caught) out2.push(ifThen(failed(), [assign(names.map(identifier), [caught])]));
1389
+ if (finalizer) {
1390
+ out2.push(doBlock(finalizer.statements));
1391
+ out2.push(ifThen(failed(), [callStatement(call(this.builtin("error"), [identifier(result2), number(0)]))]));
1392
+ }
1393
+ for (const exit of [...frame.exits.values()].sort((a, b) => a.code - b.code)) {
1394
+ clauses.push({
1395
+ type: "IfClause",
1396
+ condition: binary("==", identifier(result2), number(exit.code)),
1397
+ body: block(this.jump(exit.kind, exit.kind === "return" && returnsValue ? identifier(value) : void 0, void 0, exit.label)),
1398
+ ...spanOf(node)
1399
+ });
1400
+ }
1401
+ if (clauses.length) out2.push({ type: "IfStatement", clauses, ...spanOf(node) });
1402
+ return out2;
1403
+ }
1203
1404
  functionDeclarationStatement(node) {
1204
1405
  const statement = this.functionStatement(this.reference(node.target.base), node, this.functionBody(node.func), node.isMethod, node.target.path.map((p) => p.name));
1205
1406
  if (!node.target.method) return statement;
@@ -1255,11 +1456,12 @@ end`).body.statements);
1255
1456
  const { build, accessors } = this.classHelpers;
1256
1457
  const metamethods = `{ ${CLASS_METAMETHODS.map((name) => `"${name}"`).join(", ")} }`;
1257
1458
  return (0, import_luau_parser.parse)(`
1258
- local function ${build}(base)
1459
+ local function ${build}(base, name)
1259
1460
  local class = { __getters = {}, __setters = {} }
1260
1461
  class.__index = class
1261
1462
  class.ClassObject = class
1262
1463
  class.ParentClass = base
1464
+ class.name = name
1263
1465
  if base ~= nil then
1264
1466
  setmetatable(class, { __index = base })
1265
1467
  setmetatable(class.__getters, { __index = base.__getters })
@@ -1313,7 +1515,11 @@ end
1313
1515
  * table is assigned to `self`, which a module has already declared. */
1314
1516
  classStatements(node, self, declare) {
1315
1517
  const { build, accessors } = this.classRuntime();
1316
- const create = call(identifier(build), [node.superclass ? this.reference(node.superclass) : nil()]);
1518
+ const called = node.name?.name ?? (node.type === "ClassExpression" ? this.classExpressionNames.get(node) : void 0) ?? "";
1519
+ const create = call(identifier(build), [
1520
+ node.superclass ? this.reference(node.superclass) : nil(),
1521
+ string(called)
1522
+ ]);
1317
1523
  const out2 = [declare !== void 0 ? local([declare], [create]) : assign([self], [create])];
1318
1524
  const previous = this.classContext;
1319
1525
  this.classContext = node;
@@ -1584,6 +1790,18 @@ end
1584
1790
  // Functions
1585
1791
  // --------------------------------------------------------
1586
1792
  functionBody(func) {
1793
+ const frames = this.tryFrames;
1794
+ const loops = this.loops;
1795
+ this.tryFrames = [];
1796
+ this.loops = [];
1797
+ try {
1798
+ return this.functionBodyIn(func);
1799
+ } finally {
1800
+ this.tryFrames = frames;
1801
+ this.loops = loops;
1802
+ }
1803
+ }
1804
+ functionBodyIn(func) {
1587
1805
  const params = func.isMethod ? func.params.slice(1) : func.params;
1588
1806
  const prelude = [];
1589
1807
  const names = [];
@@ -1634,8 +1852,10 @@ end
1634
1852
  return nil();
1635
1853
  case "InterpolatedStringExpression":
1636
1854
  return this.interpolatedString(node);
1855
+ // An object's method, `{ m() { ... } }`, keeps its `this` as the
1856
+ // first parameter written out: a function value has no `:`.
1637
1857
  case "FunctionExpression":
1638
- return functionExpression(this.functionBody(node.func));
1858
+ return functionExpression(this.classFunctionBody(node.func));
1639
1859
  case "TableExpression":
1640
1860
  return this.tableExpression(node);
1641
1861
  case "ArrayExpression":
@@ -1650,6 +1870,11 @@ end
1650
1870
  if (node.operator === "instanceof") {
1651
1871
  return call(this.helper("instanceof"), [this.keptToOne(left), this.keptToOne(right)]);
1652
1872
  }
1873
+ if (node.operator === "+") {
1874
+ const join2 = this.options.types?.joins.get(node);
1875
+ if (join2 === "concat") return binary("..", left, right);
1876
+ if (join2 === "dynamic") return call(this.helper("add"), [this.keptToOne(left), this.keptToOne(right)]);
1877
+ }
1653
1878
  if (this.lua51 && node.operator === "//") return this.floorDivide(left, right);
1654
1879
  return binary(node.operator, left, right);
1655
1880
  }
@@ -1909,14 +2134,52 @@ end
1909
2134
  if (!args2.length) return string(text);
1910
2135
  return methodCall(parenthesized(string(format)), "format", args2);
1911
2136
  }
2137
+ /** `t ??= v`: `if t == nil then t = v end`, which no Luau has an
2138
+ * operator for. `v` is read only where `t` is nil. As in `a += b` for
2139
+ * Lua 5.1, what addresses the target is read once: an object or key
2140
+ * that is not a plain name goes into a local first. */
2141
+ nullishAssignment(node) {
2142
+ const { before, target } = this.targetOnce(node.target);
2143
+ const statement = ifThen(binary("==", target, nil()), [assign([target], [this.expression(node.value)])]);
2144
+ return before.length ? [doBlock([...before, statement])] : [statement];
2145
+ }
2146
+ /** `t += v` where only the values can say whether it joins or adds:
2147
+ * `t = tilua_add(t, v)`, with what addresses `t` read once. */
2148
+ dynamicAddition(node) {
2149
+ const { before, target } = this.targetOnce(node.target);
2150
+ const statement = assign([target], [call(this.helper("add"), [target, this.keptToOne(this.expression(node.value))])]);
2151
+ return before.length ? [doBlock([...before, statement])] : [statement];
2152
+ }
2153
+ /** An assignment's target, as an expression that may be read and written
2154
+ * freely: an object or key that is not a plain name goes into a local
2155
+ * first, so that `t[next()]` advances once. */
2156
+ targetOnce(node) {
2157
+ const before = [];
2158
+ const once = (expression, name) => {
2159
+ if (expression.type === "Identifier" || expression.type === "StringLiteral" || expression.type === "NumberLiteral") return expression;
2160
+ const local2 = this.names.fresh(name);
2161
+ before.push(local([local2], [expression]));
2162
+ return identifier(local2);
2163
+ };
2164
+ let target;
2165
+ if (node.type === "MemberExpression") {
2166
+ target = member(once(this.expression(node.object), "target"), node.property.name);
2167
+ } else if (node.type === "IndexExpression") {
2168
+ const object2 = once(this.expression(node.object), "target");
2169
+ target = index(object2, once(this.expression(node.index), "key"));
2170
+ } else {
2171
+ target = this.expression(node);
2172
+ }
2173
+ return { before, target };
2174
+ }
1912
2175
  /** `a += b` for Lua 5.1, which has no compound assignment: `a = a + b`.
1913
2176
  *
1914
2177
  * The target has to be read and written, and writing it out twice would
1915
2178
  * evaluate whatever addresses it twice — `t[next()] += 1` would advance
1916
2179
  * twice and add to the wrong slot. So anything but a plain name has its
1917
2180
  * object and key taken into locals first, and both halves use those. */
1918
- compoundAssignment51(node) {
1919
- const operator = node.operator.slice(0, -1);
2181
+ compoundAssignment51(node, written = node.operator) {
2182
+ const operator = written.slice(0, -1);
1920
2183
  const before = [];
1921
2184
  let target;
1922
2185
  if (node.target.type === "MemberExpression" || node.target.type === "IndexExpression") {
@@ -2115,6 +2378,7 @@ function optionalChain(node) {
2115
2378
  if (first < 0) return void 0;
2116
2379
  return { base: linkObject(spine[first]), links: spine.slice(first) };
2117
2380
  }
2381
+ var LOOPS = /* @__PURE__ */ new Set(["WhileStatement", "RepeatStatement", "NumericForStatement", "GenericForStatement"]);
2118
2382
  function usesVararg(node) {
2119
2383
  if (Array.isArray(node)) return node.some(usesVararg);
2120
2384
  if (!node || typeof node !== "object") return false;
@@ -2982,7 +3246,7 @@ function analyzeModules(modules, config2) {
2982
3246
  });
2983
3247
  for (const d of types.diagnostics) {
2984
3248
  const at = d.node;
2985
- said.push({ file, message: d.message, line: at.line.start, column: at.column.start, category: "type" });
3249
+ said.push({ file, message: d.message, line: at.line.start, column: at.column.start, category: "type", severity: d.severity });
2986
3250
  }
2987
3251
  const result2 = { types, diagnostics: said };
2988
3252
  if (partials === before) {
@@ -3111,7 +3375,7 @@ async function main(from) {
3111
3375
  outFile: entryFile !== void 0 ? (0, import_node_path3.basename)(entryFile) : void 0
3112
3376
  });
3113
3377
  for (const d of result2.diagnostics) {
3114
- console.error(`${(0, import_node_path3.relative)(process.cwd(), d.file)}:${d.line}:${d.column} ${d.message}`);
3378
+ console.error(`${(0, import_node_path3.relative)(process.cwd(), d.file)}:${d.line}:${d.column} ${d.severity === "warning" ? "warning: " : ""}${d.message}`);
3115
3379
  }
3116
3380
  if (result2.code === void 0) {
3117
3381
  console.error("no bundle written");
@@ -3123,7 +3387,7 @@ async function main(from) {
3123
3387
  (0, import_node_fs4.writeFileSync)(target, file.code);
3124
3388
  console.log(`${target}: ${file.modules.length} module${file.modules.length === 1 ? "" : "s"}`);
3125
3389
  }
3126
- process.exit(result2.diagnostics.length ? 1 : 0);
3390
+ process.exit(result2.diagnostics.some((d) => d.severity !== "warning") ? 1 : 0);
3127
3391
  }
3128
3392
  main(entry).catch((error) => {
3129
3393
  console.error(error instanceof Error ? error.message : error);
package/dist/cli.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  bundle,
4
4
  resolveConfig
5
- } from "./chunk-3J2QMA4W.js";
5
+ } from "./chunk-EQE22LX7.js";
6
6
 
7
7
  // src/cli.ts
8
8
  import { mkdirSync, writeFileSync } from "fs";
@@ -57,7 +57,7 @@ async function main(from) {
57
57
  outFile: entryFile !== void 0 ? basename(entryFile) : void 0
58
58
  });
59
59
  for (const d of result.diagnostics) {
60
- console.error(`${relative(process.cwd(), d.file)}:${d.line}:${d.column} ${d.message}`);
60
+ console.error(`${relative(process.cwd(), d.file)}:${d.line}:${d.column} ${d.severity === "warning" ? "warning: " : ""}${d.message}`);
61
61
  }
62
62
  if (result.code === void 0) {
63
63
  console.error("no bundle written");
@@ -69,7 +69,7 @@ async function main(from) {
69
69
  writeFileSync(target, file.code);
70
70
  console.log(`${target}: ${file.modules.length} module${file.modules.length === 1 ? "" : "s"}`);
71
71
  }
72
- process.exit(result.diagnostics.length ? 1 : 0);
72
+ process.exit(result.diagnostics.some((d) => d.severity !== "warning") ? 1 : 0);
73
73
  }
74
74
  main(entry).catch((error) => {
75
75
  console.error(error instanceof Error ? error.message : error);