@stevenvo780/st-lang 3.1.0 → 3.1.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.
Files changed (55) hide show
  1. package/dist/api.d.ts.map +1 -1
  2. package/dist/api.js +44 -9
  3. package/dist/api.js.map +1 -1
  4. package/dist/parser/parser.d.ts +4 -0
  5. package/dist/parser/parser.d.ts.map +1 -1
  6. package/dist/parser/parser.js +213 -92
  7. package/dist/parser/parser.js.map +1 -1
  8. package/dist/profiles/classical/first-order.d.ts.map +1 -1
  9. package/dist/profiles/classical/first-order.js +12 -5
  10. package/dist/profiles/classical/first-order.js.map +1 -1
  11. package/dist/profiles/classical/propositional.d.ts.map +1 -1
  12. package/dist/profiles/classical/propositional.js +281 -35
  13. package/dist/profiles/classical/propositional.js.map +1 -1
  14. package/dist/profiles/shared/tableau-engine.d.ts +4 -3
  15. package/dist/profiles/shared/tableau-engine.d.ts.map +1 -1
  16. package/dist/profiles/shared/tableau-engine.js +101 -15
  17. package/dist/profiles/shared/tableau-engine.js.map +1 -1
  18. package/dist/protocol/handler.d.ts +4 -0
  19. package/dist/protocol/handler.d.ts.map +1 -1
  20. package/dist/protocol/handler.js +133 -41
  21. package/dist/protocol/handler.js.map +1 -1
  22. package/dist/repl/repl.d.ts +2 -0
  23. package/dist/repl/repl.d.ts.map +1 -1
  24. package/dist/repl/repl.js +39 -18
  25. package/dist/repl/repl.js.map +1 -1
  26. package/dist/runtime/compat.d.ts +29 -0
  27. package/dist/runtime/compat.d.ts.map +1 -0
  28. package/dist/runtime/compat.js +821 -0
  29. package/dist/runtime/compat.js.map +1 -0
  30. package/dist/runtime/interpreter.d.ts +3 -0
  31. package/dist/runtime/interpreter.d.ts.map +1 -1
  32. package/dist/runtime/interpreter.js +128 -28
  33. package/dist/runtime/interpreter.js.map +1 -1
  34. package/dist/tests/compat.test.d.ts +2 -0
  35. package/dist/tests/compat.test.d.ts.map +1 -0
  36. package/dist/tests/compat.test.js +247 -0
  37. package/dist/tests/compat.test.js.map +1 -0
  38. package/dist/tests/core.test.js +37 -0
  39. package/dist/tests/core.test.js.map +1 -1
  40. package/dist/tests/parser.test.js +38 -0
  41. package/dist/tests/parser.test.js.map +1 -1
  42. package/dist/tests/profiles.test.js +8 -0
  43. package/dist/tests/profiles.test.js.map +1 -1
  44. package/dist/tests/protocol-text-layer.test.d.ts +2 -0
  45. package/dist/tests/protocol-text-layer.test.d.ts.map +1 -0
  46. package/dist/tests/protocol-text-layer.test.js +54 -0
  47. package/dist/tests/protocol-text-layer.test.js.map +1 -0
  48. package/dist/text-layer/compiler.d.ts.map +1 -1
  49. package/dist/text-layer/compiler.js +35 -8
  50. package/dist/text-layer/compiler.js.map +1 -1
  51. package/dist/types/index.d.ts +27 -1
  52. package/dist/types/index.d.ts.map +1 -1
  53. package/dist/types/index.js +7 -0
  54. package/dist/types/index.js.map +1 -1
  55. package/package.json +2 -2
@@ -704,6 +704,77 @@ function addDerivedFormula(state, formula, justification, premises) {
704
704
  state.known.set(hash, formula);
705
705
  return true;
706
706
  }
