lemmascript 0.1.0 → 0.3.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/README.md +25 -31
- package/package.json +1 -1
- package/tools/dist/dafny-commands.js +47 -53
- package/tools/dist/dafny-emit.js +495 -93
- package/tools/dist/extract.js +847 -46
- package/tools/dist/ir.js +2 -2
- package/tools/dist/lean-commands.js +35 -0
- package/tools/dist/lean-emit.js +397 -0
- package/tools/dist/lsc.js +62 -44
- package/tools/dist/resolve.js +500 -34
- package/tools/dist/specparser.js +66 -9
- package/tools/dist/transform.js +813 -202
- package/tools/dist/types.js +59 -13
package/tools/dist/specparser.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Spec expression parser.
|
|
3
3
|
* Parses //@ annotation expressions into RawExpr AST nodes.
|
|
4
4
|
*/
|
|
5
|
-
const MULTI_OPS = ["==>", "===", "!==", ">=", "<=", "&&", "||"];
|
|
5
|
+
const MULTI_OPS = ["==>", "===", "!==", "==", "!=", ">=", "<=", "&&", "||"];
|
|
6
6
|
function tokenize(input) {
|
|
7
7
|
const tokens = [];
|
|
8
8
|
let i = 0;
|
|
@@ -28,10 +28,23 @@ function tokenize(input) {
|
|
|
28
28
|
continue;
|
|
29
29
|
}
|
|
30
30
|
if (/[0-9]/.test(input[i])) {
|
|
31
|
-
let
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
let value;
|
|
32
|
+
if (input[i] === "0" && i + 1 < input.length && input[i + 1] === "x") {
|
|
33
|
+
i += 2;
|
|
34
|
+
let hex = "";
|
|
35
|
+
while (i < input.length && /[0-9a-fA-F]/.test(input[i]))
|
|
36
|
+
hex += input[i++];
|
|
37
|
+
value = parseInt(hex, 16);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
let dec = "";
|
|
41
|
+
while (i < input.length && /[0-9]/.test(input[i]))
|
|
42
|
+
dec += input[i++];
|
|
43
|
+
value = parseInt(dec, 10);
|
|
44
|
+
}
|
|
45
|
+
if (i < input.length && input[i] === "n")
|
|
46
|
+
i++;
|
|
47
|
+
tokens.push({ type: "num", value });
|
|
35
48
|
continue;
|
|
36
49
|
}
|
|
37
50
|
if (/[a-zA-Z_]/.test(input[i])) {
|
|
@@ -116,9 +129,16 @@ class Parser {
|
|
|
116
129
|
parseCmp() {
|
|
117
130
|
const left = this.parseAdd();
|
|
118
131
|
const t = this.peek();
|
|
119
|
-
|
|
132
|
+
// 'in' as infix membership operator (set/seq/map): x in S
|
|
133
|
+
if (t?.type === "ident" && t.value === "in") {
|
|
134
|
+
this.advance();
|
|
135
|
+
return { kind: "binop", op: "in", left, right: this.parseAdd() };
|
|
136
|
+
}
|
|
137
|
+
if (t?.type === "op" && ["===", "!==", "==", "!=", ">=", "<=", ">", "<"].includes(t.value)) {
|
|
120
138
|
this.advance();
|
|
121
|
-
|
|
139
|
+
// Normalize == to ===, != to !== so downstream sees one spelling
|
|
140
|
+
const op = t.value === "==" ? "===" : t.value === "!=" ? "!==" : t.value;
|
|
141
|
+
return { kind: "binop", op, left, right: this.parseAdd() };
|
|
122
142
|
}
|
|
123
143
|
return left;
|
|
124
144
|
}
|
|
@@ -201,6 +221,34 @@ class Parser {
|
|
|
201
221
|
this.advance();
|
|
202
222
|
return { kind: "bool", value: false };
|
|
203
223
|
}
|
|
224
|
+
// new Set<T>() / new Map<K,V>()
|
|
225
|
+
if (t.value === "new") {
|
|
226
|
+
this.advance();
|
|
227
|
+
const name = this.expect("ident").value;
|
|
228
|
+
if (name !== "Set" && name !== "Map")
|
|
229
|
+
throw new Error(`Unsupported constructor: new ${name}`);
|
|
230
|
+
// Skip <T> or <K,V> type arguments
|
|
231
|
+
let tsType = name;
|
|
232
|
+
if (this.match("op", "<")) {
|
|
233
|
+
let depth = 1;
|
|
234
|
+
let typeArgs = "";
|
|
235
|
+
while (depth > 0) {
|
|
236
|
+
const next = this.advance();
|
|
237
|
+
if (next.value === "<")
|
|
238
|
+
depth++;
|
|
239
|
+
else if (next.value === ">") {
|
|
240
|
+
depth--;
|
|
241
|
+
if (depth === 0)
|
|
242
|
+
break;
|
|
243
|
+
}
|
|
244
|
+
typeArgs += next.value;
|
|
245
|
+
}
|
|
246
|
+
tsType = `${name}<${typeArgs}>`;
|
|
247
|
+
}
|
|
248
|
+
this.expect("punc", "(");
|
|
249
|
+
this.expect("punc", ")");
|
|
250
|
+
return { kind: "emptyCollection", collectionType: name, tsType };
|
|
251
|
+
}
|
|
204
252
|
if (t.value === "forall" || t.value === "exists") {
|
|
205
253
|
const q = t.value;
|
|
206
254
|
this.advance();
|
|
@@ -209,8 +257,6 @@ class Parser {
|
|
|
209
257
|
let varType = "int";
|
|
210
258
|
if (this.match("punc", ":")) {
|
|
211
259
|
const ty = this.expect("ident").value;
|
|
212
|
-
if (ty !== "nat" && ty !== "int")
|
|
213
|
-
throw new Error(`Unknown type '${ty}'`);
|
|
214
260
|
varType = ty;
|
|
215
261
|
}
|
|
216
262
|
this.expect("punc", ",");
|
|
@@ -227,6 +273,17 @@ class Parser {
|
|
|
227
273
|
this.expect("punc", ")");
|
|
228
274
|
return expr;
|
|
229
275
|
}
|
|
276
|
+
if (t.type === "punc" && t.value === "[") {
|
|
277
|
+
this.advance();
|
|
278
|
+
const elems = [];
|
|
279
|
+
if (!this.match("punc", "]")) {
|
|
280
|
+
elems.push(this.parseImplies());
|
|
281
|
+
while (this.match("punc", ","))
|
|
282
|
+
elems.push(this.parseImplies());
|
|
283
|
+
this.expect("punc", "]");
|
|
284
|
+
}
|
|
285
|
+
return { kind: "arrayLiteral", elems };
|
|
286
|
+
}
|
|
230
287
|
if (t.type === "punc" && t.value === "{") {
|
|
231
288
|
this.advance();
|
|
232
289
|
const fields = [];
|