@stevenvo780/st-lang 3.1.0 → 3.1.2

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.
Files changed (93) hide show
  1. package/README.md +3 -3
  2. package/dist/api.d.ts.map +1 -1
  3. package/dist/api.js +44 -9
  4. package/dist/api.js.map +1 -1
  5. package/dist/lexer/lexer.d.ts.map +1 -1
  6. package/dist/lexer/lexer.js +8 -0
  7. package/dist/lexer/lexer.js.map +1 -1
  8. package/dist/lexer/tokens.d.ts +2 -0
  9. package/dist/lexer/tokens.d.ts.map +1 -1
  10. package/dist/lexer/tokens.js +6 -0
  11. package/dist/lexer/tokens.js.map +1 -1
  12. package/dist/parser/parser.d.ts +4 -0
  13. package/dist/parser/parser.d.ts.map +1 -1
  14. package/dist/parser/parser.js +224 -92
  15. package/dist/parser/parser.js.map +1 -1
  16. package/dist/profiles/aristotelian/syllogistic.d.ts +1 -1
  17. package/dist/profiles/aristotelian/syllogistic.d.ts.map +1 -1
  18. package/dist/profiles/aristotelian/syllogistic.js +26 -8
  19. package/dist/profiles/aristotelian/syllogistic.js.map +1 -1
  20. package/dist/profiles/arithmetic/index.d.ts +1 -1
  21. package/dist/profiles/arithmetic/index.d.ts.map +1 -1
  22. package/dist/profiles/arithmetic/index.js +29 -7
  23. package/dist/profiles/arithmetic/index.js.map +1 -1
  24. package/dist/profiles/classical/first-order.d.ts +1 -1
  25. package/dist/profiles/classical/first-order.d.ts.map +1 -1
  26. package/dist/profiles/classical/first-order.js +32 -8
  27. package/dist/profiles/classical/first-order.js.map +1 -1
  28. package/dist/profiles/classical/propositional.d.ts +1 -1
  29. package/dist/profiles/classical/propositional.d.ts.map +1 -1
  30. package/dist/profiles/classical/propositional.js +464 -69
  31. package/dist/profiles/classical/propositional.js.map +1 -1
  32. package/dist/profiles/intuitionistic/propositional.d.ts +1 -1
  33. package/dist/profiles/intuitionistic/propositional.d.ts.map +1 -1
  34. package/dist/profiles/intuitionistic/propositional.js +33 -5
  35. package/dist/profiles/intuitionistic/propositional.js.map +1 -1
  36. package/dist/profiles/paraconsistent/belnap.d.ts +1 -2
  37. package/dist/profiles/paraconsistent/belnap.d.ts.map +1 -1
  38. package/dist/profiles/paraconsistent/belnap.js +25 -11
  39. package/dist/profiles/paraconsistent/belnap.js.map +1 -1
  40. package/dist/profiles/probabilistic/basic.d.ts +1 -1
  41. package/dist/profiles/probabilistic/basic.d.ts.map +1 -1
  42. package/dist/profiles/probabilistic/basic.js +29 -5
  43. package/dist/profiles/probabilistic/basic.js.map +1 -1
  44. package/dist/profiles/shared/base-profile.d.ts +1 -1
  45. package/dist/profiles/shared/base-profile.d.ts.map +1 -1
  46. package/dist/profiles/shared/base-profile.js +20 -3
  47. package/dist/profiles/shared/base-profile.js.map +1 -1
  48. package/dist/profiles/shared/tableau-engine.d.ts +4 -3
  49. package/dist/profiles/shared/tableau-engine.d.ts.map +1 -1
  50. package/dist/profiles/shared/tableau-engine.js +107 -15
  51. package/dist/profiles/shared/tableau-engine.js.map +1 -1
  52. package/dist/protocol/handler.d.ts +4 -0
  53. package/dist/protocol/handler.d.ts.map +1 -1
  54. package/dist/protocol/handler.js +133 -41
  55. package/dist/protocol/handler.js.map +1 -1
  56. package/dist/repl/repl.d.ts +2 -0
  57. package/dist/repl/repl.d.ts.map +1 -1
  58. package/dist/repl/repl.js +44 -19
  59. package/dist/repl/repl.js.map +1 -1
  60. package/dist/runtime/compat.d.ts +29 -0
  61. package/dist/runtime/compat.d.ts.map +1 -0
  62. package/dist/runtime/compat.js +819 -0
  63. package/dist/runtime/compat.js.map +1 -0
  64. package/dist/runtime/interpreter.d.ts +3 -0
  65. package/dist/runtime/interpreter.d.ts.map +1 -1
  66. package/dist/runtime/interpreter.js +133 -30
  67. package/dist/runtime/interpreter.js.map +1 -1
  68. package/dist/tests/cli.test.js +5 -1
  69. package/dist/tests/cli.test.js.map +1 -1
  70. package/dist/tests/compat.test.d.ts +2 -0
  71. package/dist/tests/compat.test.d.ts.map +1 -0
  72. package/dist/tests/compat.test.js +247 -0
  73. package/dist/tests/compat.test.js.map +1 -0
  74. package/dist/tests/core.test.js +41 -1
  75. package/dist/tests/core.test.js.map +1 -1
  76. package/dist/tests/parser.test.js +38 -0
  77. package/dist/tests/parser.test.js.map +1 -1
  78. package/dist/tests/profiles.test.js +8 -0
  79. package/dist/tests/profiles.test.js.map +1 -1
  80. package/dist/tests/protocol-text-layer.test.d.ts +2 -0
  81. package/dist/tests/protocol-text-layer.test.d.ts.map +1 -0
  82. package/dist/tests/protocol-text-layer.test.js +54 -0
  83. package/dist/tests/protocol-text-layer.test.js.map +1 -0
  84. package/dist/tests/stress-exhaustive.test.js +5 -1
  85. package/dist/tests/stress-exhaustive.test.js.map +1 -1
  86. package/dist/text-layer/compiler.d.ts.map +1 -1
  87. package/dist/text-layer/compiler.js +35 -8
  88. package/dist/text-layer/compiler.js.map +1 -1
  89. package/dist/types/index.d.ts +37 -3
  90. package/dist/types/index.d.ts.map +1 -1
  91. package/dist/types/index.js +42 -0
  92. package/dist/types/index.js.map +1 -1
  93. package/package.json +1 -3