707
+ function buildPremiseRefs(theory, premiseNames) {
708
+ return premiseNames.map((name) => ({
709
+ name,
710
+ location: (theory.axioms.get(name) || theory.theorems.get(name))?.source,
711
+ }));
712
+ }
713
+ function buildProof(goal, steps, premiseNames, theory, method = 'natural_deduction', subproofs) {
714
+ return {
715
+ goal,
716
+ steps,
717
+ status: 'complete',
718
+ derivedFrom: premiseNames,
719
+ premiseRefs: buildPremiseRefs(theory, premiseNames),
720
+ method,
721
+ subproofs,
722
+ metadata: {
723
+ createdAt: new Date().toISOString(),
724
+ profile: theory.profile,
725
+ },
726
+ };
727
+ }
728
+ function isNegationOf(a, b) {
729
+ return a.kind === 'not' && !!a.args?.[0] && formulasEqual(a.args[0], b);
730
+ }
731
+ function isExcludedMiddleFormula(formula) {
732
+ if (formula.kind !== 'or' || !formula.args?.[0] || !formula.args?.[1])
733
+ return false;
734
+ return (isNegationOf(formula.args[0], formula.args[1]) || isNegationOf(formula.args[1], formula.args[0]));
735
+ }
736
+ function getCommutativeVariant(formula) {
737
+ if ((formula.kind === 'and' || formula.kind === 'or') && formula.args?.[0] && formula.args?.[1]) {
738
+ return { kind: formula.kind, args: [formula.args[1], formula.args[0]] };
739
+ }
740
+ return null;
741
+ }
742
+ function getAssociativeVariants(formula) {
743
+ const variants = [];
744
+ if ((formula.kind === 'and' || formula.kind === 'or') && formula.args?.[0] && formula.args?.[1]) {
745
+ const [left, right] = formula.args;
746
+ if (left.kind === formula.kind && left.args?.[0] && left.args?.[1]) {
747
+ variants.push({
748
+ kind: formula.kind,
749
+ args: [left.args[0], { kind: formula.kind, args: [left.args[1], right] }],
750
+ });
751
+ }
752
+ if (right.kind === formula.kind && right.args?.[0] && right.args?.[1]) {
753
+ variants.push({
754
+ kind: formula.kind,
755
+ args: [{ kind: formula.kind, args: [left, right.args[0]] }, right.args[1]],
756
+ });
757
+ }
758
+ }
759
+ return variants;
760
+ }
761
+ function getAbsorptionResult(formula) {
762
+ if (formula.kind === 'and' && formula.args?.[0] && formula.args?.[1]) {
763
+ const [left, right] = formula.args;
764
+ if (right.kind === 'or' && right.args?.some((arg) => formulasEqual(arg, left)))
765
+ return left;
766
+ if (left.kind === 'or' && left.args?.some((arg) => formulasEqual(arg, right)))
767
+ return right;
768
+ }
769
+ if (formula.kind === 'or' && formula.args?.[0] && formula.args?.[1]) {
770
+ const [left, right] = formula.args;
771
+ if (right.kind === 'and' && right.args?.some((arg) => formulasEqual(arg, left)))
772
+ return left;
773
+ if (left.kind === 'and' && left.args?.some((arg) => formulasEqual(arg, right)))
774
+ return right;
775
+ }
776
+ return null;
777
+ }
707
778
  function tryDerive(goal, theory, premiseNames, depth = 0) {
708
779
  const state = {
709
780
  known: new Map(),
@@ -712,7 +783,25 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
712
783
  };
713
784
  // Cargar premisas
714
785
  for (const name of premiseNames) {
715
- const f = theory.axioms.get(name) || theory.theorems.get(name);
786
+ let f = theory.axioms.get(name) || theory.theorems.get(name);
787
+ // Fallback: if name not found directly, search for an axiom/theorem whose formula
788
+ // matches the bare atom name (e.g., premise "Q" matches a theorem whose formula is atom Q)
789
+ if (!f) {
790
+ for (const [, formula] of theory.axioms) {
791
+ if (formula.kind === 'atom' && formula.name === name) {
792
+ f = formula;
793
+ break;
794
+ }
795
+ }
796
+ if (!f) {
797
+ for (const [, formula] of theory.theorems) {
798
+ if (formula.kind === 'atom' && formula.name === name) {
799
+ f = formula;
800
+ break;
801
+ }
802
+ }
803
+ }
804
+ }
716
805
  if (f) {
717
806
  state.stepCount++;
718
807
  state.steps.push({
@@ -724,6 +813,9 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
724
813
  state.known.set(formulaHash(f), f);
725
814
  }
726
815
  }
816
+ if (isExcludedMiddleFormula(goal)) {
817
+ addDerivedFormula(state, goal, 'Tercero excluido', []);
818
+ }
727
819
  // Intentar derivar con BFS aplicando reglas (optimizado)
728
820
  const maxIterations = 1000;
729
821
  let changed = true;
@@ -928,7 +1020,9 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
928
1020
  const disjHashRev = formulaHash({ kind: 'or', args: [r, p] });
929
1021
  if (state.known.has(disjHash) || state.known.has(disjHashRev)) {
930
1022
  const qs = { kind: 'or', args: [q, s] };
931
- const disjFormula = state.known.get(disjHash) || state.known.get(disjHashRev);
1023
+ const disjFormula = state.known.get(disjHash) ?? state.known.get(disjHashRev);
1024
+ if (!disjFormula)
1025
+ continue;
932
1026
  changed =
933
1027
  addDerivedFormula(state, qs, 'Dilema Constructivo', [
934
1028
  findStep(state.steps, f1),
@@ -975,6 +1069,32 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
975
1069
  ]) || changed;
976
1070
  }
977
1071
  }
1072
+ const commutative = getCommutativeVariant(f1);
1073
+ if (commutative && isRelevantToGoal(commutative, goal)) {
1074
+ changed =
1075
+ addDerivedFormula(state, commutative, 'Conmutatividad', [findStep(state.steps, f1)]) ||
1076
+ changed;
1077
+ }
1078
+ for (const associative of getAssociativeVariants(f1)) {
1079
+ if (isRelevantToGoal(associative, goal)) {
1080
+ changed =
1081
+ addDerivedFormula(state, associative, 'Asociatividad', [findStep(state.steps, f1)]) ||
1082
+ changed;
1083
+ }
1084
+ }
1085
+ if ((f1.kind === 'and' || f1.kind === 'or') &&
1086
+ f1.args?.[0] &&
1087
+ f1.args?.[1] &&
1088
+ formulasEqual(f1.args[0], f1.args[1])) {
1089
+ changed =
1090
+ addDerivedFormula(state, f1.args[0], 'Idempotencia', [findStep(state.steps, f1)]) ||
1091
+ changed;
1092
+ }
1093
+ const absorbed = getAbsorptionResult(f1);
1094
+ if (absorbed) {
1095
+ changed =
1096
+ addDerivedFormula(state, absorbed, 'Absorcion', [findStep(state.steps, f1)]) || changed;
1097
+ }
978
1098
  // Disjunction Introduction: de A, derivar A | B
979
1099
  // Relaxed: also allow intermediate disjunctions that are relevant to goal
980
1100
  if (goal.kind === 'or' && goal.args?.[0] && goal.args?.[1]) {
@@ -1027,6 +1147,35 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
1027
1147
  findStep(state.steps, f1),
1028
1148
  ]) || changed;
1029
1149
  }
