lemmascript 0.5.17 → 0.5.18
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/package.json +1 -1
- package/tools/dist/narrow.js +2 -2
- package/tools/dist/resolve.js +5 -2
- package/tools/dist/typedir.js +6 -0
package/package.json
CHANGED
package/tools/dist/narrow.js
CHANGED
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
* (early-return, let-cond) run in `walkStmts` so they can consume the rest
|
|
35
35
|
* of the block.
|
|
36
36
|
*/
|
|
37
|
+
import { isTerminatorKind } from "./typedir.js";
|
|
37
38
|
import { freshName } from "./names.js";
|
|
38
39
|
// ── Optional-check detection ────────────────────────────────
|
|
39
40
|
/** Counter for naming optChain binders. Reset per module. */
|
|
@@ -918,8 +919,7 @@ function parseNegativeDiscriminantCond(cond) {
|
|
|
918
919
|
function isTerminating(stmts) {
|
|
919
920
|
if (stmts.length === 0)
|
|
920
921
|
return false;
|
|
921
|
-
|
|
922
|
-
return last.kind === "return" || last.kind === "throw" || last.kind === "break" || last.kind === "continue";
|
|
922
|
+
return isTerminatorKind(stmts[stmts.length - 1].kind);
|
|
923
923
|
}
|
|
924
924
|
/** Rule (list-level): consecutive `if (x.kind === "v") ...` chain → tagMatch.
|
|
925
925
|
* Walks consecutive top-level ifs on the same discriminator var; the first
|
package/tools/dist/resolve.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Uses linked environments (Scheme-style) for lexical scoping.
|
|
5
5
|
* No mutation — each let extends the chain, lookup walks it.
|
|
6
6
|
*/
|
|
7
|
-
import { isBigInt, tyEqual } from "./typedir.js";
|
|
7
|
+
import { isBigInt, tyEqual, isTerminatorKind } from "./typedir.js";
|
|
8
8
|
import { parseTsType, tyToCanonical } from "./types.js";
|
|
9
9
|
import { parseExpr } from "./specparser.js";
|
|
10
10
|
import { freshName } from "./names.js";
|
|
@@ -1263,9 +1263,12 @@ function resolveBlock(stmts, ctx) {
|
|
|
1263
1263
|
env = nextEnv;
|
|
1264
1264
|
// Flow narrowing: if (x === undefined) { return } narrows x for rest of block.
|
|
1265
1265
|
// Also handles compound: if (x === undefined || y === undefined) { return }
|
|
1266
|
+
// Any terminator counts (return/throw/break/continue — same set as narrow's
|
|
1267
|
+
// isTerminating): each exits the current block, so the rest of the block
|
|
1268
|
+
// only runs when the guard was false.
|
|
1266
1269
|
// Field chains are excluded — resolve can't substitute in statement lists;
|
|
1267
1270
|
// transform's emitOptionalMatch handles field chains in statement contexts.
|
|
1268
|
-
if (s.kind === "if" && s.then.length > 0 && s.then[s.then.length - 1].kind
|
|
1271
|
+
if (s.kind === "if" && s.then.length > 0 && isTerminatorKind(s.then[s.then.length - 1].kind) && s.else.length === 0) {
|
|
1269
1272
|
const narrowings = collectEarlyReturnNarrowings(s.cond, withEnv(ctx, env));
|
|
1270
1273
|
for (const n of narrowings) {
|
|
1271
1274
|
env = extend(env, n.varName, n.innerTy);
|
package/tools/dist/typedir.js
CHANGED
|
@@ -44,3 +44,9 @@ export function tyEqual(a, b) {
|
|
|
44
44
|
case "unknown": return true; // no payload
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
|
+
/** Statement kinds that unconditionally leave the enclosing block. Shared by
|
|
48
|
+
* resolve (block-tail narrowing) and narrow (isTerminating); works on raw and
|
|
49
|
+
* typed IR alike since both use these kind strings. */
|
|
50
|
+
export function isTerminatorKind(kind) {
|
|
51
|
+
return kind === "return" || kind === "throw" || kind === "break" || kind === "continue";
|
|
52
|
+
}
|