@@ -0,0 +1,819 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.normalizeSTSource = normalizeSTSource;
4
+ exports.createReplCompatState = createReplCompatState;
5
+ exports.transformReplInput = transformReplInput;
6
+ const IDENTIFIER_RE = /^[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)*$/;
7
+ const BARE_ATOM_RE = /^[A-Z][A-Z0-9_]*$/;
8
+ function createTransformState() {
9
+ return {
10
+ nextId: 1,
11
+ knownFormulas: new Map(),
12
+ localScope: null,
13
+ hasPremiseBlock: false,
14
+ numberedLineNames: new Map(),
15
+ availableNumberedLines: new Set(),
16
+ pendingBareProofSteps: [],
17
+ pendingDerivedProofSteps: [],
18
+ };
19
+ }
20
+ function nextCompatName(state, prefix) {
21
+ return `__compat_${prefix}_${state.nextId++}`;
22
+ }
23
+ function beginLocalScope(state) {
24
+ if (!state.localScope) {
25
+ state.localScope = [];
26
+ }
27
+ }
28
+ function rememberFormula(state, name, formula, options) {
29
+ const previous = state.knownFormulas.get(name);
30
+ if (options?.local) {
31
+ beginLocalScope(state);
32
+ state.localScope?.push({ name, previous });
33
+ }
34
+ state.knownFormulas.set(name, formula.trim());
35
+ }
36
+ function closeLocalScope(state) {
37
+ if (!state.localScope) {
38
+ state.hasPremiseBlock = false;
39
+ return;
40
+ }
41
+ for (let index = state.localScope.length - 1; index >= 0; index -= 1) {
42
+ const binding = state.localScope[index];
43
+ if (binding.previous === undefined) {
44
+ state.knownFormulas.delete(binding.name);
45
+ }
46
+ else {
47
+ state.knownFormulas.set(binding.name, binding.previous);
48
+ }
49
+ }
50
+ state.localScope = null;
51
+ state.hasPremiseBlock = false;
52
+ }
53
+ function splitLineComment(line) {
54
+ let inString = false;
55
+ for (let index = 0; index < line.length; index += 1) {
56
+ const current = line[index];
57
+ const next = line[index + 1];
58
+ if (inString) {
59
+ if (current === '\\') {
60
+ index += 1;
61
+ continue;
62
+ }
63
+ if (current === '"') {
64
+ inString = false;
65
+ }
66
+ continue;
67
+ }
68
+ if (current === '"') {
69
+ inString = true;
70
+ continue;
71
+ }
72
+ if (current === '/' && next === '/') {
73
+ return {
74
+ code: line.slice(0, index),
75
+ comment: line.slice(index),
76
+ };
77
+ }
78
+ }
79
+ return { code: line, comment: '' };
80
+ }
81
+ function stripLeadingProofBars(code) {
82
+ if (/^\s*\|-/.test(code)) {
83
+ return { code, hadBars: false };
84
+ }
85
+ const match = code.match(/^(\s*(?:[|│]+\s*)+)(.*)$/);
86
+ if (!match) {
87
+ return { code, hadBars: false };
88
+ }
89
+ return {
90
+ code: `${match[1].match(/^\s*/)?.[0] ?? ''}${match[2]}`,
91
+ hadBars: true,
92
+ };
93
+ }
94
+ function appendComment(lines, comment) {
95
+ if (!comment || lines.length === 0) {
96
+ return lines;
97
+ }
98
+ const next = [...lines];
99
+ next[0] = `${next[0]} ${comment.trimStart()}`.trimEnd();
100
+ return next;
101
+ }
102
+ function splitTopLevel(value, delimiter = ',') {
103
+ const parts = [];
104
+ let current = '';
105
+ let depthParen = 0;
106
+ let depthBrace = 0;
107
+ let depthBracket = 0;
108
+ let inString = false;
109
+ for (let index = 0; index < value.length; index += 1) {
110
+ const char = value[index];
111
+ if (inString) {
112
+ current += char;
113
+ if (char === '\\' && index + 1 < value.length) {
114
+ current += value[index + 1];
115
+ index += 1;
116
+ continue;
117
+ }
118
+ if (char === '"') {
119
+ inString = false;
120
+ }
121
+ continue;
122
+ }
123
+ if (char === '"') {
124
+ inString = true;
125
+ current += char;
126
+ continue;
127
+ }
128
+ if (char === '(')
129
+ depthParen += 1;
130
+ if (char === ')')
131
+ depthParen = Math.max(0, depthParen - 1);
132
+ if (char === '{')
133
+ depthBrace += 1;
134
+ if (char === '}')
135
+ depthBrace = Math.max(0, depthBrace - 1);
136
+ if (char === '[')
137
+ depthBracket += 1;
138
+ if (char === ']')
139
+ depthBracket = Math.max(0, depthBracket - 1);
140
+ if (char === delimiter && depthParen === 0 && depthBrace === 0 && depthBracket === 0) {
141
+ const trimmed = current.trim();
142
+ if (trimmed) {
143
+ parts.push(trimmed);
144
+ }
145
+ current = '';
146
+ continue;
147
+ }
148
+ current += char;
149
+ }
150
+ const trimmed = current.trim();
151
+ if (trimmed) {
152
+ parts.push(trimmed);
153
+ }
154
+ return parts;
155
+ }
156
+ function compatProofLineName(lineNumber) {
157
+ return `__compat_line_${lineNumber}`;
158
+ }
159
+ function reserveNumberedLineName(state, lineNumber) {
160
+ const existing = state.numberedLineNames.get(lineNumber);
161
+ if (existing) {
162
+ return existing;
163
+ }
164
+ const name = compatProofLineName(lineNumber);
165
+ state.numberedLineNames.set(lineNumber, name);
166
+ return name;
167
+ }
168
+ function rememberNumberedLine(state, lineNumber, formula) {
169
+ const name = reserveNumberedLineName(state, lineNumber);
170
+ rememberFormula(state, name, formula);
171
+ state.availableNumberedLines.add(lineNumber);
172
+ return name;
173
+ }
174
+ function canEmitPendingDerivedStep(state, step) {
175
+ return step.refs.every((ref) => state.availableNumberedLines.has(ref));
176
+ }
177
+ function emitPendingDerivedStep(state, step) {
178
+ const premiseNames = step.refs.map((ref) => state.numberedLineNames.get(ref) ?? compatProofLineName(ref));
179
+ const name = rememberNumberedLine(state, step.lineNumber, step.formula);
180
+ // Emit derive for validation, then register as axiom so subsequent numbered steps
181
+ // can reference it. Use axiom (not theorem) so it's available as a premise name.
182
+ return appendComment([
183
+ `${step.indent}derive ${step.formula} from {${premiseNames.join(', ')}}`,
184
+ `${step.indent}axiom ${name} : ${step.formula}`,
185
+ ], step.comment);
186
+ }
187
+ function flushResolvablePendingDerivedSteps(state) {
188
+ const lines = [];
189
+ let changed = true;
190
+ while (changed) {
191
+ changed = false;
192
+ const remaining = [];
193
+ for (const step of state.pendingDerivedProofSteps) {
194
+ if (canEmitPendingDerivedStep(state, step)) {
195
+ lines.push(...emitPendingDerivedStep(state, step));
196
+ changed = true;
197
+ }
198
+ else {
199
+ remaining.push(step);
200
+ }
201
+ }
202
+ state.pendingDerivedProofSteps = remaining;
203
+ }
204
+ return lines;
205
+ }
206
+ function flushCompatState(state) {
207
+ const lines = flushPendingBareProofSteps(state);
208
+ lines.push(...flushResolvablePendingDerivedSteps(state));
209
+ return lines;
210
+ }
211
+ function flushPendingBareProofSteps(state) {
212
+ if (state.pendingBareProofSteps.length === 0) {
213
+ return [];
214
+ }
215
+ const pending = state.pendingBareProofSteps;
216
+ state.pendingBareProofSteps = [];
217
+ if (pending.length === 1) {
218
+ const step = pending[0];
219
+ const name = rememberNumberedLine(state, step.lineNumber, step.formula);
220
+ return appendComment([`${step.indent}axiom ${name} : ${step.formula}`], step.comment);
221
+ }
222
+ const lines = [];
223
+ for (let index = 0; index < pending.length - 1; index += 1) {
224
+ const step = pending[index];
225
+ const name = rememberNumberedLine(state, step.lineNumber, step.formula);
226
+ lines.push(...appendComment([`${step.indent}axiom ${name} : ${step.formula}`], step.comment));
227
+ }
228
+ const last = pending[pending.length - 1];
229
+ const lastName = rememberNumberedLine(state, last.lineNumber, last.formula);
230
+ const premiseNames = pending
231
+ .slice(0, -1)
232
+ .map((step) => state.numberedLineNames.get(step.lineNumber) ?? compatProofLineName(step.lineNumber));
233
+ lines.push(...appendComment([
234
+ `${last.indent}derive ${last.formula} from {${premiseNames.join(', ')}}`,
235
+ `${last.indent}axiom ${lastName} : ${last.formula}`,
236
+ ], last.comment));
237
+ return lines;
238
+ }
239
+ function looksLikeFormulaCandidate(value) {
240
+ const trimmed = value.trim();
241
+ if (!trimmed) {
242
+ return false;
243
+ }
244
+ if (/^(?:forall|exists)\b/i.test(trimmed)) {
245
+ return true;
246
+ }
247
+ if (/^(?:\[\]|<>)/.test(trimmed)) {
248
+ return true;
249
+ }
250
+ if (/<->|->|<=>|=>/.test(trimmed)) {
251
+ return true;
252
+ }
253
+ if (/[()!~¬∼&|∨∧→↔⇒⇔⊃≡]/.test(trimmed)) {
254
+ return true;
255
+ }
256
+ if (/^[A-Za-z_][A-Za-z0-9_.]*(?:\([^)]*\))?$/.test(trimmed)) {
257
+ return true;
258
+ }
259
+ if (/^\(.*\)$/.test(trimmed)) {
260
+ return true;
261
+ }
262
+ return false;
263
+ }
264
+ function extractJustifiedStep(rest) {
265
+ // Extract refs (comma-separated digits, optionally parenthesized) anchored at the end.
266
+ // Use a right-anchored pattern that greedily captures the full digit list.
267
+ const refsMatch = rest.match(/\(?\b(\d+(?:\s*,\s*\d+)*)\)?\s*$/);
268
+ if (!refsMatch) {
269
+ return null;
270
+ }
271
+ const refsStr = refsMatch[1];
272
+ const refs = refsStr.split(/\s*,\s*/);
273
+ // beforeRefs is everything before the refs match
274
+ const beforeRefs = rest.slice(0, refsMatch.index).trim();
275
+ if (!beforeRefs) {
276
+ return null;
277
+ }
278
+ const parts = beforeRefs.split(/\s+/);
279
+ // Try progressively shorter prefixes as the formula, leaving the rest as justification text.
280
+ // When there are multiple tokens, prefer shorter formulas to leave room for justification.
281
+ // Only use the full beforeRefs if it's a single token (e.g. just "Q").
282
+ const startIndex = parts.length === 1 ? 1 : parts.length - 1;
283
+ for (let splitIndex = startIndex; splitIndex >= 1; splitIndex -= 1) {
284
+ const formula = parts.slice(0, splitIndex).join(' ').trim();
285
+ if (looksLikeFormulaCandidate(formula)) {
286
+ return { formula, refs };
287
+ }
288
+ }
289
+ return null;
290
+ }
291
+ function extractPrefixJustifiedStep(rest) {
292
+ const refsMatch = rest.match(/^(.+?)\s+\(?(\d+(?:\s*,\s*\d+)*)\)?\s+(.+)$/);
293
+ if (!refsMatch) {
294
+ return null;
295
+ }
296
+ const formula = refsMatch[3].trim();
297
+ if (!looksLikeFormulaCandidate(formula)) {
298
+ return null;
299
+ }
300
+ return {
301
+ formula,
302
+ refs: refsMatch[2].split(/\s*,\s*/),
303
+ };
304
+ }
305
+ function transformNumberedProofLine(line, state) {
306
+ const { code, comment } = splitLineComment(line);
307
+ const stripped = stripLeadingProofBars(code);
308
+ const numberedLineMatch = stripped.code.match(/^\s*(?:\[(\d+)\]|(\d+)[.):])\s+(.+?)\s*$/);
309
+ if (!numberedLineMatch) {
310
+ return null;
311
+ }
312
+ const indent = stripped.code.match(/^\s*/)?.[0] ?? '';
313
+ const lineNumber = numberedLineMatch[1] ?? numberedLineMatch[2];
314
+ const rest = numberedLineMatch[3].trim();
315
+ const trailingPremiseMatch = rest.match(/^(.+?)\s+(premise|premisa)$/i);
316
+ const leadingPremiseMatch = rest.match(/^(premise|premisa)\s+(.+)$/i);
317
+ if (trailingPremiseMatch || leadingPremiseMatch) {
318
+ const prefix = flushCompatState(state);
319
+ const formula = (trailingPremiseMatch?.[1] ?? leadingPremiseMatch?.[2] ?? '').trim();
320
+ const name = rememberNumberedLine(state, lineNumber, formula);
321
+ return [...prefix, ...appendComment([`${indent}axiom ${name} : ${formula}`], comment)];
322
+ }
323
+ const assumptionMatch = rest.match(/^(?:assume|asumir|supuesto|hipotesis|hipótesis)\s+(.+)$/i);
324
+ if (assumptionMatch) {
325
+ const prefix = flushCompatState(state);
326
+ const formula = assumptionMatch[1].trim().replace(/^[A-Za-z_][A-Za-z0-9_.]*\s*[:=]\s*/, '');
327
+ const name = rememberNumberedLine(state, lineNumber, formula);
328
+ return [...prefix, ...appendComment([`${indent}axiom ${name} : ${formula}`], comment)];
329
+ }
330
+ const justifiedStep = extractJustifiedStep(rest) ?? extractPrefixJustifiedStep(rest);
331
+ if (justifiedStep) {
332
+ const prefix = flushCompatState(state);
333
+ const { formula, refs } = justifiedStep;
334
+ if (!canEmitPendingDerivedStep(state, { refs })) {
335
+ reserveNumberedLineName(state, lineNumber);
336
+ state.pendingDerivedProofSteps.push({
337
+ lineNumber,
338
+ formula,
339
+ refs,
340
+ indent,
341
+ comment,
342
+ originalLine: line,
343
+ });
344
+ return prefix;
345
+ }
346
+ return [
347
+ ...prefix,
348
+ ...emitPendingDerivedStep(state, {
349
+ lineNumber,
350
+ formula,
351
+ refs,
352
+ indent,
353
+ comment,
354
+ originalLine: line,
355
+ }),
356
+ ];
357
+ }
358
+ state.pendingBareProofSteps.push({
359
+ lineNumber,
360
+ formula: rest,
361
+ indent,
362
+ comment,
363
+ });
364
+ return [];
365
+ }
366
+ function normalizeUnicodeSyntax(source) {
367
+ let output = '';
368
+ let inString = false;
369
+ let inLineComment = false;
370
+ let inBlockComment = false;
371
+ let inDoubleBracket = false;
372
+ for (let index = 0; index < source.length; index += 1) {
373
+ const current = source[index];
374
+ const next = source[index + 1];
375
+ if (inLineComment) {
376
+ output += current;
377
+ if (current === '\n') {
378
+ inLineComment = false;
379
+ }
380
+ continue;
381
+ }
382
+ if (inBlockComment) {
383
+ output += current;
384
+ if (current === '*' && next === '/') {
385
+ output += '/';
386
+ index += 1;
387
+ inBlockComment = false;
388
+ }
389
+ continue;
390
+ }
391
+ if (inDoubleBracket) {
392
+ output += current;
393
+ if (current === ']' && next === ']') {
394
+ output += ']';
395
+ index += 1;
396
+ inDoubleBracket = false;
397
+ }
398
+ continue;
399
+ }
400
+ if (inString) {
401
+ output += current;
402
+ if (current === '\\' && next) {
403
+ output += next;
404
+ index += 1;
405
+ continue;
406
+ }
407
+ if (current === '"') {
408
+ inString = false;
409
+ }
410
+ continue;
411
+ }
412
+ if (current === '/' && next === '/') {
413
+ output += '//';
414
+ index += 1;
415
+ inLineComment = true;
416
+ continue;
417
+ }
418
+ if (current === '/' && next === '*') {
419
+ output += '/*';
420
+ index += 1;
421
+ inBlockComment = true;
422
+ continue;
423
+ }
424
+ if (current === '[' && next === '[') {
425
+ output += '[[';
426
+ index += 1;
427
+ inDoubleBracket = true;
428
+ continue;
429
+ }
430
+ if (current === '"') {
431
+ output += current;
432
+ inString = true;
433
+ continue;
434
+ }
435
+ if (current === '<' && next === '=' && source[index + 2] === '>') {
436
+ output += '<->';
437
+ index += 2;
438
+ continue;
439
+ }
440
+ if (current === '=' && next === '>') {
441
+ output += '->';
442
+ index += 1;
443
+ continue;
444
+ }
445
+ if (current === '¬' || current === '~' || current === '∼') {
446
+ output += '!';
447
+ continue;
448
+ }
449
+ if (current === '∧') {
450
+ output += '&';
451
+ continue;
452
+ }
453
+ if (current === '∨') {
454
+ output += '|';
455
+ continue;
456
+ }
457
+ if (current === '→' || current === '⇒' || current === '⊃') {
458
+ output += '->';
459
+ continue;
460
+ }
461
+ if (current === '↔' || current === '⇔' || current === '≡') {
462
+ output += '<->';
463
+ continue;
464
+ }
465
+ if (current === '⊢') {
466
+ output += '|-';
467
+ continue;
468
+ }
469
+ if (current === '⊥') {
470
+ output += '⊥';
471
+ continue;
472
+ }
473
+ if (current === '⊤') {
474
+ output += '⊤';
475
+ continue;
476
+ }
477
+ if (current === '∴') {
478
+ output += 'therefore';
479
+ continue;
480
+ }
481
+ output += current;
482
+ }
483
+ return output;
484
+ }
485
+ function extractNamedFormula(line) {
486
+ const axiomMatch = line.match(/^\s*(?:(?:export|exportar)\s+)?(?:axiom|axioma|theorem|teorema)\s+([A-Za-z_][A-Za-z0-9_.]*)\s*[:=]\s*(.+?)\s*$/);
487
+ if (axiomMatch) {
488
+ return { name: axiomMatch[1], formula: axiomMatch[2] };
489
+ }
490
+ const assumeMatch = line.match(/^\s*(?:assume|asumir)\s+([A-Za-z_][A-Za-z0-9_.]*)\s*[:=]\s*(.+?)\s*$/i);
491
+ if (assumeMatch) {
492
+ return { name: assumeMatch[1], formula: assumeMatch[2] };
493
+ }
494
+ const describedLetMatch = line.match(/^\s*(?:(?:export|exportar)\s+)?(?:let|sea)\s+([A-Za-z_][A-Za-z0-9_.]*)\s*=\s*"[^"]*"\s*:\s*(.+?)\s*$/);
495
+ if (describedLetMatch) {
496
+ return { name: describedLetMatch[1], formula: describedLetMatch[2] };
497
+ }
498
+ const letMatch = line.match(/^\s*(?:(?:export|exportar)\s+)?(?:let|sea)\s+([A-Za-z_][A-Za-z0-9_.]*)\s*=\s*(.+?)\s*$/);
499
+ if (!letMatch) {
500
+ return null;
501
+ }
502
+ const rhs = letMatch[2].trim();
503
+ if (rhs.startsWith('"') ||
504
+ /^(?:passage|pasaje|formalize|formalizar)\b/i.test(rhs) ||
505
+ /^(?:\d+|true|false)\b/i.test(rhs)) {
506
+ return null;
507
+ }
508
+ return { name: letMatch[1], formula: rhs };
509
+ }
510
+ function buildStandaloneProof(goal, premises, indent, state) {
511
+ const proofLines = premises.map((formula) => `${indent}assume ${nextCompatName(state, 'p')} : ${formula}`);
512
+ proofLines.push(`${indent}show ${goal}`);
513
+ proofLines.push(`${indent}qed`);
514
+ return proofLines;
515
+ }
516
+ function transformLine(line, state) {
517
+ const { code, comment } = splitLineComment(line);
518
+ const stripped = stripLeadingProofBars(code);
519
+ const effectiveCode = stripped.code;
520
+ const trimmed = effectiveCode.trim();
521
+ if (!trimmed) {
522
+ return [line];
523
+ }
524
+ const premiseMatch = effectiveCode.match(/^\s*(premise|premisa)\s+(.+?)\s*$/i);
525
+ if (premiseMatch) {
526
+ const rest = premiseMatch[2];
527
+ const named = rest.match(/^([A-Za-z_][A-Za-z0-9_.]*)\s*[:=]\s*(.+?)\s*$/);
528
+ const name = named?.[1] ?? nextCompatName(state, 'h');
529
+ const formula = (named?.[2] ?? rest).trim();
530
+ rememberFormula(state, name, formula, { local: true });
531
+ state.hasPremiseBlock = true;
532
+ return appendComment([`${effectiveCode.match(/^\s*/)?.[0] ?? ''}assume ${name} : ${formula}`], comment);
533
+ }
534
+ const assumeMatch = effectiveCode.match(/^\s*(assume|asumir)\s+(.+?)\s*$/i);
535
+ if (assumeMatch) {
536
+ const indent = effectiveCode.match(/^\s*/)?.[0] ?? '';
537
+ const rest = assumeMatch[2].trim();
538
+ const named = rest.match(/^([A-Za-z_][A-Za-z0-9_.]*)\s*[:=]\s*(.+?)\s*$/);
539
+ const name = named?.[1] ?? nextCompatName(state, 'h');
540
+ const formula = (named?.[2] ?? rest).trim();
541
+ rememberFormula(state, name, formula, { local: true });
542
+ return appendComment([`${indent}assume ${name} : ${formula}`], comment);
543
+ }
544
+ const conclusionMatch = effectiveCode.match(/^\s*(conclusion|conclusi(?:o|ó)n|therefore|por(?:\s+|_)tanto)\s+(.+?)\s*$/i);
545
+ if (conclusionMatch) {
546
+ const indent = effectiveCode.match(/^\s*/)?.[0] ?? '';
547
+ const goal = conclusionMatch[2].trim();
548
+ if (state.hasPremiseBlock || state.localScope) {
549
+ const lines = appendComment([`${indent}show ${goal}`, `${indent}qed`], comment);
550
+ closeLocalScope(state);
551
+ return lines;
552
+ }
553
+ const knownPremises = Array.from(state.knownFormulas.keys());
554
+ if (knownPremises.length > 0) {
555
+ return appendComment([`${indent}derive ${goal} from {${knownPremises.join(', ')}}`], comment);
556
+ }
557
+ return appendComment([`${indent}check valid ${goal}`], comment);
558
+ }
559
+ const turnstileMatch = effectiveCode.match(/^\s*(.*?)\s*\|-\s*(.+?)\s*$/);
560
+ if (turnstileMatch) {
561
+ const indent = effectiveCode.match(/^\s*/)?.[0] ?? '';
562
+ const left = turnstileMatch[1].trim();
563
+ const goal = turnstileMatch[2].trim();
564
+ const premiseSource = left.startsWith('{') && left.endsWith('}') ? left.slice(1, -1) : left;
565
+ const premises = splitTopLevel(premiseSource);
566
+ if (premises.length === 0) {
567
+ return appendComment([`${indent}check valid ${goal}`], comment);
568
+ }
569
+ return appendComment(buildStandaloneProof(goal, premises, indent, state), comment);
570
+ }
571
+ const deriveMatch = effectiveCode.match(/^\s*(derive|derivar|prove|probar)\s+(.+?)\s+(from|desde)\s+(\{.+\}|.+?)\s*$/i);
572
+ if (deriveMatch) {
573
+ const indent = effectiveCode.match(/^\s*/)?.[0] ?? '';
574
+ const command = deriveMatch[1].toLowerCase();
575
+ const canonicalCommand = command === 'prove' || command === 'probar' ? 'prove' : 'derive';
576
+ const goal = deriveMatch[2].trim();
577
+ const premiseSource = deriveMatch[4].trim();
578
+ const unwrappedPremiseSource = premiseSource.startsWith('{') && premiseSource.endsWith('}')
579
+ ? premiseSource.slice(1, -1)
580
+ : premiseSource;
581
+ const premiseItems = splitTopLevel(unwrappedPremiseSource);
582
+ // Determine whether each premise needs expansion:
583
+ // - Non-identifier items (formulas with operators like "P -> Q"): always expand
584
+ // - Bare atoms (BARE_ATOM_RE, e.g. P, Q): expand if NOT known in compat state
585
+ // (unknown bare atoms are inline formula premises, known ones are references to prior results)
586
+ // - Non-bare identifiers (e.g. h1, a1): always pass through as names
587
+ const requiresExpansion = premiseItems.some((item) => !IDENTIFIER_RE.test(item) || (BARE_ATOM_RE.test(item) && !state.knownFormulas.has(item)));
588
+ if (!requiresExpansion) {
589
+ return appendComment([`${indent}${canonicalCommand} ${goal} from {${premiseItems.join(', ')}}`], comment);
590
+ }
591
+ const resolvedPremises = premiseItems.map((item) => {
592
+ if (!IDENTIFIER_RE.test(item)) {
593
+ return item;
594
+ }
595
+ if (state.knownFormulas.has(item)) {
596
+ return state.knownFormulas.get(item) ?? null;
597
+ }
598
+ // Bare atom not in known formulas → treat as inline formula
599
+ return BARE_ATOM_RE.test(item) ? item : null;
600
+ });
601
+ if (resolvedPremises.some((item) => item === null)) {
602
+ return appendComment([`${indent}${canonicalCommand} ${goal} from {${premiseItems.join(', ')}}`], comment);
603
+ }
604
+ return appendComment(buildStandaloneProof(goal, resolvedPremises, indent, state), comment);
605
+ }
606
+ if (/^\s*qed\b/i.test(effectiveCode)) {
607
+ const transformed = appendComment([effectiveCode.replace(/\bqed\b/i, 'qed')], comment);
608
+ closeLocalScope(state);
609
+ return transformed;
610
+ }
611
+ const namedFormula = extractNamedFormula(effectiveCode);
612
+ if (namedFormula) {
613
+ rememberFormula(state, namedFormula.name, namedFormula.formula);
614
+ }
615
+ return [line];
616
+ }
617
+ function normalizeSTSource(source) {
618
+ const transformState = createTransformState();
619
+ const normalized = normalizeUnicodeSyntax(source);
620
+ const lines = normalized.split('\n');
621
+ const transformed = [];
622
+ let inBlockComment = false;
623
+ let inDoubleBracket = false;
624
+ for (const line of lines) {
625
+ const trimmed = line.trim();
626
+ if (inBlockComment) {
627
+ transformed.push(line);
628
+ if (line.includes('*/')) {
629
+ inBlockComment = false;
630
+ }
631
+ continue;
632
+ }
633
+ if (inDoubleBracket) {
634
+ transformed.push(line);
635
+ if (line.includes(']]')) {
636
+ inDoubleBracket = false;
637
+ }
638
+ continue;
639
+ }
640
+ if (trimmed.startsWith('/*') && !trimmed.includes('*/')) {
641
+ inBlockComment = true;
642
+ transformed.push(line);
643
+ continue;
644
+ }
645
+ if (line.includes('[[') && !line.includes(']]')) {
646
+ inDoubleBracket = true;
647
+ transformed.push(line);
648
+ continue;
649
+ }
650
+ transformed.push(...flushResolvablePendingDerivedSteps(transformState));
651
+ const numberedLines = transformNumberedProofLine(line, transformState);
652
+ if (numberedLines !== null) {
653
+ transformed.push(...numberedLines);
654
+ continue;
655
+ }
656
+ transformed.push(...flushCompatState(transformState));
657
+ transformed.push(...transformLine(line, transformState));
658
+ }
659
+ transformed.push(...flushCompatState(transformState));
660
+ for (const pending of transformState.pendingDerivedProofSteps) {
661
+ transformed.push(pending.originalLine);
662
+ }
663
+ return transformed.join('\n');
664
+ }
665
+ function createReplCompatState() {
666
+ return {
667
+ nextId: 1,
668
+ pendingPremises: [],
669
+ pendingBlockLines: [],
670
+ pendingBlockBraceDepth: 0,
671
+ pendingBlockProofDepth: 0,
672
+ pendingBlockProofAwaitingShow: [],
673
+ };
674
+ }
675
+ function analyzeReplBlockLine(line) {
676
+ const { code } = splitLineComment(line);
677
+ let braceDelta = 0;
678
+ let inString = false;
679
+ for (let index = 0; index < code.length; index += 1) {
680
+ const current = code[index];
681
+ if (inString) {
682
+ if (current === '\\' && index + 1 < code.length) {
683
+ index += 1;
684
+ continue;
685
+ }
686
+ if (current === '"') {
687
+ inString = false;
688
+ }
689
+ continue;
690
+ }
691
+ if (current === '"') {
692
+ inString = true;
693
+ continue;
694
+ }
695
+ if (current === '{')
696
+ braceDelta += 1;
697
+ if (current === '}')
698
+ braceDelta -= 1;
699
+ }
700
+ return { braceDelta, trimmed: code.trim() };
701
+ }
702
+ function isReplMultilineStart(line) {
703
+ const { braceDelta, trimmed } = analyzeReplBlockLine(line);
704
+ if (!trimmed)
705
+ return false;
706
+ if (/^(assume|asumir)\b/i.test(trimmed))
707
+ return true;
708
+ return braceDelta > 0;
709
+ }
710
+ function appendReplBlockLine(state, line) {
711
+ state.pendingBlockLines.push(line);
712
+ const { braceDelta, trimmed } = analyzeReplBlockLine(line);
713
+ state.pendingBlockBraceDepth = Math.max(0, state.pendingBlockBraceDepth + braceDelta);
714
+ if (/^(assume|asumir)\b/i.test(trimmed)) {
715
+ const insideProofBody = state.pendingBlockProofDepth > 0 &&
716
+ state.pendingBlockProofAwaitingShow[state.pendingBlockProofAwaitingShow.length - 1] === false;
717
+ if (state.pendingBlockProofDepth === 0 || insideProofBody) {
718
+ state.pendingBlockProofDepth += 1;
719
+ state.pendingBlockProofAwaitingShow.push(true);
720
+ }
721
+ }
722
+ else if (/^(show|demostrar)\b/i.test(trimmed)) {
723
+ if (state.pendingBlockProofAwaitingShow.length > 0) {
724
+ state.pendingBlockProofAwaitingShow[state.pendingBlockProofAwaitingShow.length - 1] = false;
725
+ }
726
+ }
727
+ else if (/^qed\b/i.test(trimmed)) {
728
+ if (state.pendingBlockProofDepth > 0) {
729
+ state.pendingBlockProofDepth -= 1;
730
+ state.pendingBlockProofAwaitingShow.pop();
731
+ }
732
+ }
733
+ return state.pendingBlockBraceDepth === 0 && state.pendingBlockProofDepth === 0;
734
+ }
735
+ function consumeReplBlock(state) {
736
+ const source = state.pendingBlockLines.join('\n');
737
+ state.pendingBlockLines = [];
738
+ state.pendingBlockBraceDepth = 0;
739
+ state.pendingBlockProofDepth = 0;
740
+ state.pendingBlockProofAwaitingShow = [];
741
+ return source;
742
+ }
743
+ function transformReplInput(source, state, context) {
744
+ const normalized = normalizeUnicodeSyntax(source);
745
+ if (normalized.includes('\n')) {
746
+ state.pendingBlockLines = [];
747
+ state.pendingBlockBraceDepth = 0;
748
+ state.pendingBlockProofDepth = 0;
749
+ state.pendingBlockProofAwaitingShow = [];
750
+ return { kind: 'executeSingle', source: normalizeSTSource(normalized) };
751
+ }
752
+ if (state.pendingBlockLines.length > 0) {
753
+ if (appendReplBlockLine(state, normalized)) {
754
+ return {
755
+ kind: 'executeSingle',
756
+ source: normalizeSTSource(consumeReplBlock(state)),
757
+ };
758
+ }
759
+ return {
760
+ kind: 'buffered',
761
+ source: '',
762
+ message: `Bloque multilinea en curso (${state.pendingBlockLines.length} lineas)...`,
763
+ };
764
+ }
765
+ const trimmed = normalized.trim();
766
+ const premiseMatch = trimmed.match(/^(premise|premisa)\s+(.+?)\s*$/i);
767
+ if (premiseMatch) {
768
+ const rest = premiseMatch[2];
769
+ const named = rest.match(/^([A-Za-z_][A-Za-z0-9_.]*)\s*[:=]\s*(.+?)\s*$/);
770
+ const name = named?.[1] ?? `__compat_repl_${state.nextId++}`;
771
+ const formula = (named?.[2] ?? rest).trim();
772
+ state.pendingPremises.push({ name, formula });
773
+ return {
774
+ kind: 'buffered',
775
+ source: '',
776
+ message: `Premisa registrada: ${formula}`,
777
+ };
778
+ }
779
+ const conclusionMatch = trimmed.match(/^(conclusion|conclusi(?:o|ó)n|therefore|por(?:\s+|_)tanto)\s+(.+?)\s*$/i);
780
+ if (conclusionMatch && state.pendingPremises.length > 0) {
781
+ const goal = conclusionMatch[2].trim();
782
+ const proof = [
783
+ ...state.pendingPremises.map((premise) => `assume ${premise.name} : ${premise.formula}`),
784
+ `show ${goal}`,
785
+ 'qed',
786
+ ].join('\n');
787
+ state.pendingPremises = [];
788
+ return { kind: 'execute', source: proof };
789
+ }
790
+ if (conclusionMatch) {
791
+ const goal = conclusionMatch[2].trim();
792
+ const knownPremises = context?.knownPremises ?? [];
793
+ if (knownPremises.length > 0) {
794
+ return {
795
+ kind: 'executeSingle',
796
+ source: `derive ${goal} from {${knownPremises.join(', ')}}`,
797
+ };
798
+ }
799
+ return {
800
+ kind: 'executeSingle',
801
+ source: `check valid ${goal}`,
802
+ };
803
+ }
804
+ if (isReplMultilineStart(normalized)) {
805
+ if (appendReplBlockLine(state, normalized)) {
806
+ return {
807
+ kind: 'executeSingle',
808
+ source: normalizeSTSource(consumeReplBlock(state)),
809
+ };
810
+ }
811
+ return {
812
+ kind: 'buffered',
813
+ source: '',
814
+ message: `Bloque multilinea en curso (${state.pendingBlockLines.length} lineas)...`,
815
+ };
816
+ }
817
+ return { kind: 'executeSingle', source: normalizeSTSource(normalized) };
818
+ }
819
+ //# sourceMappingURL=compat.js.map