1150
+ // Implicación material (→ a ∨): de A->B, derivar !A|B
1151
+ if (f1.kind === 'implies' && f1.args?.[0] && f1.args?.[1]) {
1152
+ const matImpl = {
1153
+ kind: 'or',
1154
+ args: [{ kind: 'not', args: [f1.args[0]] }, f1.args[1]],
1155
+ };
1156
+ if (isRelevantToGoal(matImpl, goal)) {
1157
+ changed =
1158
+ addDerivedFormula(state, matImpl, 'Implicacion material (→ a ∨)', [
1159
+ findStep(state.steps, f1),
1160
+ ]) || changed;
1161
+ }
1162
+ }
1163
+ // Implicación material inversa (∨ a →): de !A|B, derivar A->B
1164
+ if (f1.kind === 'or' &&
1165
+ f1.args?.[0]?.kind === 'not' &&
1166
+ f1.args[0].args?.[0] &&
1167
+ f1.args?.[1]) {
1168
+ const impl = {
1169
+ kind: 'implies',
1170
+ args: [f1.args[0].args[0], f1.args[1]],
1171
+ };
1172
+ if (isRelevantToGoal(impl, goal)) {
1173
+ changed =
1174
+ addDerivedFormula(state, impl, 'Implicacion material (∨ a →)', [
1175
+ findStep(state.steps, f1),
1176
+ ]) || changed;
1177
+ }
1178
+ }
1030
1179
  // Contraposition: de A->B, derivar !B->!A
