lemmascript 0.5.14 → 0.5.15
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/dafny-emit.js +21 -4
- package/tools/dist/lean-emit.js +18 -2
- package/tools/dist/lsc.js +2 -1
package/package.json
CHANGED
package/tools/dist/dafny-emit.js
CHANGED
|
@@ -1083,22 +1083,39 @@ const SEQ_SORT_BY = `function {:axiom} SeqSortBy<T(==,!new)>(s: seq<T>, cmp: (T,
|
|
|
1083
1083
|
ensures multiset(SeqSortBy(s, cmp)) == multiset(s)
|
|
1084
1084
|
ensures |SeqSortBy(s, cmp)| == |s|
|
|
1085
1085
|
ensures forall i: int, j: int :: 0 <= i <= j < |SeqSortBy(s, cmp)| ==> cmp(SeqSortBy(s, cmp)[i], SeqSortBy(s, cmp)[j]) <= 0`;
|
|
1086
|
-
|
|
1086
|
+
// TS/JS String.prototype.trim() strips ECMAScript WhiteSpace ∪ LineTerminator:
|
|
1087
|
+
// Unicode general-category Zs plus TAB/VT/FF/CR/LF, LS/PS, and the BOM — NOT just
|
|
1088
|
+
// U+0020, and NOT U+0085 (NEL, which is Cc). See
|
|
1089
|
+
// https://tc39.es/ecma262/#sec-white-space and
|
|
1090
|
+
// https://tc39.es/ecma262/#sec-line-terminators.
|
|
1091
|
+
// `\\U{..}` are Dafny char escapes (not JS: the string
|
|
1092
|
+
// is emitted verbatim), so the enumeration below is Dafny source, not decoded.
|
|
1093
|
+
const STRING_TRIM = `predicate IsJSWhitespace(c: char)
|
|
1094
|
+
{
|
|
1095
|
+
c == '\\U{0009}' || c == '\\U{000A}' || c == '\\U{000B}' || c == '\\U{000C}' || c == '\\U{000D}' ||
|
|
1096
|
+
c == '\\U{0020}' || c == '\\U{00A0}' || c == '\\U{1680}' ||
|
|
1097
|
+
('\\U{2000}' <= c <= '\\U{200A}') ||
|
|
1098
|
+
c == '\\U{2028}' || c == '\\U{2029}' || c == '\\U{202F}' || c == '\\U{205F}' ||
|
|
1099
|
+
c == '\\U{3000}' || c == '\\U{FEFF}'
|
|
1100
|
+
}
|
|
1101
|
+
|
|
1102
|
+
function StringTrimLeft(s: string): string
|
|
1087
1103
|
ensures |StringTrimLeft(s)| <= |s|
|
|
1088
|
-
ensures StringTrimLeft(s) == "" || (|StringTrimLeft(s)| > 0 && StringTrimLeft(s)[0]
|
|
1104
|
+
ensures StringTrimLeft(s) == "" || (|StringTrimLeft(s)| > 0 && !IsJSWhitespace(StringTrimLeft(s)[0]))
|
|
1089
1105
|
decreases |s|
|
|
1090
1106
|
{
|
|
1091
1107
|
if |s| == 0 then ""
|
|
1092
|
-
else if s[0]
|
|
1108
|
+
else if IsJSWhitespace(s[0]) then StringTrimLeft(s[1..])
|
|
1093
1109
|
else s
|
|
1094
1110
|
}
|
|
1095
1111
|
|
|
1096
1112
|
function StringTrimRight(s: string): string
|
|
1097
1113
|
ensures |StringTrimRight(s)| <= |s|
|
|
1114
|
+
ensures StringTrimRight(s) == "" || (|StringTrimRight(s)| > 0 && !IsJSWhitespace(StringTrimRight(s)[|StringTrimRight(s)|-1]))
|
|
1098
1115
|
decreases |s|
|
|
1099
1116
|
{
|
|
1100
1117
|
if |s| == 0 then ""
|
|
1101
|
-
else if s[|s|-1]
|
|
1118
|
+
else if IsJSWhitespace(s[|s|-1]) then StringTrimRight(s[..|s|-1])
|
|
1102
1119
|
else s
|
|
1103
1120
|
}
|
|
1104
1121
|
|
package/tools/dist/lean-emit.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Lean emitter — IR → Lean text.
|
|
3
|
-
*
|
|
2
|
+
* Lean emitter — IR → Lean text. Beyond serialization it makes type-driven
|
|
3
|
+
* decisions: Bool-vs-Prop connectives, dropping Repr/DecidableEq for
|
|
4
|
+
* opaque-tainted types, discriminator/destructor lowering, method dispatch,
|
|
5
|
+
* and support-import selection.
|
|
4
6
|
*/
|
|
5
7
|
import { anyExpr, usesNameInDecl, patternBinders } from "./ir.js";
|
|
6
8
|
import { freshName } from "./names.js";
|
|
@@ -760,6 +762,20 @@ function emitPureExpr(e, indent) {
|
|
|
760
762
|
}
|
|
761
763
|
}
|
|
762
764
|
// ── File emission ────────────────────────────────────────────
|
|
765
|
+
/** Reset per-module emitter state. Call once per module before the types file
|
|
766
|
+
* (not between types and def — the def file reads the types file's registries). */
|
|
767
|
+
export function resetLeanModule() {
|
|
768
|
+
_resultName = "res";
|
|
769
|
+
_unionCtors.clear();
|
|
770
|
+
_opaqueNames.clear();
|
|
771
|
+
_opaqueNames.add("Unknown");
|
|
772
|
+
_typeRefs.clear();
|
|
773
|
+
_taintedTypes.clear();
|
|
774
|
+
_needsJSString = false;
|
|
775
|
+
_needsUnknown = false;
|
|
776
|
+
_unknownEmitted = false;
|
|
777
|
+
_boolCtx = false;
|
|
778
|
+
}
|
|
763
779
|
export function emitLeanFile(file) {
|
|
764
780
|
_needsJSString = false;
|
|
765
781
|
_needsUnknown = false;
|
package/tools/dist/lsc.js
CHANGED
|
@@ -15,7 +15,7 @@ import { narrowModule } from "./narrow.js";
|
|
|
15
15
|
import { autoHavocModule } from "./autohavoc.js";
|
|
16
16
|
import { transformModuleLean, transformModuleDafny } from "./transform.js";
|
|
17
17
|
import { peepholeModule } from "./peephole.js";
|
|
18
|
-
import { emitLeanFile } from "./lean-emit.js";
|
|
18
|
+
import { emitLeanFile, resetLeanModule } from "./lean-emit.js";
|
|
19
19
|
import { emitDafnyFile } from "./dafny-emit.js";
|
|
20
20
|
import { dafnyGen, dafnyCheckDiff, dafnyVerify, dafnyRegen } from "./dafny-commands.js";
|
|
21
21
|
import { leanGen, leanCheck } from "./lean-commands.js";
|
|
@@ -261,6 +261,7 @@ function runFile(cmd, filePath, backend, timeLimit, extraFlags) {
|
|
|
261
261
|
if (typesFile)
|
|
262
262
|
typesFile = peepholeModule(typesFile, "lean");
|
|
263
263
|
defFile = peepholeModule(defFile, "lean");
|
|
264
|
+
resetLeanModule(); // clear per-module emitter state so batch mode doesn't leak into this module
|
|
264
265
|
const typesPath = typesFile ? path.join(dir, `${leanBase}.types.lean`) : null;
|
|
265
266
|
const typesText = typesFile ? emitLeanFile(typesFile) : null;
|
|
266
267
|
const defPath = path.join(dir, `${leanBase}.def.lean`);
|