lemmascript 0.2.0 → 0.3.1
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/README.md +3 -2
- package/package.json +1 -1
- package/tools/dist/dafny-commands.js +4 -3
- package/tools/dist/dafny-emit.js +206 -161
- package/tools/dist/extract.js +483 -51
- package/tools/dist/lean-emit.js +6 -2
- package/tools/dist/lsc.js +28 -5
- package/tools/dist/resolve.js +353 -113
- package/tools/dist/specparser.js +5 -2
- package/tools/dist/transform.js +452 -117
- package/tools/dist/types.js +14 -1
package/tools/dist/lean-emit.js
CHANGED
|
@@ -51,7 +51,7 @@ function escapeName(name) {
|
|
|
51
51
|
const PREC = {
|
|
52
52
|
"→": 1, "∨": 2, "∧": 3,
|
|
53
53
|
"=": 4, "≠": 4, "≥": 4, "≤": 4, ">": 4, "<": 4,
|
|
54
|
-
"+": 5, "-": 5, "*": 6, "/": 6, "%": 6,
|
|
54
|
+
"+": 5, "-": 5, "++": 5, "arrayConcat": 5, "*": 6, "/": 6, "%": 6,
|
|
55
55
|
};
|
|
56
56
|
function prec(op) { return PREC[op] ?? 10; }
|
|
57
57
|
// ── Method call → Lean syntax ───────────────────────────────
|
|
@@ -143,7 +143,8 @@ function emitExpr(e, parentPrec) {
|
|
|
143
143
|
return `-${e.expr.value}`;
|
|
144
144
|
return `(-${emitExpr(e.expr)})`;
|
|
145
145
|
case "binop": {
|
|
146
|
-
const
|
|
146
|
+
const op = e.op === "arrayConcat" ? "++" : e.op;
|
|
147
|
+
const s = `${emitExpr(e.left, prec(e.op))} ${op} ${emitExpr(e.right, prec(e.op))}`;
|
|
147
148
|
return (parentPrec !== undefined && prec(e.op) < parentPrec) ? `(${s})` : s;
|
|
148
149
|
}
|
|
149
150
|
case "implies": {
|
|
@@ -317,6 +318,9 @@ function emitDecl(d) {
|
|
|
317
318
|
lines.push(`deriving ${d.deriving.join(", ")}`);
|
|
318
319
|
return lines.join("\n");
|
|
319
320
|
}
|
|
321
|
+
case "type-alias": {
|
|
322
|
+
return `abbrev ${d.name} := ${tyToLean(d.target)}`;
|
|
323
|
+
}
|
|
320
324
|
case "def": {
|
|
321
325
|
const params = d.params.map(p => `(${escapeName(p.name)} : ${tyToLean(p.type)})`).join(" ");
|
|
322
326
|
return `def ${d.name} ${params} : ${tyToLean(d.returnType)} :=\n${emitPureExpr(d.body, 1)}`;
|
package/tools/dist/lsc.js
CHANGED
|
@@ -9,7 +9,7 @@ import { existsSync } from "fs";
|
|
|
9
9
|
import path from "path";
|
|
10
10
|
import { extractModule } from "./extract.js";
|
|
11
11
|
import { resolveModule } from "./resolve.js";
|
|
12
|
-
import {
|
|
12
|
+
import { transformModuleLean, transformModuleDafny } from "./transform.js";
|
|
13
13
|
import { emitLeanFile } from "./lean-emit.js";
|
|
14
14
|
import { emitDafnyFile } from "./dafny-emit.js";
|
|
15
15
|
import { dafnyGen, dafnyCheckDiff, dafnyVerify, dafnyRegen } from "./dafny-commands.js";
|
|
@@ -17,7 +17,7 @@ import { leanGen, leanCheck } from "./lean-commands.js";
|
|
|
17
17
|
function main() {
|
|
18
18
|
const args = process.argv.slice(2);
|
|
19
19
|
const backendIdx = args.findIndex(a => a.startsWith("--backend="));
|
|
20
|
-
let backend = "
|
|
20
|
+
let backend = "dafny";
|
|
21
21
|
if (backendIdx >= 0) {
|
|
22
22
|
const val = args[backendIdx].split("=")[1];
|
|
23
23
|
if (val !== "lean" && val !== "dafny") {
|
|
@@ -33,6 +33,12 @@ function main() {
|
|
|
33
33
|
timeLimit = parseInt(args[timeLimitIdx].split("=")[1]);
|
|
34
34
|
args.splice(timeLimitIdx, 1);
|
|
35
35
|
}
|
|
36
|
+
const extraFlagsIdx = args.findIndex(a => a.startsWith("--extra-flags="));
|
|
37
|
+
let extraFlags;
|
|
38
|
+
if (extraFlagsIdx >= 0) {
|
|
39
|
+
extraFlags = args[extraFlagsIdx].split("=").slice(1).join("=");
|
|
40
|
+
args.splice(extraFlagsIdx, 1);
|
|
41
|
+
}
|
|
36
42
|
const [cmd, filePath] = args;
|
|
37
43
|
if (!cmd || !filePath) {
|
|
38
44
|
console.error("Usage: lsc <gen|check|regen|extract> [--backend=lean|dafny] <file.ts>");
|
|
@@ -43,8 +49,25 @@ function main() {
|
|
|
43
49
|
console.error(`File not found: ${absPath}`);
|
|
44
50
|
process.exit(1);
|
|
45
51
|
}
|
|
46
|
-
|
|
52
|
+
// Find nearest tsconfig.json for import resolution; fall back to bare options
|
|
53
|
+
function findTsConfig(from) {
|
|
54
|
+
let dir = path.dirname(from);
|
|
55
|
+
while (true) {
|
|
56
|
+
const candidate = path.join(dir, "tsconfig.json");
|
|
57
|
+
if (existsSync(candidate))
|
|
58
|
+
return candidate;
|
|
59
|
+
const parent = path.dirname(dir);
|
|
60
|
+
if (parent === dir)
|
|
61
|
+
return undefined;
|
|
62
|
+
dir = parent;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const tsConfigFilePath = findTsConfig(absPath);
|
|
66
|
+
const project = tsConfigFilePath
|
|
67
|
+
? new Project({ tsConfigFilePath })
|
|
68
|
+
: new Project({ compilerOptions: { strict: true, target: ScriptTarget.ESNext, lib: ["lib.esnext.d.ts"] } });
|
|
47
69
|
const sourceFile = project.addSourceFileAtPath(absPath);
|
|
70
|
+
project.resolveSourceFileDependencies();
|
|
48
71
|
// Check //@ backend directive — skip if backend doesn't match
|
|
49
72
|
const backendDirective = sourceFile.getFullText().match(/\/\/@ backend (\w+)/);
|
|
50
73
|
if (backendDirective && backendDirective[1] !== backend) {
|
|
@@ -84,7 +107,7 @@ function main() {
|
|
|
84
107
|
dafnyGen(genPath, dfyPath, text);
|
|
85
108
|
if (!dafnyCheckDiff(genPath, dfyPath))
|
|
86
109
|
process.exit(1);
|
|
87
|
-
if (!dafnyVerify(dfyPath, dir, timeLimit))
|
|
110
|
+
if (!dafnyVerify(dfyPath, dir, timeLimit, extraFlags))
|
|
88
111
|
process.exit(1);
|
|
89
112
|
return;
|
|
90
113
|
}
|
|
@@ -98,7 +121,7 @@ function main() {
|
|
|
98
121
|
// ── Lean backend ──────────────────────────────────────────
|
|
99
122
|
const specPath = path.join(dir, `${base}.spec.lean`);
|
|
100
123
|
const specImport = existsSync(specPath) ? `«${base}.spec»` : undefined;
|
|
101
|
-
const { typesFile, defFile } =
|
|
124
|
+
const { typesFile, defFile } = transformModuleLean(typed, specImport);
|
|
102
125
|
const typesPath = typesFile ? path.join(dir, `${base}.types.lean`) : null;
|
|
103
126
|
const typesText = typesFile ? emitLeanFile(typesFile) : null;
|
|
104
127
|
const defPath = path.join(dir, `${base}.def.lean`);
|