1031
1180
  // Restringir a fórmulas con profundidad de negación baja para evitar
1032
1181
  // cadenas infinitas de contrapositivas (!!A→!!B → !!!B→!!!A → ...)
@@ -1251,21 +1400,13 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
1251
1400
  if (state.known.has(formulaHash(goal))) {
1252
1401
  // Filtrar solo pasos relevantes para la derivación
1253
1402
  const relevantSteps = traceBack(state.steps, goal);
1254
- return {
1255
- goal,
1256
- steps: relevantSteps,
1257
- status: 'complete',
1258
- derivedFrom: premiseNames,
1259
- };
1403
+ return buildProof(goal, relevantSteps, premiseNames, theory);
1260
1404
  }
1261
1405
  // --- Sub-derivaciones recursivas (antes del fallback semántico) ---
1262
1406
  const MAX_SUB_DEPTH = 2;
1263
1407
  // Prueba Condicional real (→-Introducción / Deduction Theorem):
1264
1408
  // Para derivar A→B, asumimos A como premisa temporal y derivamos B.
1265
- if (depth < MAX_SUB_DEPTH &&
1266
- goal.kind === 'implies' &&
1267
- goal.args?.[0] &&
1268
- goal.args?.[1]) {
1409
+ if (depth < MAX_SUB_DEPTH && goal.kind === 'implies' && goal.args?.[0] && goal.args?.[1]) {
1269
1410
  const assumption = goal.args[0];
1270
1411
  const subGoal = goal.args[1];
1271
1412
  // Create a temporary theory with the assumption added
@@ -1304,7 +1445,6 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
1304
1445
  premises: [],
1305
1446
  });
1306
1447
  // Add sub-derivation steps (renumber, adjusting premise references)
1307
- const subStepOffset = stepNum;
1308
1448
  const subStepMap = new Map();
1309
1449
  for (const s of subProof.steps) {
1310
1450
  if (s.justification.startsWith('Premisa') && formulasEqual(s.formula, assumption)) {
@@ -1330,19 +1470,15 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
1330
1470
  }
1331
1471
  // Add final conditional proof step
1332
1472
  stepNum++;
1333
- const subGoalStepNum = subStepMap.get(subProof.steps[subProof.steps.length - 1]?.stepNumber ?? 0) ?? (stepNum - 1);
1473
+ const subGoalStepNum = subStepMap.get(subProof.steps[subProof.steps.length - 1]?.stepNumber ?? 0) ?? stepNum - 1;
1334
1474
  mainSteps.push({
1335
1475
  stepNumber: stepNum,
1336
1476
  formula: goal,
1337
1477
  justification: 'Prueba Condicional (Teorema de Deduccion)',
1338
1478
  premises: [assumptionStepNum, subGoalStepNum],
1479
+ subproofs: [subProof],
1339
1480
  });
1340
- return {
1341
- goal,
1342
- steps: mainSteps,
1343
- status: 'complete',
1344
- derivedFrom: premiseNames,
1345
- };
1481
+ return buildProof(goal, mainSteps, premiseNames, theory, 'natural_deduction', [subProof]);
1346
1482
  }
1347
1483
  }
1348
1484
  }
