lemmascript 0.5.21 → 0.5.22
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/extract.js +24 -8
- package/tools/dist/transform.js +3 -2
package/package.json
CHANGED
package/tools/dist/extract.js
CHANGED
|
@@ -2028,6 +2028,17 @@ export function extractModule(sourceFile) {
|
|
|
2028
2028
|
// here), deduped by qualified name.
|
|
2029
2029
|
_externs.clear();
|
|
2030
2030
|
_externSigTypes.length = 0;
|
|
2031
|
+
// Match a `//@ <kw>` directive only as the first non-whitespace on a line,
|
|
2032
|
+
// so prose mentioning an annotation does not activate it.
|
|
2033
|
+
function hasLineDirective(text, kw) {
|
|
2034
|
+
return new RegExp(String.raw `^[ \t]*//@ ${kw}\b`, "m").test(text);
|
|
2035
|
+
}
|
|
2036
|
+
// Declaration-level directives must be attached as leading comments. Do
|
|
2037
|
+
// not scan a function's whole body: a statement-level `//@ skip` inside it
|
|
2038
|
+
// must not omit the enclosing function.
|
|
2039
|
+
function hasLeadingDirective(node, kw) {
|
|
2040
|
+
return node.getLeadingCommentRanges().some(r => hasLineDirective(r.getText(), kw));
|
|
2041
|
+
}
|
|
2031
2042
|
// Share the module's ts-morph Project with parseTsType (scratch source file
|
|
2032
2043
|
// for type-string parsing). Done before declare-type parsing so any
|
|
2033
2044
|
// parseTsType call downstream uses the same Project.
|
|
@@ -2124,6 +2135,8 @@ export function extractModule(sourceFile) {
|
|
|
2124
2135
|
const constants = [];
|
|
2125
2136
|
for (const stmt of sourceFile.getStatements()) {
|
|
2126
2137
|
if (Node.isVariableStatement(stmt)) {
|
|
2138
|
+
if (hasLeadingDirective(stmt, "skip"))
|
|
2139
|
+
continue;
|
|
2127
2140
|
for (const decl of stmt.getDeclarationList().getDeclarations()) {
|
|
2128
2141
|
if (stmt.getDeclarationList().getFlags() & 2 /* const */) {
|
|
2129
2142
|
const init = decl.getInitializer();
|
|
@@ -2206,11 +2219,9 @@ export function extractModule(sourceFile) {
|
|
|
2206
2219
|
// regex — but its callers should still be verifiable against an
|
|
2207
2220
|
// uninterpreted predicate. Parallel to auto-extern for cross-file calls,
|
|
2208
2221
|
// and emitted the same way (`function {:axiom} foo(...)` in Dafny).
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
function hasLineDirective(text, kw) {
|
|
2213
|
-
return new RegExp(String.raw `^[ \t]*//@ ${kw}\b`, "m").test(text);
|
|
2222
|
+
function hasSkip(f) {
|
|
2223
|
+
return hasLeadingDirective(f.parentStmt ?? f.node, "skip")
|
|
2224
|
+
|| (!!f.parentStmt && hasLeadingDirective(f.node, "skip"));
|
|
2214
2225
|
}
|
|
2215
2226
|
function hasExtern(f) {
|
|
2216
2227
|
if (hasLineDirective(f.node.getFullText(), "extern"))
|
|
@@ -2243,7 +2254,7 @@ export function extractModule(sourceFile) {
|
|
|
2243
2254
|
return null;
|
|
2244
2255
|
}
|
|
2245
2256
|
for (const f of allFns) {
|
|
2246
|
-
if (!hasExtern(f))
|
|
2257
|
+
if (hasSkip(f) || !hasExtern(f))
|
|
2247
2258
|
continue;
|
|
2248
2259
|
const qualified = externName(f) ?? f.name;
|
|
2249
2260
|
const flat = qualified.replace(/\./g, "_");
|
|
@@ -2280,8 +2291,9 @@ export function extractModule(sourceFile) {
|
|
|
2280
2291
|
}
|
|
2281
2292
|
return false;
|
|
2282
2293
|
}
|
|
2283
|
-
const
|
|
2284
|
-
const
|
|
2294
|
+
const nonExternFns = allFns.filter(f => !hasSkip(f) && !hasExtern(f));
|
|
2295
|
+
const hasVerifiedClassMethod = sourceFile.getClasses().some(cls => !hasLeadingDirective(cls, "skip") && cls.getMethods().some(method => !hasLeadingDirective(method, "skip") && hasLineDirective(method.getFullText(), "verify")));
|
|
2296
|
+
const hasVerifyDirective = nonExternFns.some(hasVerify) || hasVerifiedClassMethod;
|
|
2285
2297
|
const fnsToExtract = hasVerifyDirective ? nonExternFns.filter(hasVerify) : nonExternFns;
|
|
2286
2298
|
// `//@ autohavoc` — enable the auto-havoc abstraction (see autohavoc.ts).
|
|
2287
2299
|
// File-level: a directive at column 0 (top of file) enables it for every
|
|
@@ -2795,8 +2807,12 @@ export function extractModule(sourceFile) {
|
|
|
2795
2807
|
// Extract classes with //@ verify methods
|
|
2796
2808
|
const classes = [];
|
|
2797
2809
|
for (const cls of sourceFile.getClasses()) {
|
|
2810
|
+
if (hasLeadingDirective(cls, "skip"))
|
|
2811
|
+
continue;
|
|
2798
2812
|
const methods = [];
|
|
2799
2813
|
for (const method of cls.getMethods()) {
|
|
2814
|
+
if (hasLeadingDirective(method, "skip"))
|
|
2815
|
+
continue;
|
|
2800
2816
|
if (!method.getFullText().includes('//@ verify'))
|
|
2801
2817
|
continue;
|
|
2802
2818
|
methods.push(extractFunction(method));
|
package/tools/dist/transform.js
CHANGED
|
@@ -2525,7 +2525,8 @@ export function transformModule(mod, specImport, moduleBaseOverride) {
|
|
|
2525
2525
|
};
|
|
2526
2526
|
});
|
|
2527
2527
|
// Def file: Velvet methods
|
|
2528
|
-
// Pure functions get a thin wrapper
|
|
2528
|
+
// Pure functions get a thin wrapper. Lean keeps pure definitions in the
|
|
2529
|
+
// `Pure` namespace; Dafny flattens that namespace, so its call is unqualified.
|
|
2529
2530
|
// def-by-method functions also skip their method wrappers
|
|
2530
2531
|
const pureDefNames = new Set([...pureDefs.map(d => d.name), ...defByMethods.map(d => d.name)]);
|
|
2531
2532
|
const methods = mod.functions.map(fn => {
|
|
@@ -2539,7 +2540,7 @@ export function transformModule(mod, specImport, moduleBaseOverride) {
|
|
|
2539
2540
|
}
|
|
2540
2541
|
_forofCounters.clear();
|
|
2541
2542
|
let body = pureDefNames.has(fn.name)
|
|
2542
|
-
? [{ kind: "return", value: { kind: "app", fn: `Pure.${fn.name}
|
|
2543
|
+
? [{ kind: "return", value: { kind: "app", fn: _opts.backend === "lean" ? `Pure.${fn.name}` : fn.name, args: fn.params.map(p => ({ kind: "var", name: p.name })) } }]
|
|
2543
2544
|
: promoteAssignedLets(transformStmts(fn.body, mod.typeDecls));
|
|
2544
2545
|
// Lean-only method-body rewrites (Velvet can't WP-synthesize monadic matches
|
|
2545
2546
|
// and forbids `return` in loops):
|