@@ -1351,8 +1487,10 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
1351
1487
  if (depth < MAX_SUB_DEPTH) {
1352
1488
  const disjunctions = Array.from(state.known.values()).filter((f) => f.kind === 'or' && f.args?.[0] && f.args?.[1]);
1353
1489
  for (const disj of disjunctions) {
1354
- const left = disj.args[0];
1355
- const right = disj.args[1];
1490
+ const left = disj.args?.[0];
1491
+ const right = disj.args?.[1];
1492
+ if (!left || !right)
1493
+ continue;
1356
1494
  // Try to derive goal assuming left
1357
1495
  const tempTheoryL = {
1358
1496
  profile: theory.profile,
@@ -1469,13 +1607,12 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
1469
1607
  formula: goal,
1470
1608
  justification: 'Eliminacion de disyuncion (prueba por casos)',
1471
1609
  premises: [disjStepNum, leftGoalStep, rightGoalStep],
1610
+ subproofs: [subProofL, subProofR],
1472
1611
  });
1473
- return {
1474
- goal,
1475
- steps: mainSteps,
1476
- status: 'complete',
1477
- derivedFrom: premiseNames,
1478
- };
1612
+ return buildProof(goal, mainSteps, premiseNames, theory, 'natural_deduction', [
1613
+ subProofL,
1614
+ subProofR,
1615
+ ]);
1479
1616
  }
1480
1617
  }
1481
1618
  // Fallback: verificar semánticamente
@@ -1547,12 +1684,7 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
1547
1684
  state.known.set(goalHash, goal);
1548
1685
  }
1549
1686
  const relevantSteps = traceBack(state.steps, goal);
1550
- return {
1551
- goal,
1552
- steps: relevantSteps,
1553
- status: 'complete',
1554
- derivedFrom: premiseNames,
1555
- };
1687
+ return buildProof(goal, relevantSteps, premiseNames, theory, 'semantic');
1556
1688
  }
1557
1689
  }
1558
1690
  return null;
@@ -1583,7 +1715,17 @@ function traceBack(steps, goal) {
1583
1715
  }
1584
1716
  }
1585
1717
  trace(goalStep.stepNumber);
1586
- return steps.filter((s) => needed.has(s.stepNumber));
1718
+ const filtered = steps.filter((s) => needed.has(s.stepNumber));
1719
+ // Compact renumbering: eliminate gaps in step numbers
1720
+ const oldToNew = new Map();
1721
+ filtered.forEach((s, i) => {
1722
+ oldToNew.set(s.stepNumber, i + 1);
1723
+ });
1724
+ return filtered.map((s) => ({
1725
+ ...s,
1726
+ stepNumber: oldToNew.get(s.stepNumber) ?? s.stepNumber,
1727
+ premises: s.premises.map((p) => oldToNew.get(p) ?? p),
1728
+ }));
1587
1729
  }
1588
1730
  // --- Perfil Classical Propositional ---
1589
1731
  class ClassicalPropositional {
@@ -1779,6 +1921,96 @@ class ClassicalPropositional {
1779
1921
  formula: goal,
1780
1922
  };
1781
1923
  }
1924
+ // Semantic fallback: verify via SAT/truth-table whether goal follows from axioms
1925
+ const allAxiomFormulas = premiseNames
1926
+ .map((n) => theory.axioms.get(n) || theory.theorems.get(n))
1927
+ .filter((f) => f !== undefined);
1928
+ let semanticResult;
1929
+ const atoms = new Set();
1930
+ for (const f of allAxiomFormulas)
1931
+ collectAtoms(f).forEach((a) => atoms.add(a));
1932
+ collectAtoms(goal).forEach((a) => atoms.add(a));
1933
+ const atomList = Array.from(atoms).sort();
1934
+ if (allAxiomFormulas.length > 0) {
1935
+ // With premises: check if premises entail goal
1936
+ const allPure = allAxiomFormulas.every(isPurePropositional) && isPurePropositional(goal);
1937
+ if (allPure && atomList.length <= 26) {
1938
+ const premiseBits = allAxiomFormulas.map((f) => evaluateBitset(f, atomList).result);
1939
+ const goalBits = evaluateBitset(goal, atomList).result;
1940
+ const allOnes = bvOnes(1 << atomList.length);
1941
+ let premisesConj = allOnes;
1942
+ for (const pb of premiseBits)
1943
+ premisesConj = bvAnd(premisesConj, pb);
1944
+ semanticResult = bvIsZero(bvAnd(premisesConj, bvNot(goalBits, allOnes)));
1945
+ }
1946
+ else if (allPure && atomList.length > 26) {
1947
+ let conjunction = allAxiomFormulas[0];
1948
+ for (let i = 1; i < allAxiomFormulas.length; i++) {
1949
+ conjunction = { kind: 'and', args: [conjunction, allAxiomFormulas[i]] };
1950
+ }
1951
+ const negGoal = { kind: 'not', args: [goal] };
1952
+ const check = { kind: 'and', args: [conjunction, negGoal] };
1953
+ semanticResult = !(0, dpll_1.dpll)(check).satisfiable;
1954
+ }
1955
+ else {
1956
+ const valuations = generateValuations(atomList);
1957
+ semanticResult = true;
1958
+ for (const v of valuations) {
1959
+ const premisesTrue = allAxiomFormulas.every((f) => evaluateClassical(f, v));
1960
+ if (premisesTrue && !evaluateClassical(goal, v)) {
1961
+ semanticResult = false;
1962
+ break;
1963
+ }
1964
+ }
1965
+ }
1966
+ }
1967
+ else {
1968
+ // No premises: check if goal is a tautology
1969
+ if (isPurePropositional(goal) && atomList.length <= 26) {
1970
+ const { result, allOnes } = evaluateBitset(goal, atomList);
1971
+ semanticResult = bvEquals(result, allOnes);
1972
+ }
1973
+ else if (isPurePropositional(goal) && atomList.length > 26) {
1974
+ const negated = { kind: 'not', args: [goal] };
1975
+ semanticResult = !(0, dpll_1.dpll)(negated).satisfiable;
1976
+ }
1977
+ else {
1978
+ const valuations = generateValuations(atomList);
1979
+ semanticResult = valuations.every((v) => evaluateClassical(goal, v));
1980
+ }
1981
+ }
1982
+ if (semanticResult) {
1983
+ const semanticProofSteps = [
1984
+ ...premiseNames
1985
+ .map((n, i) => {
1986
+ const f = theory.axioms.get(n) || theory.theorems.get(n);
1987
+ return f
1988
+ ? {
1989
+ stepNumber: i + 1,
1990
+ formula: f,
1991
+ justification: `Premisa (${n})`,
1992
+ premises: [],
1993
+ }
1994
+ : null;
1995
+ })
1996
+ .filter((s) => s !== null),
1997
+ {
1998
+ stepNumber: premiseNames.length + 1,
1999
+ formula: goal,
2000
+ justification: 'Verificacion semantica (tautologia o consecuencia logica)',
2001
+ premises: premiseNames.map((_, i) => i + 1),
2002
+ },
2003
+ ];
2004
+ const semanticProof = buildProof(goal, semanticProofSteps, premiseNames, theory, 'semantic');
2005
+ return {
2006
+ status: 'provable',
2007
+ output: `${formulaToString(goal)} es DEMOSTRABLE desde la teoria`,
2008
+ proof: semanticProof,
2009
+ educationalNote: (0, educational_notes_1.pickEducationalNote)({ op: 'prove', ok: true }),
2010
+ diagnostics: [],
2011
+ formula: goal,
2012
+ };
2013
+ }
1782
2014
  return {
1783
2015
  status: 'refutable',
1784
2016
  output: `${formulaToString(goal)} NO es demostrable desde la teoria dada`,
@@ -1915,6 +2147,20 @@ class ClassicalPropositional {
1915
2147
  };
1916
2148
  }
1917
2149
  explain(formula) {
2150
+ if (!isPurePropositional(formula)) {
2151
+ return {
2152
+ status: 'error',
2153
+ output: `explain solo esta disponible para formulas puramente proposicionales: ${(0, format_1.formulaToUnicode)(formula)}`,
2154
+ diagnostics: [
2155
+ {
2156
+ severity: 'error',
2157
+ message: 'La formula incluye operadores no proposicionales; use un perfil con explain semantico especifico.',
2158
+ },
2159
+ ...this.checkWellFormed(formula),
2160
+ ],
2161
+ formula,
2162
+ };
2163
+ }
1918
2164
  const wf = this.checkWellFormed(formula);
1919
2165
  if (wf.length > 0) {
1920
2166
  return { status: 'error', diagnostics: wf, formula };