From b33e6ae369e9c473f02f7876af4bee74e79d59cf Mon Sep 17 00:00:00 2001 From: Johann Rosain Date: Sun, 20 Jul 2025 12:06:16 +0200 Subject: [PATCH 01/30] Clean: replace *FormList by Lib.List[Form] --- src/AST/{formula_list.go => form-list.go} | 71 +---- src/AST/formsDef.go | 153 ++++----- src/AST/formula.go | 36 +-- src/AST/quantifiers.go | 6 +- src/Core/FormListDS.go | 28 +- src/Core/Sko/preinner-skolemization.go | 8 +- src/Core/form_and_terms_list.go | 10 +- src/Core/int_subst_and_form.go | 5 +- src/Core/subst_and_form.go | 36 ++- src/Core/substitutions_search.go | 16 +- src/Engine/syntax-translation.go | 12 +- src/Lib/list.go | 28 ++ src/Mods/dmt/axiom_registration.go | 4 +- src/Mods/dmt/dmt.go | 16 +- src/Mods/dmt/rewrite.go | 30 +- src/Mods/dmt/utils.go | 7 +- src/Mods/equality/bse/equality.go | 2 +- src/Mods/equality/bse/equality_problem.go | 4 +- .../equality/bse/equality_problem_list.go | 8 +- src/Mods/gs3/dependency.go | 25 +- src/Mods/gs3/proof.go | 123 ++++---- src/Mods/gs3/sequent.go | 35 ++- src/Mods/lambdapi/context.go | 8 +- src/Mods/lambdapi/proof.go | 55 ++-- src/Mods/rocq/context.go | 4 +- src/Mods/rocq/proof.go | 153 +++++---- src/Mods/tptp/proof.go | 296 +++++++++--------- src/Search/destructive.go | 4 +- src/Search/incremental/rules.go | 12 +- src/Search/incremental/rulesManager.go | 12 +- src/Search/nonDestructiveSearch.go | 4 +- src/Search/proof.go | 12 +- src/Search/rules.go | 24 +- src/Search/state.go | 4 +- src/Typing/form_rules.go | 9 +- src/Typing/launch_rules.go | 10 +- src/Typing/rules.go | 14 +- src/Typing/type.go | 10 +- src/Unif/code-trees.go | 48 +-- src/Unif/data_structure.go | 5 +- src/Unif/matching.go | 2 +- src/Unif/parsing.go | 6 +- src/main.go | 10 +- 43 files changed, 708 insertions(+), 657 deletions(-) rename src/AST/{formula_list.go => form-list.go} (58%) diff --git a/src/AST/formula_list.go b/src/AST/form-list.go similarity index 58% rename from src/AST/formula_list.go rename to src/AST/form-list.go index e0762008..b5aad920 100644 --- a/src/AST/formula_list.go +++ b/src/AST/form-list.go @@ -31,71 +31,38 @@ **/ /** -* This file contains functions and types which describe the fomula_list's data -* structure +* This file contains utility functions for list of formulas **/ package AST import ( - "sort" - - "github.com/GoelandProver/Goeland/Glob" + "github.com/GoelandProver/Goeland/Lib" ) -type FormList struct { - *Glob.List[Form] -} - -func NewFormList(slice ...Form) *FormList { - return &FormList{Glob.NewList(slice...)} -} - -func (fl *FormList) Less(i, j int) bool { - return (fl.Get(i).ToString() < fl.Get(j).ToString()) -} - -func (fl *FormList) Copy() *FormList { - return &FormList{fl.List.Copy()} +// ex-name: ReplaceMetaByTerm +func LsSubstByTerm(formulas Lib.List[Form], meta Meta, term Term) Lib.List[Form] { + for i, f := range formulas.GetSlice() { + formulas.Upd(i, f.ReplaceMetaByTerm(meta, term)) + } + return formulas } -func (lf *FormList) ToMappableStringSlice() []MappableString { +// ex-name: ToMappableStringSlice +func LsToMappableStringSlice(formulas Lib.List[Form]) []MappableString { forms := []MappableString{} - - for _, form := range lf.Slice() { + for _, form := range formulas.GetSlice() { forms = append(forms, form.(MappableString)) } - return forms } -func (fl *FormList) Equals(other *FormList) bool { - if fl.Len() != other.Len() { - return false - } - - flSorted := fl.Copy() - sort.Sort(flSorted) +func LsFlatten(formulas Lib.List[Form]) Lib.List[Form] { + result := Lib.NewList[Form]() - otherSorted := other.Copy() - sort.Sort(otherSorted) - - for i := range flSorted.Slice() { - if !flSorted.Get(i).Equals(otherSorted.Get(i)) { - return false - } - } - - return true -} - -// Removes all AND formulas: {(a & b), (b => c), (d & (e & f))} -> {(a), (b), (b => c), (d), (e), (f)} -func (fl *FormList) Flatten() *FormList { - result := NewFormList() - - for _, form := range fl.Slice() { + for _, form := range formulas.GetSlice() { if typed, ok := form.(And); ok { - result.Append(typed.FormList.Flatten().Slice()...) + result.Append(LsFlatten(typed.GetChildFormulas()).GetSlice()...) } else { result.Append(form) } @@ -103,11 +70,3 @@ func (fl *FormList) Flatten() *FormList { return result } - -func (fl *FormList) ReplaceMetaByTerm(meta Meta, term Term) *FormList { - for i, f := range fl.Slice() { - fl.Set(i, f.ReplaceMetaByTerm(meta, term)) - } - - return fl -} diff --git a/src/AST/formsDef.go b/src/AST/formsDef.go index e6839766..e8b55413 100644 --- a/src/AST/formsDef.go +++ b/src/AST/formsDef.go @@ -46,10 +46,10 @@ import ( // ----------------------------------------------------------------------------- // Utility functions -func getAllSubFormulasAppended(f Form) *FormList { - subforms := NewFormList(f.Copy()) - for _, sf := range f.GetChildFormulas().Slice() { - subforms.Append(sf.GetSubFormulasRecur().Slice()...) +func getAllSubFormulasAppended(f Form) Lib.List[Form] { + subforms := Lib.MkListV(f.Copy()) + for _, sf := range f.GetChildFormulas().GetSlice() { + subforms.Append(sf.GetSubFormulasRecur().GetSlice()...) } return subforms } @@ -57,14 +57,14 @@ func getAllSubFormulasAppended(f Form) *FormList { func substVarByMetaInFormList( old Var, new Meta, - formList *FormList, + formList Lib.List[Form], metas Lib.Set[Meta], -) (replacedFormList *FormList, newMetas Lib.Set[Meta]) { - replacedFormList = NewFormList() +) (replacedFormList Lib.List[Form], newMetas Lib.Set[Meta]) { + replacedFormList = Lib.NewList[Form]() newMetas = metas.Copy() found := false - for _, form := range formList.Slice() { + for _, form := range formList.GetSlice() { replacedForm := form.SubstituteVarByMeta(old, new) replacedFormList.Append(replacedForm) @@ -107,7 +107,7 @@ func (a All) Equals(other any) bool { return false } -func (a All) GetSubFormulasRecur() *FormList { +func (a All) GetSubFormulasRecur() Lib.List[Form] { return getAllSubFormulasAppended(a) } @@ -163,7 +163,7 @@ func (e Ex) Equals(other any) bool { return false } -func (e Ex) GetSubFormulasRecur() *FormList { +func (e Ex) GetSubFormulasRecur() Lib.List[Form] { return getAllSubFormulasAppended(e) } @@ -255,7 +255,7 @@ func (a AllType) ToMappedStringChild(mapping MapString, displayTypes bool) (sepa } func (a AllType) GetChildrenForMappedString() []MappableString { - return a.GetChildFormulas().ToMappableStringSlice() + return LsToMappableStringSlice(a.GetChildFormulas()) } func (a AllType) forceGetMetas() Lib.Set[Meta] { @@ -312,12 +312,12 @@ func (a AllType) SubstituteVarByMeta(old Var, new Meta) Form { return MakeAllTypeSimple(a.index, a.tvList, f, a.metas.Raw()) } -func (a AllType) GetSubFormulasRecur() *FormList { +func (a AllType) GetSubFormulasRecur() Lib.List[Form] { return getAllSubFormulasAppended(a) } -func (a AllType) GetChildFormulas() *FormList { - return NewFormList(a.GetForm()) +func (a AllType) GetChildFormulas() Lib.List[Form] { + return Lib.MkListV(a.GetForm()) } func (e AllType) ReplaceMetaByTerm(meta Meta, term Term) Form { @@ -330,24 +330,24 @@ func (e AllType) ReplaceMetaByTerm(meta Meta, term Term) Form { type Or struct { *MappedString index int - *FormList + forms Lib.List[Form] metas Lib.Cache[Lib.Set[Meta], Or] } /** Constructors **/ -func MakeOrSimple(i int, forms *FormList, metas Lib.Set[Meta]) Or { +func MakeOrSimple(i int, forms Lib.List[Form], metas Lib.Set[Meta]) Or { fms := &MappedString{} or := Or{fms, i, forms, Lib.MkCache(metas, Or.forceGetMetas)} fms.MappableString = &or return or } -func MakeOr(i int, forms *FormList) Or { +func MakeOr(i int, forms Lib.List[Form]) Or { return MakeOrSimple(i, forms, Lib.EmptySet[Meta]()) } -func MakerOr(forms *FormList) Or { +func MakerOr(forms Lib.List[Form]) Or { return MakeOr(MakerIndexFormula(), forms) } @@ -360,7 +360,7 @@ func (o Or) GetIndex() int { } func (o Or) forceGetMetas() Lib.Set[Meta] { - return metasUnion(o.FormList) + return metasUnion(o.forms) } func (o Or) GetMetas() Lib.Set[Meta] { @@ -374,7 +374,7 @@ func (o Or) GetType() TypeScheme { func (o Or) GetSubTerms() Lib.List[Term] { res := Lib.NewList[Term]() - for _, tl := range o.FormList.Slice() { + for _, tl := range o.forms.GetSlice() { res.Add(TermEquals, tl.GetSubTerms().GetSlice()...) } @@ -383,7 +383,7 @@ func (o Or) GetSubTerms() Lib.List[Term] { func (o Or) Equals(f any) bool { oth, isOr := f.(Or) - return isOr && oth.FormList.Equals(o.FormList) + return isOr && Lib.ListEquals(oth.forms, o.forms) } func (o Or) Copy() Form { @@ -391,7 +391,7 @@ func (o Or) Copy() Form { or := Or{ fms, o.index, - o.FormList.Copy(), + Lib.ListCpy(o.forms), o.metas.Copy(Lib.Set[Meta].Copy), } fms.MappableString = &or @@ -411,15 +411,15 @@ func (o Or) ToMappedStringChild(mapping MapString, displayTypes bool) (separator } func (o Or) GetChildrenForMappedString() []MappableString { - return o.GetChildFormulas().ToMappableStringSlice() + return LsToMappableStringSlice(o.GetChildFormulas()) } func (o Or) ReplaceTypeByMeta(varList []TypeVar, index int) Form { - return MakeOr(o.GetIndex(), replaceList(o.FormList, varList, index)) + return MakeOr(o.GetIndex(), replaceList(o.forms, varList, index)) } func (o Or) ReplaceTermByTerm(old Term, new Term) (Form, bool) { - formList, res := replaceTermInFormList(o.FormList, old, new) + formList, res := replaceTermInFormList(o.forms, old, new) no := MakeOrSimple(o.GetIndex(), formList, o.metas.Raw()) if !res && !o.metas.NeedsUpd() { no.metas.AvoidUpd() @@ -428,24 +428,24 @@ func (o Or) ReplaceTermByTerm(old Term, new Term) (Form, bool) { } func (o Or) RenameVariables() Form { - return MakeOr(o.GetIndex(), renameFormList(o.FormList)) + return MakeOr(o.GetIndex(), renameFormList(o.forms)) } func (o Or) SubstituteVarByMeta(old Var, new Meta) Form { - newFormList, newMetas := substVarByMetaInFormList(old, new, o.FormList, o.metas.Raw()) + newFormList, newMetas := substVarByMetaInFormList(old, new, o.forms, o.metas.Raw()) return MakeOrSimple(o.index, newFormList, newMetas) } -func (o Or) GetSubFormulasRecur() *FormList { +func (o Or) GetSubFormulasRecur() Lib.List[Form] { return getAllSubFormulasAppended(o) } -func (o Or) GetChildFormulas() *FormList { - return o.FormList +func (o Or) GetChildFormulas() Lib.List[Form] { + return o.forms } func (o Or) ReplaceMetaByTerm(meta Meta, term Term) Form { - return MakeOr(o.GetIndex(), o.FormList.ReplaceMetaByTerm(meta, term)) + return MakeOr(o.GetIndex(), LsSubstByTerm(o.forms, meta, term)) } // ----------------------------------------------------------------------------- @@ -454,32 +454,33 @@ func (o Or) ReplaceMetaByTerm(meta Meta, term Term) Form { type And struct { *MappedString index int - *FormList + forms Lib.List[Form] metas Lib.Cache[Lib.Set[Meta], And] } /** Constructors **/ -func MakeAndSimple(i int, forms *FormList, metas Lib.Set[Meta]) And { +func MakeAndSimple(i int, forms Lib.List[Form], metas Lib.Set[Meta]) And { fms := &MappedString{} and := And{fms, i, forms, Lib.MkCache(metas, And.forceGetMetas)} fms.MappableString = &and return and } -func MakeAndSimpleBinary(i int, forms *FormList, metas Lib.Set[Meta]) And { +func MakeAndSimpleBinary(i int, forms Lib.List[Form], metas Lib.Set[Meta]) And { switch forms.Len() { + // FIXME: case 0 and 1 should error, no? case 0, 1, 2: return MakeAndSimple(i, forms, metas) default: return MakeAndSimple( i, - NewFormList([]Form{forms.Get(0), MakerAnd(NewFormList(forms.GetElements(1, forms.Len())...), true)}...), + Lib.MkListV[Form](forms.At(0), MakerAnd(forms.Slice(1, forms.Len()), true)), metas) } } -func MakeAnd(i int, forms *FormList, binary ...bool) And { +func MakeAnd(i int, forms Lib.List[Form], binary ...bool) And { if binary != nil { return MakeAndSimpleBinary(i, forms, Lib.EmptySet[Meta]()) } else { @@ -487,7 +488,7 @@ func MakeAnd(i int, forms *FormList, binary ...bool) And { } } -func MakerAnd(forms *FormList, binary ...bool) And { +func MakerAnd(forms Lib.List[Form], binary ...bool) And { return MakeAnd(MakerIndexFormula(), forms, binary...) } @@ -500,7 +501,7 @@ func (a And) GetIndex() int { } func (a And) forceGetMetas() Lib.Set[Meta] { - return metasUnion(a.FormList) + return metasUnion(a.forms) } func (a And) GetMetas() Lib.Set[Meta] { @@ -514,7 +515,7 @@ func (a And) GetType() TypeScheme { func (a And) GetSubTerms() Lib.List[Term] { res := Lib.NewList[Term]() - for _, tl := range a.FormList.Slice() { + for _, tl := range a.forms.GetSlice() { res.Add(TermEquals, tl.GetSubTerms().GetSlice()...) } @@ -523,7 +524,7 @@ func (a And) GetSubTerms() Lib.List[Term] { func (a And) Equals(other any) bool { if typed, ok := other.(And); ok { - return typed.FormList.Equals(a.FormList) + return Lib.ListEquals(typed.forms, a.forms) } return false @@ -534,7 +535,7 @@ func (a And) Copy() Form { and := And{ fms, a.index, - a.FormList.Copy(), + Lib.ListCpy(a.forms), a.metas.Copy(Lib.Set[Meta].Copy), } fms.MappableString = &and @@ -554,15 +555,15 @@ func (a And) ToMappedStringChild(mapping MapString, displayTypes bool) (separato } func (a And) GetChildrenForMappedString() []MappableString { - return a.GetChildFormulas().ToMappableStringSlice() + return LsToMappableStringSlice(a.GetChildFormulas()) } func (a And) ReplaceTypeByMeta(varList []TypeVar, index int) Form { - return MakeAnd(a.GetIndex(), replaceList(a.FormList, varList, index)) + return MakeAnd(a.GetIndex(), replaceList(a.forms, varList, index)) } func (a And) ReplaceTermByTerm(old Term, new Term) (Form, bool) { - varList, res := replaceTermInFormList(a.FormList, old, new) + varList, res := replaceTermInFormList(a.forms, old, new) na := MakeAndSimple(a.index, varList, a.metas.Raw()) if !res && !a.metas.NeedsUpd() { na.metas.AvoidUpd() @@ -571,24 +572,24 @@ func (a And) ReplaceTermByTerm(old Term, new Term) (Form, bool) { } func (a And) RenameVariables() Form { - return MakeAnd(a.GetIndex(), renameFormList(a.FormList)) + return MakeAnd(a.GetIndex(), renameFormList(a.forms)) } func (a And) SubstituteVarByMeta(old Var, new Meta) Form { - newFormList, newMetas := substVarByMetaInFormList(old, new, a.FormList, a.metas.Raw()) + newFormList, newMetas := substVarByMetaInFormList(old, new, a.forms, a.metas.Raw()) return MakeAndSimple(a.index, newFormList, newMetas) } -func (a And) GetSubFormulasRecur() *FormList { +func (a And) GetSubFormulasRecur() Lib.List[Form] { return getAllSubFormulasAppended(a) } -func (a And) GetChildFormulas() *FormList { - return a.FormList +func (a And) GetChildFormulas() Lib.List[Form] { + return a.forms } func (a And) ReplaceMetaByTerm(meta Meta, term Term) Form { - return MakeAnd(a.GetIndex(), a.FormList.ReplaceMetaByTerm(meta, term)) + return MakeAnd(a.GetIndex(), LsSubstByTerm(a.forms, meta, term)) } // ----------------------------------------------------------------------------- @@ -631,7 +632,7 @@ func (e Equ) ToMappedStringChild(mapping MapString, displayTypes bool) (separato } func (e Equ) GetChildrenForMappedString() []MappableString { - return e.GetChildFormulas().ToMappableStringSlice() + return LsToMappableStringSlice(e.GetChildFormulas()) } func (e Equ) GetIndex() int { return e.index } @@ -698,16 +699,16 @@ func (e Equ) GetSubTerms() Lib.List[Term] { } func (e Equ) SubstituteVarByMeta(old Var, new Meta) Form { - fl, metas := substVarByMetaInFormList(old, new, NewFormList(e.f1, e.f2), e.metas.Raw()) - return MakeEquSimple(e.index, fl.Get(0), fl.Get(1), metas) + fl, metas := substVarByMetaInFormList(old, new, Lib.MkListV(e.f1, e.f2), e.metas.Raw()) + return MakeEquSimple(e.index, fl.At(0), fl.At(1), metas) } -func (e Equ) GetSubFormulasRecur() *FormList { +func (e Equ) GetSubFormulasRecur() Lib.List[Form] { return getAllSubFormulasAppended(e) } -func (e Equ) GetChildFormulas() *FormList { - return NewFormList(e.f1, e.f2) +func (e Equ) GetChildFormulas() Lib.List[Form] { + return Lib.MkListV(e.f1, e.f2) } func (e Equ) ReplaceMetaByTerm(meta Meta, term Term) Form { @@ -754,7 +755,7 @@ func (i Imp) ToMappedStringChild(mapping MapString, displayTypes bool) (separato } func (i Imp) GetChildrenForMappedString() []MappableString { - return i.GetChildFormulas().ToMappableStringSlice() + return LsToMappableStringSlice(i.GetChildFormulas()) } func (i Imp) GetIndex() int { return i.index } @@ -824,16 +825,16 @@ func (i Imp) GetSubTerms() Lib.List[Term] { } func (i Imp) SubstituteVarByMeta(old Var, new Meta) Form { - fl, metas := substVarByMetaInFormList(old, new, NewFormList(i.f1, i.f2), i.metas.Raw()) - return MakeImpSimple(i.index, fl.Get(0), fl.Get(1), metas) + fl, metas := substVarByMetaInFormList(old, new, Lib.MkListV(i.f1, i.f2), i.metas.Raw()) + return MakeImpSimple(i.index, fl.At(0), fl.At(1), metas) } -func (i Imp) GetSubFormulasRecur() *FormList { +func (i Imp) GetSubFormulasRecur() Lib.List[Form] { return getAllSubFormulasAppended(i) } -func (i Imp) GetChildFormulas() *FormList { - return NewFormList(i.f1, i.f2) +func (i Imp) GetChildFormulas() Lib.List[Form] { + return Lib.MkListV(i.f1, i.f2) } func (i Imp) ReplaceMetaByTerm(meta Meta, term Term) Form { @@ -920,7 +921,7 @@ func (n Not) ToMappedStringChild(mapping MapString, displayTypes bool) (separato } func (n Not) GetChildrenForMappedString() []MappableString { - return n.GetChildFormulas().ToMappableStringSlice() + return LsToMappableStringSlice(n.GetChildFormulas()) } func (n Not) ReplaceTypeByMeta(varList []TypeVar, index int) Form { @@ -957,12 +958,12 @@ func (n Not) SubstituteVarByMeta(old Var, new Meta) Form { return MakeNotSimple(n.index, f, f.GetMetas().Copy()) } -func (n Not) GetSubFormulasRecur() *FormList { +func (n Not) GetSubFormulasRecur() Lib.List[Form] { return getAllSubFormulasAppended(n) } -func (n Not) GetChildFormulas() *FormList { - return NewFormList(n.GetForm()) +func (n Not) GetChildFormulas() Lib.List[Form] { + return Lib.MkListV(n.GetForm()) } /** Utils **/ @@ -1228,12 +1229,12 @@ func (p Pred) SubstituteVarByMeta(old Var, new Meta) Form { return f } -func (p Pred) GetSubFormulasRecur() *FormList { - return NewFormList(p.Copy()) +func (p Pred) GetSubFormulasRecur() Lib.List[Form] { + return Lib.MkListV(p.Copy()) } -func (p Pred) GetChildFormulas() *FormList { - return NewFormList() +func (p Pred) GetChildFormulas() Lib.List[Form] { + return Lib.NewList[Form]() } func (p Pred) ReplaceMetaByTerm(meta Meta, term Term) Form { @@ -1279,7 +1280,7 @@ func (t Top) ToMappedStringChild(mapping MapString, displayTypes bool) (separato } func (t Top) GetChildrenForMappedString() []MappableString { - return t.GetChildFormulas().ToMappableStringSlice() + return LsToMappableStringSlice(t.GetChildFormulas()) } func (t Top) GetType() TypeScheme { return DefaultPropType(0) } @@ -1293,8 +1294,8 @@ func (t Top) GetIndex() int { return t.index } func (t Top) GetSubTerms() Lib.List[Term] { return Lib.NewList[Term]() } func (t Top) SubstituteVarByMeta(Var, Meta) Form { return t } func (t Top) GetInternalMetas() Lib.Set[Meta] { return Lib.EmptySet[Meta]() } -func (t Top) GetSubFormulasRecur() *FormList { return NewFormList(t.Copy()) } -func (t Top) GetChildFormulas() *FormList { return NewFormList() } +func (t Top) GetSubFormulasRecur() Lib.List[Form] { return Lib.MkListV[Form](t) } +func (t Top) GetChildFormulas() Lib.List[Form] { return Lib.NewList[Form]() } func (t Top) ReplaceMetaByTerm(meta Meta, term Term) Form { return t } /* Bot (always false) definition */ @@ -1323,7 +1324,7 @@ func (b Bot) ToMappedStringChild(mapping MapString, displayTypes bool) (separato } func (b Bot) GetChildrenForMappedString() []MappableString { - return b.GetChildFormulas().ToMappableStringSlice() + return LsToMappableStringSlice(b.GetChildFormulas()) } func (b Bot) GetType() TypeScheme { return DefaultPropType(0) } @@ -1337,6 +1338,6 @@ func (b Bot) GetIndex() int { return b.index } func (b Bot) GetSubTerms() Lib.List[Term] { return Lib.NewList[Term]() } func (b Bot) SubstituteVarByMeta(Var, Meta) Form { return b } func (b Bot) GetInternalMetas() Lib.Set[Meta] { return Lib.EmptySet[Meta]() } -func (b Bot) GetSubFormulasRecur() *FormList { return NewFormList(b.Copy()) } -func (b Bot) GetChildFormulas() *FormList { return NewFormList() } +func (b Bot) GetSubFormulasRecur() Lib.List[Form] { return Lib.MkListV[Form](b) } +func (b Bot) GetChildFormulas() Lib.List[Form] { return Lib.NewList[Form]() } func (b Bot) ReplaceMetaByTerm(meta Meta, term Term) Form { return b } diff --git a/src/AST/formula.go b/src/AST/formula.go index 87bb1033..0b50c2f6 100644 --- a/src/AST/formula.go +++ b/src/AST/formula.go @@ -48,8 +48,8 @@ type Form interface { GetMetas() Lib.Set[Meta] GetType() TypeScheme GetSubTerms() Lib.List[Term] - GetSubFormulasRecur() *FormList - GetChildFormulas() *FormList + GetSubFormulasRecur() Lib.List[Form] + GetChildFormulas() Lib.List[Form] Lib.Copyable[Form] MappableString @@ -132,47 +132,45 @@ func instanciateTypeAppList(typeApps []TypeApp, vars []TypeVar, index int) []Typ return typeVars } -// Creates and returns a MetaList from a FormList, making sure there are no duplicates -func metasUnion(forms *FormList) Lib.Set[Meta] { +func metasUnion(forms Lib.List[Form]) Lib.Set[Meta] { res := Lib.EmptySet[Meta]() - for _, form := range forms.Slice() { + for _, form := range forms.GetSlice() { res = res.Union(form.GetMetas()) } return res } -// Creates and returns a FormList -func replaceList(oldForms *FormList, vars []TypeVar, index int) *FormList { - newForms := NewFormList() +func replaceList(oldForms Lib.List[Form], vars []TypeVar, index int) Lib.List[Form] { + newForms := Lib.MkList[Form](oldForms.Len()) - for _, form := range oldForms.Slice() { - newForms.Append(form.ReplaceTypeByMeta(vars, index)) + for i, form := range oldForms.GetSlice() { + newForms.Upd(i, form.ReplaceTypeByMeta(vars, index)) } return newForms } -func replaceTermInFormList(oldForms *FormList, oldTerm Term, newTerm Term) (*FormList, bool) { - newForms := NewFormList() +// Returns whether the term has been replaced in a subformula or not +func replaceTermInFormList(oldForms Lib.List[Form], oldTerm Term, newTerm Term) (Lib.List[Form], bool) { + newForms := Lib.MkList[Form](oldForms.Len()) res := false - for _, form := range oldForms.Slice() { + for i, form := range oldForms.GetSlice() { newForm, r := form.ReplaceTermByTerm(oldTerm, newTerm) res = res || r - newForms.Append(newForm) + newForms.Upd(i, newForm) } return newForms, res } -// Creates and returns a FormList with its Forms renamed -func renameFormList(forms *FormList) *FormList { - newForms := NewFormList() +func renameFormList(forms Lib.List[Form]) Lib.List[Form] { + newForms := Lib.MkList[Form](forms.Len()) - for _, form := range forms.Slice() { - newForms.Append(form.RenameVariables()) + for i, form := range forms.GetSlice() { + newForms.Upd(i, form.RenameVariables()) } return newForms diff --git a/src/AST/quantifiers.go b/src/AST/quantifiers.go index 3f9ca9f0..6872063e 100644 --- a/src/AST/quantifiers.go +++ b/src/AST/quantifiers.go @@ -143,11 +143,11 @@ func (q quantifier) ToMappedStringSurround(mapping MapString, displayTypes bool) } func (q quantifier) GetChildrenForMappedString() []MappableString { - return q.GetChildFormulas().ToMappableStringSlice() + return LsToMappableStringSlice(q.GetChildFormulas()) } -func (q quantifier) GetChildFormulas() *FormList { - return NewFormList(q.GetForm()) +func (q quantifier) GetChildFormulas() Lib.List[Form] { + return Lib.MkListV(q.GetForm()) } func (q quantifier) Equals(other any) bool { diff --git a/src/Core/FormListDS.go b/src/Core/FormListDS.go index cc31e8b0..c07a6662 100644 --- a/src/Core/FormListDS.go +++ b/src/Core/FormListDS.go @@ -38,30 +38,34 @@ import ( ) type FormListDS struct { - fl *AST.FormList + fl Lib.List[AST.Form] } -func (f FormListDS) GetFL() *AST.FormList { - return f.fl.Copy() +func (f FormListDS) GetFL() Lib.List[AST.Form] { + return Lib.ListCpy(f.fl) } /* Data struct */ /* Take a list of formula and return a FormList (Datastructure type) */ -func (f FormListDS) MakeDataStruct(lf *AST.FormList, is_pos bool) Unif.DataStructure { +func (f FormListDS) MakeDataStruct(lf Lib.List[AST.Form], is_pos bool) Unif.DataStructure { return (new(FormListDS)).InsertFormulaListToDataStructure(lf) } /* Insert a list of formula into the given Datastructure (here, FormList) */ -func (f FormListDS) InsertFormulaListToDataStructure(lf *AST.FormList) Unif.DataStructure { - for _, v := range lf.Slice() { +func (f FormListDS) InsertFormulaListToDataStructure(lf Lib.List[AST.Form]) Unif.DataStructure { + for _, v := range lf.GetSlice() { switch nf := v.(type) { case AST.Pred: - f.fl.AppendIfNotContains(nf) + if !Lib.ListMem(nf.Copy(), f.fl) { + f.fl.Append(nf) + } case AST.Not: switch nf.GetForm().(type) { case AST.Pred: - f.fl.AppendIfNotContains(nf.GetForm()) + if !Lib.ListMem(nf.Copy(), f.fl) { + f.fl.Append(nf) + } } } } @@ -69,21 +73,21 @@ func (f FormListDS) InsertFormulaListToDataStructure(lf *AST.FormList) Unif.Data } func (f FormListDS) Print() { - for _, f := range f.GetFL().Slice() { + for _, f := range f.GetFL().GetSlice() { debug(Lib.MkLazy(func() string { return f.ToString() })) } } func (f FormListDS) Copy() Unif.DataStructure { - return FormListDS{f.GetFL().Copy()} + return FormListDS{Lib.ListCpy(f.GetFL())} } func (fl FormListDS) IsEmpty() bool { - return fl.GetFL().IsEmpty() + return fl.GetFL().Empty() } func (fl FormListDS) Unify(f AST.Form) (bool, []Unif.MatchingSubstitutions) { - for _, element := range fl.GetFL().Slice() { + for _, element := range fl.GetFL().GetSlice() { if element.Equals(f) { return true, []Unif.MatchingSubstitutions{} } diff --git a/src/Core/Sko/preinner-skolemization.go b/src/Core/Sko/preinner-skolemization.go index ae155d71..8ac9fab2 100644 --- a/src/Core/Sko/preinner-skolemization.go +++ b/src/Core/Sko/preinner-skolemization.go @@ -141,9 +141,9 @@ func alphaConvert( case AST.And: return AST.MakeAnd( f.GetIndex(), - AST.NewFormList( + Lib.MkListV( Glob.MapTo( - f.FormList.Slice(), + f.GetChildFormulas().GetSlice(), func(_ int, f AST.Form) AST.Form { return alphaConvert(f, k, substitution) })...), @@ -151,8 +151,8 @@ func alphaConvert( case AST.Or: return AST.MakeOr( f.GetIndex(), - AST.NewFormList(Glob.MapTo( - f.FormList.Slice(), + Lib.MkListV(Glob.MapTo( + f.GetChildFormulas().GetSlice(), func(_ int, f AST.Form) AST.Form { return alphaConvert(f, k, substitution) })...), diff --git a/src/Core/form_and_terms_list.go b/src/Core/form_and_terms_list.go index 077726e4..f10b0d98 100644 --- a/src/Core/form_and_terms_list.go +++ b/src/Core/form_and_terms_list.go @@ -110,9 +110,9 @@ func (fl FormAndTermsList) Copy() FormAndTermsList { } /* Create a FaT List from a FormList */ -func MakeFTListFromFormList(l *AST.FormList) FormAndTermsList { +func MakeFTListFromFormList(l Lib.List[AST.Form]) FormAndTermsList { res := MakeEmptyFormAndTermsList() - for _, f := range l.Slice() { + for _, f := range l.GetSlice() { res = append(res, MakeFormAndTerm(f.Copy(), Lib.MkList[AST.Term](0))) } return res @@ -183,10 +183,10 @@ func (l1 FormAndTermsList) Merge(l2 FormAndTermsList) FormAndTermsList { return res } -func (fl FormAndTermsList) ExtractForms() *AST.FormList { - res := AST.NewFormList() +func (fl FormAndTermsList) ExtractForms() Lib.List[AST.Form] { + res := Lib.NewList[AST.Form]() for _, f := range fl { - res.AppendIfNotContains(f.GetForm()) + res = Lib.ListAdd(res, f.GetForm()) } return res } diff --git a/src/Core/int_subst_and_form.go b/src/Core/int_subst_and_form.go index 8af75b7e..a223dae7 100644 --- a/src/Core/int_subst_and_form.go +++ b/src/Core/int_subst_and_form.go @@ -39,6 +39,7 @@ package Core import ( "strconv" + "github.com/GoelandProver/Goeland/Lib" "github.com/GoelandProver/Goeland/Unif" ) @@ -84,8 +85,8 @@ func (s IntSubstAndForm) ToString() string { res += s.GetSaf().GetSubst().ToString() } res += " - " - if !s.GetSaf().GetForm().IsEmpty() { - res += s.GetSaf().GetForm().ToString() + if !s.GetSaf().GetForm().Empty() { + res += Lib.ListToString(s.GetSaf().GetForm(), ", ", "[]") } res += " }" diff --git a/src/Core/subst_and_form.go b/src/Core/subst_and_form.go index 92629c59..997a1dd5 100644 --- a/src/Core/subst_and_form.go +++ b/src/Core/subst_and_form.go @@ -42,32 +42,34 @@ import ( "github.com/GoelandProver/Goeland/AST" "github.com/GoelandProver/Goeland/Glob" + "github.com/GoelandProver/Goeland/Lib" "github.com/GoelandProver/Goeland/Unif" ) /* Stock the substitution and the corresponding list of formulas */ type SubstAndForm struct { s Unif.Substitutions - f *AST.FormList + f Lib.List[AST.Form] } func (s SubstAndForm) GetSubst() Unif.Substitutions { return s.s.Copy() } -func (s SubstAndForm) GetForm() *AST.FormList { - return s.f.Copy() +func (s SubstAndForm) GetForm() Lib.List[AST.Form] { + return Lib.ListCpy(s.f) } func (s *SubstAndForm) SetSubst(subst Unif.Substitutions) { s.s = subst.Copy() } -func (s *SubstAndForm) SetForm(form *AST.FormList) { - s.f = form.Copy() +func (s *SubstAndForm) SetForm(form Lib.List[AST.Form]) { + s.f = Lib.ListCpy(form) } func (saf SubstAndForm) IsEmpty() bool { - return saf.s.IsEmpty() && saf.f.IsEmpty() + return saf.s.IsEmpty() && saf.f.Empty() } func (s1 SubstAndForm) Equals(s2 SubstAndForm) bool { - return s1.GetSubst().Equals(s2.GetSubst()) && s1.GetForm().Equals(s2.GetForm()) + return s1.GetSubst().Equals(s2.GetSubst()) && + Lib.ListEquals(s1.GetForm(), s2.GetForm()) } func (s SubstAndForm) Copy() SubstAndForm { if s.IsEmpty() { @@ -82,23 +84,23 @@ func (s SubstAndForm) ToString() string { res += s.GetSubst().ToString() } res += " - " - if !s.GetForm().IsEmpty() { - res += s.GetForm().ToString() + if !s.GetForm().Empty() { + res += Lib.ListToString(s.GetForm(), ", ", "[]") } res += " }" return res } -func MakeSubstAndForm(subst Unif.Substitutions, form *AST.FormList) SubstAndForm { - return SubstAndForm{subst.Copy(), form.Copy()} +func MakeSubstAndForm(subst Unif.Substitutions, form Lib.List[AST.Form]) SubstAndForm { + return SubstAndForm{subst.Copy(), Lib.ListCpy(form)} } func MakeEmptySubstAndForm() SubstAndForm { - return SubstAndForm{Unif.MakeEmptySubstitution(), AST.NewFormList()} + return SubstAndForm{Unif.MakeEmptySubstitution(), Lib.NewList[AST.Form]()} } -func (s SubstAndForm) AddFormulas(fl *AST.FormList) SubstAndForm { - formList := s.GetForm().Copy() - formList.AppendIfNotContains(fl.Copy().Slice()...) +func (s SubstAndForm) AddFormulas(fl Lib.List[AST.Form]) SubstAndForm { + formList := s.GetForm() + formList = Lib.ListAdd(formList, Lib.ListCpy(fl).GetSlice()...) return MakeSubstAndForm(s.GetSubst(), formList) } @@ -202,8 +204,8 @@ func MergeSubstAndForm(s1, s2 SubstAndForm) (error, SubstAndForm) { return errors.New("Couldn't merge two substitutions"), MakeEmptySubstAndForm() } - newFormList := s1.GetForm().Copy() - newFormList.AppendIfNotContains(s2.GetForm().Slice()...) + newFormList := s1.GetForm() + newFormList = Lib.ListAdd(newFormList, s2.GetForm().GetSlice()...) return nil, MakeSubstAndForm(new_subst, newFormList) } diff --git a/src/Core/substitutions_search.go b/src/Core/substitutions_search.go index 51403ed8..15df6500 100644 --- a/src/Core/substitutions_search.go +++ b/src/Core/substitutions_search.go @@ -293,14 +293,14 @@ func ApplySubstitutionOnFormula(old_symbol AST.Meta, new_symbol AST.Term, f AST. case AST.Not: res = AST.MakeNot(f.GetIndex(), ApplySubstitutionOnFormula(old_symbol, new_symbol, nf.GetForm())) case AST.And: - res_tmp := AST.NewFormList() - for _, val := range nf.FormList.Slice() { + res_tmp := Lib.NewList[AST.Form]() + for _, val := range nf.GetChildFormulas().GetSlice() { res_tmp.Append(ApplySubstitutionOnFormula(old_symbol, new_symbol, val)) } res = AST.MakeAnd(f.GetIndex(), res_tmp) case AST.Or: - res_tmp := AST.NewFormList() - for _, val := range nf.FormList.Slice() { + res_tmp := Lib.NewList[AST.Form]() + for _, val := range nf.GetChildFormulas().GetSlice() { res_tmp.Append(ApplySubstitutionOnFormula(old_symbol, new_symbol, val)) } res = AST.MakeOr(f.GetIndex(), res_tmp) @@ -334,11 +334,11 @@ func ApplySubstitutionsOnFormula(s Unif.Substitutions, f AST.Form) AST.Form { } /* For each element of the substitution, apply it on the entire formula list */ -func ApplySubstitutionsOnFormulaList(s Unif.Substitutions, lf *AST.FormList) *AST.FormList { - lf_res := AST.NewFormList() - for _, f := range lf.Slice() { +func ApplySubstitutionsOnFormulaList(s Unif.Substitutions, lf Lib.List[AST.Form]) Lib.List[AST.Form] { + lf_res := Lib.NewList[AST.Form]() + for _, f := range lf.GetSlice() { new_form := ApplySubstitutionsOnFormula(s, f) - lf_res.AppendIfNotContains(new_form) + lf_res = Lib.ListAdd(lf_res, new_form) } return lf_res diff --git a/src/Engine/syntax-translation.go b/src/Engine/syntax-translation.go index 8efed527..0e27ead9 100644 --- a/src/Engine/syntax-translation.go +++ b/src/Engine/syntax-translation.go @@ -229,8 +229,7 @@ func elaborateForm(con Context, f, source_form Parser.PForm) AST.Form { func maybeFlattenOr(con Context, f Parser.PBin, source_form Parser.PForm) AST.Form { return maybeFlattenBin( con, f, source_form, - // FIXME: get rid of the pointer - func(ls *AST.FormList) AST.Form { return AST.MakerOr(ls) }, + func(ls Lib.List[AST.Form]) AST.Form { return AST.MakerOr(ls) }, Parser.PBinaryOr, ) } @@ -238,8 +237,7 @@ func maybeFlattenOr(con Context, f Parser.PBin, source_form Parser.PForm) AST.Fo func maybeFlattenAnd(con Context, f Parser.PBin, source_form Parser.PForm) AST.Form { return maybeFlattenBin( con, f, source_form, - // FIXME: get rid of the pointer - func(ls *AST.FormList) AST.Form { return AST.MakerAnd(ls) }, + func(ls Lib.List[AST.Form]) AST.Form { return AST.MakerAnd(ls) }, Parser.PBinaryAnd, ) } @@ -248,19 +246,19 @@ func maybeFlattenBin( con Context, f Parser.PBin, source_form Parser.PForm, - maker Lib.Func[*AST.FormList, AST.Form], + maker Lib.Func[Lib.List[AST.Form], AST.Form], op Parser.PBinOp, ) AST.Form { if !Glob.Flatten() { return maker( - AST.NewFormList( + Lib.MkListV( elaborateForm(con, f.Left(), source_form), elaborateForm(con, f.Right(), source_form), )) } subforms := flatten(f, op) - forms := AST.NewFormList( + forms := Lib.MkListV( Lib.ListMap( subforms, func(f Parser.PForm) AST.Form { return elaborateForm(con, f, source_form) }, diff --git a/src/Lib/list.go b/src/Lib/list.go index 514fec51..9788610b 100644 --- a/src/Lib/list.go +++ b/src/Lib/list.go @@ -88,6 +88,10 @@ func (l List[T]) At(i int) T { return l.values[i] } +func (l List[T]) Slice(st, ed int) List[T] { + return List[T]{values: l.values[st:ed]} +} + func ListEquals[T Comparable](ls0, ls1 List[T]) bool { if ls0.Len() != ls1.Len() { return false @@ -184,6 +188,30 @@ func (l List[T]) Empty() bool { return l.Len() == 0 } +func (l List[T]) IndexOf(x T, cmp Func2[T, T, bool]) Option[int] { + for i, el := range l.values { + if cmp(x, el) { + return MkSome(i) + } + } + return MkNone[int]() +} + +func ListIndexOf[T Comparable](x T, l List[T]) Option[int] { + cmp := func(x, y T) bool { return x.Equals(y) } + return l.IndexOf(x, cmp) +} + +func (l List[T]) RemoveAt(index int) List[T] { + new_list := NewList[T]() + for i, el := range l.values { + if i != index { + new_list.Append(el) + } + } + return new_list +} + func ToStrictlyOrderedList[T StrictlyOrdered](l List[T]) StrictlyOrderedList[T] { return StrictlyOrderedList[T]{values: l} } diff --git a/src/Mods/dmt/axiom_registration.go b/src/Mods/dmt/axiom_registration.go index 7cb3e963..9bcbc094 100644 --- a/src/Mods/dmt/axiom_registration.go +++ b/src/Mods/dmt/axiom_registration.go @@ -76,7 +76,7 @@ func instanciateForalls(axiom AST.Form) AST.Form { func addPosRewriteRule(axiom AST.Form, cons AST.Form) { simplifiedAxiom := AST.RemoveNeg(axiom) positiveTree = positiveTree.InsertFormulaListToDataStructure( - AST.NewFormList(simplifiedAxiom), + Lib.MkListV(simplifiedAxiom), ) addRewriteRule(simplifiedAxiom, cons, true) } @@ -84,7 +84,7 @@ func addPosRewriteRule(axiom AST.Form, cons AST.Form) { func addNegRewriteRule(axiom AST.Form, cons AST.Form) { simplifiedAxiom := AST.RemoveNeg(axiom) negativeTree = negativeTree.InsertFormulaListToDataStructure( - AST.NewFormList(simplifiedAxiom), + Lib.MkListV(simplifiedAxiom), ) addRewriteRule(simplifiedAxiom, cons, false) } diff --git a/src/Mods/dmt/dmt.go b/src/Mods/dmt/dmt.go index e4cf0351..b97fbebc 100644 --- a/src/Mods/dmt/dmt.go +++ b/src/Mods/dmt/dmt.go @@ -42,11 +42,12 @@ import ( "github.com/GoelandProver/Goeland/AST" "github.com/GoelandProver/Goeland/Glob" + "github.com/GoelandProver/Goeland/Lib" "github.com/GoelandProver/Goeland/Unif" ) -var positiveRewrite map[string]*AST.FormList /* Stores rewrites of atoms with positive occurrences */ -var negativeRewrite map[string]*AST.FormList /* Stores rewrites of atoms with negative occurrences */ +var positiveRewrite map[string]Lib.List[AST.Form] /* Stores rewrites of atoms with positive occurrences */ +var negativeRewrite map[string]Lib.List[AST.Form] /* Stores rewrites of atoms with negative occurrences */ var positiveTree Unif.DataStructure /* Matches atoms with positive occurrences */ var negativeTree Unif.DataStructure /* Matches atoms with negative occurrences */ @@ -57,7 +58,7 @@ var preskolemize bool var flagPolarized = flag.Bool("polarized", false, "Activate polarized DMT") var flagPresko = flag.Bool("presko", false, "Activate preskolemization on DMT") -var registeredAxioms *AST.FormList +var registeredAxioms Lib.List[AST.Form] /** * Base function needed to initialize any plugin of Goéland. @@ -79,12 +80,12 @@ func InitPluginTests(polarized, presko bool) { } func initPluginGlobalVariables() { - positiveRewrite = make(map[string]*AST.FormList) - negativeRewrite = make(map[string]*AST.FormList) + positiveRewrite = make(map[string]Lib.List[AST.Form]) + negativeRewrite = make(map[string]Lib.List[AST.Form]) positiveTree = Unif.NewNode() negativeTree = Unif.NewNode() - registeredAxioms = AST.NewFormList() + registeredAxioms = Lib.NewList[AST.Form]() } /** @@ -115,7 +116,6 @@ func parsePluginOptions() { Glob.PrintInfo("DMT", output) } - -func GetRegisteredAxioms() *AST.FormList { +func GetRegisteredAxioms() Lib.List[AST.Form] { return registeredAxioms } diff --git a/src/Mods/dmt/rewrite.go b/src/Mods/dmt/rewrite.go index 2fdbbac6..3fce7f14 100644 --- a/src/Mods/dmt/rewrite.go +++ b/src/Mods/dmt/rewrite.go @@ -84,7 +84,7 @@ func getRewrittenFormulas(rewritten []Core.IntSubstAndForm, unif []Unif.Matching return rewritten, nil } -func addRewrittenFormulas(rewritten []Core.IntSubstAndForm, unif Unif.MatchingSubstitutions, atomic AST.Form, equivalence *AST.FormList) []Core.IntSubstAndForm { +func addRewrittenFormulas(rewritten []Core.IntSubstAndForm, unif Unif.MatchingSubstitutions, atomic AST.Form, equivalence Lib.List[AST.Form]) []Core.IntSubstAndForm { // Keep only useful substitutions useful_subst := Core.RemoveElementWithoutMM(unif.GetSubst(), atomic.GetMetas()) meta_search := atomic.GetMetas() @@ -97,7 +97,7 @@ func addRewrittenFormulas(rewritten []Core.IntSubstAndForm, unif Unif.MatchingSu ) // Add each candidate to the rewrite slice with precedence order (Top/Bot are prioritized). - for _, rewrittenCandidate := range equivalence.Slice() { + for _, rewrittenCandidate := range equivalence.GetSlice() { rewritten = addUnifToAtomics(rewritten, rewrittenCandidate, filteredUnif) } @@ -121,12 +121,12 @@ func getAtomAndPolarity(atom AST.Form) (AST.Form, bool) { func rewriteFailure(atomic AST.Form) []Core.IntSubstAndForm { return []Core.IntSubstAndForm{ - Core.MakeIntSubstAndForm(-1, Core.MakeSubstAndForm(Unif.Failure(), AST.NewFormList(atomic))), + Core.MakeIntSubstAndForm(-1, Core.MakeSubstAndForm(Unif.Failure(), Lib.MkListV(atomic))), } } func addUnifToAtomics(atomics []Core.IntSubstAndForm, candidate AST.Form, unif Unif.MatchingSubstitutions) []Core.IntSubstAndForm { - substAndForm := Core.MakeSubstAndForm(unif.GetSubst().Copy(), AST.NewFormList(candidate)) + substAndForm := Core.MakeSubstAndForm(unif.GetSubst().Copy(), Lib.MkListV(candidate)) if isBotOrTop(candidate) { atomics = Core.InsertFirstIntSubstAndFormList(atomics, Core.MakeIntSubstAndForm(unif.GetForm().GetIndex(), substAndForm)) } else { @@ -155,8 +155,8 @@ func sortUnifications(unifs []Unif.MatchingSubstitutions, polarity bool, atomic } // Priority of substitutions: Top/Bottom > others -func insert(sortedUnifs []Unif.MatchingSubstitutions, list *AST.FormList, unif Unif.MatchingSubstitutions) []Unif.MatchingSubstitutions { - if list.Contains(AST.MakerTop()) || list.Contains(AST.MakerBot()) { +func insert(sortedUnifs []Unif.MatchingSubstitutions, list Lib.List[AST.Form], unif Unif.MatchingSubstitutions) []Unif.MatchingSubstitutions { + if Lib.ListMem(AST.MakerTop().Copy(), list) || Lib.ListMem(AST.MakerBot().Copy(), list) { sortedUnifs = insertFirst(sortedUnifs, unif) } else { sortedUnifs = append(sortedUnifs, unif) @@ -213,21 +213,25 @@ func checkMetaAreFromSearch(metas Lib.Set[AST.Meta], subst Unif.Substitutions) b return true } -func getUnifiedEquivalence(atom AST.Form, subst Unif.Substitutions, polarity bool) (*AST.FormList, error) { +func getUnifiedEquivalence(atom AST.Form, subst Unif.Substitutions, polarity bool) (Lib.List[AST.Form], error) { equivalence := findEquivalence(atom, polarity) - if equivalence == nil { - return nil, fmt.Errorf("[DMT] Fatal error : no rewrite rule found when an unification has been found : %v", atom.ToString()) + if equivalence.Empty() { + return Lib.NewList[AST.Form](), + fmt.Errorf( + "[DMT] Fatal error : no rewrite rule found when an unification has been found : %v", + atom.ToString(), + ) } - res := AST.NewFormList() - for _, f := range equivalence.Slice() { - res.AppendIfNotContains(substitute(f, subst)) + res := Lib.NewList[AST.Form]() + for _, f := range equivalence.GetSlice() { + res = Lib.ListAdd(res, substitute(f, subst)) } return res, nil } -func findEquivalence(atom AST.Form, polarity bool) *AST.FormList { +func findEquivalence(atom AST.Form, polarity bool) Lib.List[AST.Form] { return selectFromPolarity(polarity, positiveRewrite, negativeRewrite)[atom.ToString()] } diff --git a/src/Mods/dmt/utils.go b/src/Mods/dmt/utils.go index 50454f27..3b75bfc0 100644 --- a/src/Mods/dmt/utils.go +++ b/src/Mods/dmt/utils.go @@ -38,6 +38,7 @@ package dmt import ( "github.com/GoelandProver/Goeland/AST" + "github.com/GoelandProver/Goeland/Lib" ) func isEquality(pred AST.Pred) bool { @@ -59,8 +60,10 @@ func rewriteMapInsertion(polarity bool, key string, val AST.Form) { rewriteMap := selectFromPolarity(polarity, positiveRewrite, negativeRewrite) if _, ok := rewriteMap[key]; !ok { - rewriteMap[key] = AST.NewFormList() + rewriteMap[key] = Lib.NewList[AST.Form]() } - rewriteMap[key].Append(val) + ls := rewriteMap[key] + ls.Append(val) + rewriteMap[key] = ls } diff --git a/src/Mods/equality/bse/equality.go b/src/Mods/equality/bse/equality.go index ee12afae..b13b3020 100644 --- a/src/Mods/equality/bse/equality.go +++ b/src/Mods/equality/bse/equality.go @@ -94,7 +94,7 @@ func TryEquality(atomics_for_dmt Core.FormAndTermsList, st Search.State, new_ato * creates the problem * returns a bool for success and the corresponding substitution **/ -func EqualityReasoning(eqStruct eqStruct.EqualityStruct, tree_pos, tree_neg Unif.DataStructure, atomic *AST.FormList, originalNodeId int) (bool, []Unif.Substitutions) { +func EqualityReasoning(eqStruct eqStruct.EqualityStruct, tree_pos, tree_neg Unif.DataStructure, atomic Lib.List[AST.Form], originalNodeId int) (bool, []Unif.Substitutions) { debug(Lib.MkLazy(func() string { return "ER call" })) problem, equalities := buildEqualityProblemMultiList(atomic, tree_pos, tree_neg) if equalities { diff --git a/src/Mods/equality/bse/equality_problem.go b/src/Mods/equality/bse/equality_problem.go index b2e4ad91..3ce89bc1 100644 --- a/src/Mods/equality/bse/equality_problem.go +++ b/src/Mods/equality/bse/equality_problem.go @@ -136,11 +136,11 @@ func makeEqualityProblem(E Equalities, s AST.Term, t AST.Term, c ConstraintStruc /* Take a list of equalities and build the corresponding code tree */ func makeDataStructFromEqualities(eq Equalities) Unif.DataStructure { - formList := AST.NewFormList() + formList := Lib.NewList[AST.Form]() for _, e := range eq { formList.Append(Unif.MakerTermForm(e.GetT1()), Unif.MakerTermForm(e.GetT2())) } - return Unif.NewNode().MakeDataStruct(formList.Copy(), true) + return Unif.NewNode().MakeDataStruct(Lib.ListCpy(formList), true) } /* Take a list of equalities and build the corresponding assocative map */ diff --git a/src/Mods/equality/bse/equality_problem_list.go b/src/Mods/equality/bse/equality_problem_list.go index f29243bc..52d77e74 100644 --- a/src/Mods/equality/bse/equality_problem_list.go +++ b/src/Mods/equality/bse/equality_problem_list.go @@ -230,9 +230,9 @@ func buildEqualityProblemMultiListFromPredList(pred AST.Pred, tn Unif.DataStruct } /* Take a list of form and build an equality problem list, corresponding to thoses related to a predicate and its negation */ -func buildEqualityProblemMultiListFromFormList(fl *AST.FormList, tn Unif.DataStructure, eq Equalities) EqualityProblemMultiList { +func buildEqualityProblemMultiListFromFormList(fl Lib.List[AST.Form], tn Unif.DataStructure, eq Equalities) EqualityProblemMultiList { res := makeEmptyEqualityProblemMultiList() - for _, p := range fl.Slice() { + for _, p := range fl.GetSlice() { if pt, ok := p.(AST.Pred); ok { debug( Lib.MkLazy(func() string { return fmt.Sprintf("Pred found : %v", p.ToString()) }), @@ -249,7 +249,7 @@ func buildEqualityProblemMultiListFromFormList(fl *AST.FormList, tn Unif.DataStr * Take a form list * Retun a lis of independent problem list (from predicate and negation) + a boolean, true if there is equality in the formula list, false otherwise **/ -func buildEqualityProblemMultiList(fl *AST.FormList, tp, tn Unif.DataStructure) (EqualityProblemMultiList, bool) { +func buildEqualityProblemMultiList(fl Lib.List[AST.Form], tp, tn Unif.DataStructure) (EqualityProblemMultiList, bool) { res := makeEmptyEqualityProblemMultiList() eq := retrieveEqualities(tp.Copy()) if len(eq) == 0 { @@ -259,7 +259,7 @@ func buildEqualityProblemMultiList(fl *AST.FormList, tp, tn Unif.DataStructure) debug( Lib.MkLazy(func() string { return fmt.Sprintf("Res after FromNEQ : %v", res.ToString()) }), ) - res = append(res, buildEqualityProblemMultiListFromFormList(fl.Copy(), tn.Copy(), eq.copy())...) + res = append(res, buildEqualityProblemMultiListFromFormList(Lib.ListCpy(fl), tn.Copy(), eq.copy())...) debug( Lib.MkLazy(func() string { return fmt.Sprintf("Res after FromForm : %v", res.ToString()) }), ) diff --git a/src/Mods/gs3/dependency.go b/src/Mods/gs3/dependency.go index 7823a9ec..9bf39d78 100644 --- a/src/Mods/gs3/dependency.go +++ b/src/Mods/gs3/dependency.go @@ -34,6 +34,7 @@ package gs3 import ( "github.com/GoelandProver/Goeland/AST" "github.com/GoelandProver/Goeland/Glob" + "github.com/GoelandProver/Goeland/Lib" ) const ( @@ -127,13 +128,13 @@ func getVariableOccurrencesForm(v AST.Var, form AST.Form, currentOcc occurrences case AST.Not: currentOcc = getUnaryOcc(v, f.GetForm(), currentOcc, workingPath) case AST.And: - currentOcc = getNAryOcc(v, currentOcc, workingPath, f.FormList) + currentOcc = getNAryOcc(v, currentOcc, workingPath, f.GetChildFormulas()) case AST.Or: - currentOcc = getNAryOcc(v, currentOcc, workingPath, f.FormList) + currentOcc = getNAryOcc(v, currentOcc, workingPath, f.GetChildFormulas()) case AST.Imp: - currentOcc = getNAryOcc(v, currentOcc, workingPath, AST.NewFormList(f.GetF1(), f.GetF2())) + currentOcc = getNAryOcc(v, currentOcc, workingPath, Lib.MkListV(f.GetF1(), f.GetF2())) case AST.Equ: - currentOcc = getNAryOcc(v, currentOcc, workingPath, AST.NewFormList(f.GetF1(), f.GetF2())) + currentOcc = getNAryOcc(v, currentOcc, workingPath, Lib.MkListV(f.GetF1(), f.GetF2())) case AST.All: currentOcc = getUnaryOcc(v, f.GetForm(), currentOcc, workingPath) case AST.Ex: @@ -148,8 +149,8 @@ func getUnaryOcc(v AST.Var, form AST.Form, currentOcc occurrences, path occurren return getVariableOccurrencesForm(v, form, currentOcc, append(path, 0)) } -func getNAryOcc(v AST.Var, currentOcc occurrences, path occurrence, fl *AST.FormList) occurrences { - for i, nf := range fl.Slice() { +func getNAryOcc(v AST.Var, currentOcc occurrences, path occurrence, fl Lib.List[AST.Form]) occurrences { + for i, nf := range fl.GetSlice() { currentOcc = getVariableOccurrencesForm(v, nf, currentOcc, appcp(path, i)) } return currentOcc @@ -197,13 +198,13 @@ func getTermAux(form AST.Form, occ occurrence) AST.Term { case AST.Not: term = getUnaryTerm(f.GetForm(), occ) case AST.And: - term = getNAryTerm(f.FormList, occ) + term = getNAryTerm(f.GetChildFormulas(), occ) case AST.Or: - term = getNAryTerm(f.FormList, occ) + term = getNAryTerm(f.GetChildFormulas(), occ) case AST.Imp: - term = getNAryTerm(AST.NewFormList(f.GetF1(), f.GetF2()), occ) + term = getNAryTerm(Lib.MkListV(f.GetF1(), f.GetF2()), occ) case AST.Equ: - term = getNAryTerm(AST.NewFormList(f.GetF1(), f.GetF2()), occ) + term = getNAryTerm(Lib.MkListV(f.GetF1(), f.GetF2()), occ) case AST.All: term = getUnaryTerm(f.GetForm(), occ) case AST.Ex: @@ -222,12 +223,12 @@ func getUnaryTerm(form AST.Form, occ occurrence) AST.Term { return getTermAux(form, occ[1:]) } -func getNAryTerm(fl *AST.FormList, occ occurrence) AST.Term { +func getNAryTerm(fl Lib.List[AST.Form], occ occurrence) AST.Term { if occ[0] >= fl.Len() { return nil } - return getTermAux(fl.Get(occ[0]), occ[1:]) + return getTermAux(fl.At(occ[0]), occ[1:]) } func getTerm(term AST.Term, occ occurrence) AST.Term { diff --git a/src/Mods/gs3/proof.go b/src/Mods/gs3/proof.go index 67f86f9f..abc5f848 100644 --- a/src/Mods/gs3/proof.go +++ b/src/Mods/gs3/proof.go @@ -39,6 +39,7 @@ package gs3 import ( "strings" + "fmt" "github.com/GoelandProver/Goeland/AST" "github.com/GoelandProver/Goeland/Core" "github.com/GoelandProver/Goeland/Glob" @@ -47,34 +48,34 @@ import ( "github.com/GoelandProver/Goeland/Search" ) -type dependencyMap []Glob.Pair[AST.Term, *AST.FormList] +type dependencyMap []Glob.Pair[AST.Term, Lib.List[AST.Form]] func (d dependencyMap) Copy() dependencyMap { - oth := make([]Glob.Pair[AST.Term, *AST.FormList], 0) + oth := make([]Glob.Pair[AST.Term, Lib.List[AST.Form]], 0) for _, v := range d { if v.Fst != nil { - p := Glob.MakePair(v.Fst.Copy(), AST.NewFormList(v.Snd.Slice()...)) + p := Glob.MakePair(v.Fst.Copy(), Lib.MkListV(v.Snd.GetSlice()...)) oth = append(oth, p) } } return oth } -func (d dependencyMap) Get(t AST.Term) (*AST.FormList, bool) { +func (d dependencyMap) Get(t AST.Term) (Lib.List[AST.Form], bool) { for _, v := range d { if v.Fst != nil && v.Fst.Equals(t) { return v.Snd, true } } - return AST.NewFormList(), false + return Lib.NewList[AST.Form](), false } func (d *dependencyMap) Add(t AST.Term, f ...AST.Form) { found := false - formList := AST.NewFormList(f...) + formList := Lib.MkListV(f...) for i, v := range *d { if v.Fst != nil && t != nil && v.Fst.Equals(t) { - formList.Append(v.Snd.Slice()...) + formList.Append(v.Snd.GetSlice()...) (*d)[i] = Glob.MakePair(t, formList) found = true } @@ -85,7 +86,7 @@ func (d *dependencyMap) Add(t AST.Term, f ...AST.Form) { } } -func (d *dependencyMap) Set(t AST.Term, fl *AST.FormList) { +func (d *dependencyMap) Set(t AST.Term, fl Lib.List[AST.Form]) { for i, v := range *d { if v.Fst != nil && v.Fst.Equals(t) { (*d)[i] = Glob.MakePair(t, fl) @@ -95,8 +96,8 @@ func (d *dependencyMap) Set(t AST.Term, fl *AST.FormList) { // Utilitary struct to build the proof. Keeps everything that's needed on a proofstep. type GS3Proof struct { - dependency dependencyMap // Dependency graph for formulas - branchForms *AST.FormList // The formulas generated at the current point in the proof. + dependency dependencyMap // Dependency graph for formulas + branchForms Lib.List[AST.Form] // The formulas generated at the current point in the proof. rulesApplied []Glob.Pair[Rule, Search.ProofStruct] lastNode *GS3Sequent betaHisto []Glob.Pair[int, int] @@ -108,11 +109,11 @@ var MakeGS3Proof = func(proof []Search.ProofStruct) *GS3Sequent { rulesApplied: make([]Glob.Pair[Rule, Search.ProofStruct], 0), betaHisto: make([]Glob.Pair[int, int], 0), deltaHisto: make([]Glob.Pair[AST.Term, Glob.Pair[AST.Form, int]], 0), - branchForms: AST.NewFormList(), - dependency: make([]Glob.Pair[AST.Term, *AST.FormList], 0), + branchForms: Lib.NewList[AST.Form](), + dependency: make([]Glob.Pair[AST.Term, Lib.List[AST.Form]], 0), } if Glob.IsLoaded("dmt") { - gs3Proof.branchForms.Append(dmt.GetRegisteredAxioms().Slice()...) + gs3Proof.branchForms.Append(dmt.GetRegisteredAxioms().GetSlice()...) gs3Proof.branchForms.Append(proof[0].Formula.GetForm()) } sequent := gs3Proof.makeProof(proof) @@ -122,7 +123,7 @@ var MakeGS3Proof = func(proof []Search.ProofStruct) *GS3Sequent { func (gs GS3Proof) Copy() GS3Proof { return GS3Proof{ dependency: gs.dependency.Copy(), - branchForms: AST.NewFormList(appcp(gs.branchForms.Slice())...), + branchForms: Lib.MkListV(appcp(gs.branchForms.GetSlice())...), lastNode: nil, rulesApplied: appcp(gs.rulesApplied), betaHisto: appcp(gs.betaHisto), @@ -142,7 +143,7 @@ func (gs GS3Proof) makeProof(proof []Search.ProofStruct) *GS3Sequent { return seq } subRoot := MakeNewSequent() - var resultFormulas []*AST.FormList + var resultFormulas []Lib.List[AST.Form] if gs.branchForms.Len() == 0 { gs.branchForms.Append(proof[0].Formula.GetForm()) } @@ -156,7 +157,7 @@ func (gs GS3Proof) makeProof(proof []Search.ProofStruct) *GS3Sequent { for i, child := range proof[len(proof)-1].GetChildren() { childProof := GS3Proof{ dependency: gs.dependency.Copy(), - branchForms: AST.NewFormList(appcp(gs.branchForms.Slice(), resultFormulas[i].Slice()...)...), + branchForms: Lib.MkListV(appcp(gs.branchForms.GetSlice(), resultFormulas[i].GetSlice()...)...), lastNode: nil, rulesApplied: appcp(gs.rulesApplied), betaHisto: appcp(gs.betaHisto, Glob.MakePair(i, proof[len(proof)-1].GetNodeId())), @@ -172,7 +173,7 @@ func (gs GS3Proof) makeProof(proof []Search.ProofStruct) *GS3Sequent { } // Returns a sequent and the result formulas. -func (gs *GS3Proof) makeProofOneStep(proofStep Search.ProofStruct, parent *GS3Sequent) []*AST.FormList { +func (gs *GS3Proof) makeProofOneStep(proofStep Search.ProofStruct, parent *GS3Sequent) []Lib.List[AST.Form] { seq := MakeNewSequent() seq.setHypotheses(gs.branchForms) seq.nodeId = proofStep.Node_id @@ -222,7 +223,7 @@ func (gs *GS3Proof) makeProofOneStep(proofStep Search.ProofStruct, parent *GS3Se // If the length is superior, then it's a branching rule and it needs to be taken care of in makeProof. if IsAlphaRule(rule) || IsGammaRule(rule) || IsDeltaRule(rule) || rule == REWRITE { - gs.branchForms.Append(forms[0].Slice()...) + gs.branchForms.Append(forms[0].GetSlice()...) // If rule is rewrite: do not weaken the base form, as it is important to get when applying rules back. // It may however induce bad weakenings. // TODO: fix the bad weakenings in the sequent. @@ -235,7 +236,7 @@ func (gs *GS3Proof) makeProofOneStep(proofStep Search.ProofStruct, parent *GS3Se func (gs *GS3Proof) manageGammaStep(proofStep Search.ProofStruct, rule Rule, seq *GS3Sequent) *GS3Sequent { // Manage gamma: add all the gammas except the result formula to the thing - resultForm := proofStep.GetResultFormulas()[0].GetForms().Get(0) + resultForm := proofStep.GetResultFormulas()[0].GetForms().At(0) originForm := proofStep.GetFormula().GetForm() // TODO: what happens if the result form doesn't care of what it's instantiated with? // JRO: Should be OKAY as "nil" is returned if I understand everything properly. @@ -282,7 +283,7 @@ func getDepFromTerm(term AST.Term) Lib.List[AST.Term] { // TODO: factorise this function to merge some steps that are similar between the two cases. func (gs *GS3Proof) manageDeltaStep(proofStep Search.ProofStruct, rule Rule, parent *GS3Sequent) AST.Form { originForm := proofStep.GetFormula().GetForm() - resultForm := proofStep.GetResultFormulas()[0].GetForms().Get(0) + resultForm := proofStep.GetResultFormulas()[0].GetForms().At(0) termGenerated := manageDeltasSkolemisations(proofStep.GetFormula().GetForm(), resultForm) if Glob.IsPreInnerSko() && !gs.termHasBeenIntroducedByBranch(termGenerated, proofStep.Node_id) { @@ -351,15 +352,15 @@ func (gs *GS3Proof) manageDeltaStep(proofStep Search.ProofStruct, rule Rule, par return resultForm } -func (gs *GS3Proof) postTreatment(proofStep Search.ProofStruct, rule Rule) []*AST.FormList { +func (gs *GS3Proof) postTreatment(proofStep Search.ProofStruct, rule Rule) []Lib.List[AST.Form] { // Add the rule applied & the formula it has been applied on. gs.rulesApplied = append(gs.rulesApplied, Glob.MakePair(rule, proofStep)) - var forms []*AST.FormList + var forms []Lib.List[AST.Form] for i, fs := range proofStep.GetResultFormulas() { forms = append(forms, fs.GetForms()) if (rule == NOR || rule == NIMP || rule == AND || rule == EQU) && forms[i].Len() == 1 { - forms[i].Append(forms[i].Get(0).Copy()) + forms[i].Append(forms[i].At(0).Copy()) } } @@ -380,17 +381,17 @@ func makeProofStructFrom(f, nf AST.Form, rule Rule) Search.ProofStruct { return proofStruct } -func (gs GS3Proof) getFormulasDependantFromTerm(term AST.Term) (*AST.FormList, bool) { +func (gs GS3Proof) getFormulasDependantFromTerm(term AST.Term) (Lib.List[AST.Form], bool) { fs, ok := gs.dependency.Get(term) return fs, ok } -func (gs GS3Proof) getRulesAppliedInOrder(term AST.Term, dependantForms *AST.FormList, deltaForm AST.Form) ([]Glob.Pair[Rule, Search.ProofStruct], *AST.FormList) { +func (gs GS3Proof) getRulesAppliedInOrder(term AST.Term, dependantForms Lib.List[AST.Form], deltaForm AST.Form) ([]Glob.Pair[Rule, Search.ProofStruct], Lib.List[AST.Form]) { offsprings := gs.getOffspringsOf(term) rules := []Glob.Pair[Rule, Search.ProofStruct]{} for _, rule := range gs.rulesApplied { f := rule.Snd.GetFormula().GetForm() - if !f.Equals(deltaForm) && (offsprings.Contains(f) || dependantForms.Contains(f)) { + if !f.Equals(deltaForm) && (Lib.ListMem(f, offsprings) || Lib.ListMem(f, dependantForms)) { rules = append(rules, rule) } } @@ -398,9 +399,9 @@ func (gs GS3Proof) getRulesAppliedInOrder(term AST.Term, dependantForms *AST.For return rules, offsprings } -func (gs GS3Proof) getOffspringsOf(term AST.Term) *AST.FormList { - offsprings := AST.NewFormList() - for _, form := range gs.branchForms.Slice() { +func (gs GS3Proof) getOffspringsOf(term AST.Term) Lib.List[AST.Form] { + offsprings := Lib.NewList[AST.Form]() + for _, form := range gs.branchForms.GetSlice() { if form.GetSubTerms().Contains(term, AST.TermEquals) { offsprings.Append(form) } @@ -408,8 +409,8 @@ func (gs GS3Proof) getOffspringsOf(term AST.Term) *AST.FormList { return offsprings } -func (gs *GS3Proof) weakenForms(forms *AST.FormList, parent *GS3Sequent) *GS3Sequent { - for i, form := range forms.Slice() { +func (gs *GS3Proof) weakenForms(forms Lib.List[AST.Form], parent *GS3Sequent) *GS3Sequent { + for i, form := range forms.GetSlice() { newSeq := gs.weakenForm(form) if newSeq != nil { if i == 0 && parent.IsEmpty() { @@ -456,19 +457,24 @@ func (gs *GS3Proof) weakenTerm(term AST.Term) *GS3Sequent { } func (gs *GS3Proof) removeHypothesis(form AST.Form) { - index, _ := gs.branchForms.GetIndexOf(form) - gs.branchForms.Remove(index) + index := Lib.ListIndexOf(form, gs.branchForms) + switch i := index.(type) { + case Lib.Some[int]: + gs.branchForms = gs.branchForms.RemoveAt(i.Val) + case Lib.None[int]: + Glob.PrintWarn("gs3", fmt.Sprintf("Hypothesis %s not found", form.ToString())) + } } func (gs *GS3Proof) removeDependency(form AST.Form) { for _, v := range gs.dependency { if v.Fst != nil { ls, _ := gs.dependency.Get(v.Fst) - removed := ls.Copy() + removed := Lib.ListCpy(ls) nb_rm := 0 - for i, f := range v.Snd.Slice() { + for i, f := range v.Snd.GetSlice() { if f.Equals(form) { - removed.Remove(i - nb_rm) + removed.RemoveAt(i - nb_rm) nb_rm++ } } @@ -492,7 +498,7 @@ func (gs *GS3Proof) applyDeltaRule(form, result AST.Form, rule Rule, term AST.Te seq.setAppliedRule(rule) seq.setAppliedOn(form) seq.setTermGenerated(term) - seq.setFormsGenerated([]*AST.FormList{AST.NewFormList(result)}) + seq.setFormsGenerated([]Lib.List[AST.Form]{Lib.MkListV(result)}) gs.branchForms.Append(result) gs.deltaHisto = append(gs.deltaHisto, Glob.MakePair(term, Glob.MakePair(result, nodeId))) @@ -503,7 +509,7 @@ func (gs *GS3Proof) applyDeltaRule(form, result AST.Form, rule Rule, term AST.Te return seq } -func (gs GS3Proof) applyRulesBack(rulesApplied, rulesToApply []Glob.Pair[Rule, Search.ProofStruct], weakenedForms *AST.FormList) (*GS3Sequent, []int) { +func (gs GS3Proof) applyRulesBack(rulesApplied, rulesToApply []Glob.Pair[Rule, Search.ProofStruct], weakenedForms Lib.List[AST.Form]) (*GS3Sequent, []int) { // Transform everything back to a proof struct & call makeProof on it. // We need to have the right proofstructs here: the proofstructs of the branches that is not this one // on the beta formulas. @@ -514,7 +520,7 @@ func (gs GS3Proof) applyRulesBack(rulesApplied, rulesToApply []Glob.Pair[Rule, S return gs.makeProof(proof), childrenIndex } -func (gs *GS3Proof) rebuildProof(rulesApplied, rules []Glob.Pair[Rule, Search.ProofStruct], weakenedForms *AST.FormList) ([]Search.ProofStruct, []int) { +func (gs *GS3Proof) rebuildProof(rulesApplied, rules []Glob.Pair[Rule, Search.ProofStruct], weakenedForms Lib.List[AST.Form]) ([]Search.ProofStruct, []int) { rebuiltProof := make([]Search.ProofStruct, 0) childrenIndex := make([]int, 0) for i, rule := range rules { @@ -557,8 +563,8 @@ func (gs GS3Proof) getCurrentBranchChildId(id int) int { return -1 } -func (gs GS3Proof) getFormsToWeaken(rulesApplied, rulesAlreadyWeakened []Glob.Pair[Rule, Search.ProofStruct]) *AST.FormList { - formsToWeaken := AST.NewFormList() +func (gs GS3Proof) getFormsToWeaken(rulesApplied, rulesAlreadyWeakened []Glob.Pair[Rule, Search.ProofStruct]) Lib.List[AST.Form] { + formsToWeaken := Lib.NewList[AST.Form]() rule := getFirstRuleAppliedAfter(gs.rulesApplied, rulesAlreadyWeakened[0]) canBeAppending := false for _, r := range gs.rulesApplied { @@ -567,7 +573,8 @@ func (gs GS3Proof) getFormsToWeaken(rulesApplied, rulesAlreadyWeakened []Glob.Pa } if canBeAppending { if !Glob.IsPreInnerSko() || !(rule.Fst == EX || rule.Fst == NALL) { - formsToWeaken.Append(gs.getIntersectionBetweenResultAndBranchForms(rule.Snd.GetResultFormulas()).Slice()...) + formsToWeaken.Append( + gs.getIntersectionBetweenResultAndBranchForms(rule.Snd.GetResultFormulas()).GetSlice()...) } } } @@ -583,11 +590,11 @@ func getFirstRuleAppliedAfter(rulesApplied []Glob.Pair[Rule, Search.ProofStruct] return Glob.Pair[Rule, Search.ProofStruct]{} } -func (gs GS3Proof) getIntersectionBetweenResultAndBranchForms(forms []Search.IntFormAndTermsList) *AST.FormList { - fs := AST.NewFormList() +func (gs GS3Proof) getIntersectionBetweenResultAndBranchForms(forms []Search.IntFormAndTermsList) Lib.List[AST.Form] { + fs := Lib.NewList[AST.Form]() for _, fl := range forms { - for _, f := range fl.GetForms().Slice() { - if gs.branchForms.Contains(f) { + for _, f := range fl.GetForms().GetSlice() { + if Lib.ListMem(f, gs.branchForms) { fs.Append(f) } } @@ -599,9 +606,9 @@ func equalRulePair(a, b Glob.Pair[Rule, Search.ProofStruct]) bool { return a.Fst == b.Fst && a.Snd.Formula.GetForm().Equals(b.Snd.Formula.GetForm()) } -func makeWeakeningProofStructs(forms *AST.FormList) []Search.ProofStruct { +func makeWeakeningProofStructs(forms Lib.List[AST.Form]) []Search.ProofStruct { resultingProof := make([]Search.ProofStruct, 0) - for _, f := range forms.Slice() { + for _, f := range forms.GetSlice() { proofStruct := Search.MakeEmptyProofStruct() proofStruct.SetFormulaProof(Core.MakeFormAndTerm( f, @@ -642,7 +649,7 @@ func (gs GS3Proof) findInBetaHist(id int) int { return -1 } -func getAllFormulasDependantOn(term AST.Term, form AST.Form) *AST.FormList { +func getAllFormulasDependantOn(term AST.Term, form AST.Form) Lib.List[AST.Form] { switch f := form.(type) { case AST.All: return getSubformulas(term, f.GetVarList()[0], f.GetForm()) @@ -651,13 +658,13 @@ func getAllFormulasDependantOn(term AST.Term, form AST.Form) *AST.FormList { return getSubformulas(term, ex.GetVarList()[0], AST.MakerNot(f.GetForm())) } } - return AST.NewFormList() + return Lib.NewList[AST.Form]() } -func getSubformulas(term AST.Term, v AST.Var, form AST.Form) *AST.FormList { +func getSubformulas(term AST.Term, v AST.Var, form AST.Form) Lib.List[AST.Form] { subforms := form.GetSubFormulasRecur() - dependantSubforms := AST.NewFormList() - for _, f := range subforms.Slice() { + dependantSubforms := Lib.NewList[AST.Form]() + for _, f := range subforms.GetSlice() { f, res := f.ReplaceTermByTerm(v, term) if res { dependantSubforms.Append(f) @@ -666,10 +673,10 @@ func getSubformulas(term AST.Term, v AST.Var, form AST.Form) *AST.FormList { return dependantSubforms } -func (gs GS3Proof) findInDeltaHisto(term AST.Term, forms *AST.FormList) (*AST.FormList, bool) { +func (gs GS3Proof) findInDeltaHisto(term AST.Term, forms Lib.List[AST.Form]) (Lib.List[AST.Form], bool) { for _, p := range gs.deltaHisto { if p.Fst != nil && p.Fst.Equals(term) { - result := forms.Copy() + result := Lib.ListCpy(forms) result.Append(p.Snd.Fst) return result, true } @@ -685,10 +692,10 @@ func (gs *GS3Proof) removeFromDeltaHisto(term AST.Term) { } } -func (gs *GS3Proof) weakenAllFormsRelatedToTheTerm(term AST.Term) (*AST.FormList, []Glob.Pair[Rule, Search.ProofStruct]) { +func (gs *GS3Proof) weakenAllFormsRelatedToTheTerm(term AST.Term) (Lib.List[AST.Form], []Glob.Pair[Rule, Search.ProofStruct]) { rules := []Glob.Pair[Rule, Search.ProofStruct]{} - forms := AST.NewFormList() - for _, form := range gs.branchForms.Slice() { + forms := Lib.NewList[AST.Form]() + for _, form := range gs.branchForms.GetSlice() { if form.GetSubTerms().Contains(term, AST.TermEquals) { // Get the rule to apply it back for _, rule := range gs.rulesApplied { diff --git a/src/Mods/gs3/sequent.go b/src/Mods/gs3/sequent.go index 647f0047..88fb3a32 100644 --- a/src/Mods/gs3/sequent.go +++ b/src/Mods/gs3/sequent.go @@ -36,15 +36,16 @@ import ( "github.com/GoelandProver/Goeland/AST" "github.com/GoelandProver/Goeland/Glob" + "github.com/GoelandProver/Goeland/Lib" ) type GS3Sequent struct { - hypotheses *AST.FormList + hypotheses Lib.List[AST.Form] rule Rule appliedOn int rewriteWith int termGenerated AST.Term - formsGenerated []*AST.FormList + formsGenerated []Lib.List[AST.Form] children []*GS3Sequent proof GS3Proof nodeId int @@ -76,7 +77,7 @@ const ( func MakeNewSequent() *GS3Sequent { seq := new(GS3Sequent) - seq.hypotheses = AST.NewFormList() + seq.hypotheses = Lib.NewList[AST.Form]() seq.children = make([]*GS3Sequent, 0) return seq } @@ -102,7 +103,7 @@ func IsAlphaRule(rule Rule) bool { // ---------------------------------------------------------------------------- func (seq *GS3Sequent) GetTargetForm() AST.Form { - return seq.hypotheses.Get(seq.appliedOn) + return seq.hypotheses.At(seq.appliedOn) } func (seq *GS3Sequent) Child(i int) *GS3Sequent { @@ -117,12 +118,12 @@ func (seq *GS3Sequent) Rule() Rule { return seq.rule } -func (seq *GS3Sequent) GetResultFormulasOfChild(i int) *AST.FormList { +func (seq *GS3Sequent) GetResultFormulasOfChild(i int) Lib.List[AST.Form] { return seq.formsGenerated[i] } -func (seq *GS3Sequent) GetResultFormulasOfChildren() []*AST.FormList { - result := []*AST.FormList{} +func (seq *GS3Sequent) GetResultFormulasOfChildren() []Lib.List[AST.Form] { + result := []Lib.List[AST.Form]{} for i := range seq.children { result = append(result, seq.formsGenerated[i]) @@ -136,7 +137,7 @@ func (seq *GS3Sequent) TermGenerated() AST.Term { } func (seq *GS3Sequent) IsEmpty() bool { - return seq.hypotheses.IsEmpty() + return seq.hypotheses.Empty() } func (seq *GS3Sequent) ToString() string { @@ -144,7 +145,7 @@ func (seq *GS3Sequent) ToString() string { } func (seq *GS3Sequent) GetRewriteWith() AST.Form { - return seq.hypotheses.Get(seq.rewriteWith) + return seq.hypotheses.At(seq.rewriteWith) } func (seq *GS3Sequent) GetId() int { @@ -155,7 +156,7 @@ func (seq *GS3Sequent) SetId(i int) { seq.nodeId = i } -func (seq *GS3Sequent) SetFormGenerated(fg []*AST.FormList) { +func (seq *GS3Sequent) SetFormGenerated(fg []Lib.List[AST.Form]) { seq.formsGenerated = fg } @@ -164,7 +165,7 @@ func (seq *GS3Sequent) SetChildren(c []*GS3Sequent) { } func (seq *GS3Sequent) SetTargetForm(f AST.Form) { - seq.hypotheses.Set(seq.appliedOn, f) + seq.hypotheses.Upd(seq.appliedOn, f) } func (seq *GS3Sequent) SetTermGenerated(t AST.Term) { @@ -175,8 +176,8 @@ func (seq *GS3Sequent) SetTermGenerated(t AST.Term) { // Private methods & functions // ---------------------------------------------------------------------------- -func (seq *GS3Sequent) setHypotheses(forms *AST.FormList) { - seq.hypotheses = forms.Copy() +func (seq *GS3Sequent) setHypotheses(forms Lib.List[AST.Form]) { + seq.hypotheses = Lib.ListCpy(forms) // If equality reasoning has been used to terminate the proof, then an empty predicate is expected // (see search_destructive, manageClosureRule on eq reasoning). // As such, add an hypothesis with the empty = @@ -189,7 +190,7 @@ func (seq *GS3Sequent) setAppliedRule(rule Rule) { func (seq *GS3Sequent) setAppliedOn(hypothesis AST.Form) { index := -1 - for i, h := range seq.hypotheses.Slice() { + for i, h := range seq.hypotheses.GetSlice() { if hypothesis.Equals(h) { index = i break @@ -214,7 +215,7 @@ func (seq *GS3Sequent) addChild(oth ...*GS3Sequent) { func (seq *GS3Sequent) toStringAux(i int) string { identation := strings.Repeat(" ", i) - status := seq.ruleToString(seq.rule) + " on " + seq.hypotheses.Get(seq.appliedOn).ToString() + status := seq.ruleToString(seq.rule) + " on " + seq.hypotheses.At(seq.appliedOn).ToString() if seq.IsEmpty() { status = "EMPTY" } @@ -248,7 +249,7 @@ func (seq *GS3Sequent) ruleToString(rule Rule) string { return mapping[rule] } -func (seq *GS3Sequent) setFormsGenerated(forms []*AST.FormList) { +func (seq *GS3Sequent) setFormsGenerated(forms []Lib.List[AST.Form]) { seq.formsGenerated = forms } @@ -297,7 +298,7 @@ func ruleToTableauxString(rule Rule) string { } func (seq *GS3Sequent) setRewrittenWith(rewriteId int) { - for i, h := range seq.hypotheses.Slice() { + for i, h := range seq.hypotheses.GetSlice() { endForm := h for Glob.Is[AST.All](endForm) { endForm = endForm.(AST.All).GetForm() diff --git a/src/Mods/lambdapi/context.go b/src/Mods/lambdapi/context.go index e9496c46..b1359413 100644 --- a/src/Mods/lambdapi/context.go +++ b/src/Mods/lambdapi/context.go @@ -181,11 +181,11 @@ func getContextFromFormula(root AST.Form) []string { case AST.AllType: result = getContextFromFormula(nf.GetForm()) case AST.And: - for _, f := range nf.FormList.Slice() { + for _, f := range nf.GetChildFormulas().GetSlice() { result = append(result, clean(result, getContextFromFormula(f))...) } case AST.Or: - for _, f := range nf.FormList.Slice() { + for _, f := range nf.GetChildFormulas().GetSlice() { result = append(result, clean(result, getContextFromFormula(f))...) } case AST.Imp: @@ -229,11 +229,11 @@ func getIdsFromFormula(root AST.Form) []Glob.Pair[string, string] { case AST.AllType: result = getIdsFromFormula(nf.GetForm()) case AST.And: - for _, f := range nf.FormList.Slice() { + for _, f := range nf.GetChildFormulas().GetSlice() { result = append(result, getIdsFromFormula(f)...) } case AST.Or: - for _, f := range nf.FormList.Slice() { + for _, f := range nf.GetChildFormulas().GetSlice() { result = append(result, getIdsFromFormula(f)...) } case AST.Imp: diff --git a/src/Mods/lambdapi/proof.go b/src/Mods/lambdapi/proof.go index 852a7697..9c78f47b 100644 --- a/src/Mods/lambdapi/proof.go +++ b/src/Mods/lambdapi/proof.go @@ -37,6 +37,7 @@ import ( "github.com/GoelandProver/Goeland/AST" "github.com/GoelandProver/Goeland/Glob" + "github.com/GoelandProver/Goeland/Lib" "github.com/GoelandProver/Goeland/Mods/gs3" ) @@ -129,10 +130,10 @@ func getPosAndNeg(target AST.Form) (pos, neg AST.Form) { return target, AST.MakerNot(target) } -func allRules(rule string, target AST.Form, composingForms *AST.FormList, nexts []*gs3.GS3Sequent, children []*AST.FormList) string { +func allRules(rule string, target AST.Form, composingForms Lib.List[AST.Form], nexts []*gs3.GS3Sequent, children []Lib.List[AST.Form]) string { result := rule + "\n" - for _, composingForm := range composingForms.Slice() { + for _, composingForm := range composingForms.GetSlice() { result += "(" + toCorrectString(composingForm) + ")\n" } @@ -143,7 +144,7 @@ func allRules(rule string, target AST.Form, composingForms *AST.FormList, nexts return result } -func allRulesQuantUniv(rule string, target AST.Form, composingForms *AST.FormList, nexts []*gs3.GS3Sequent, children []*AST.FormList, vars []AST.Var, termGen AST.Term) string { +func allRulesQuantUniv(rule string, target AST.Form, composingForms Lib.List[AST.Form], nexts []*gs3.GS3Sequent, children []Lib.List[AST.Form], vars []AST.Var, termGen AST.Term) string { quant := "" typeStr := vars[0].GetTypeApp().ToString() @@ -159,7 +160,7 @@ func allRulesQuantUniv(rule string, target AST.Form, composingForms *AST.FormLis result := rule + "\n" result += "(" + typeStr + ")\n" - result += "(%s, " + toCorrectString(composingForms.Get(0)) + ")\n" + result += "(%s, " + toCorrectString(composingForms.At(0)) + ")\n" varStrs := []string{} for _, singleVar := range vars { @@ -176,10 +177,10 @@ func allRulesQuantUniv(rule string, target AST.Form, composingForms *AST.FormLis return result } -func getRecursionUnivStr(nexts []*gs3.GS3Sequent, children []*AST.FormList) (result string) { +func getRecursionUnivStr(nexts []*gs3.GS3Sequent, children []Lib.List[AST.Form]) (result string) { for i, next := range nexts { result += "(\n" - for _, childForm := range children[i].Slice() { + for _, childForm := range children[i].GetSlice() { result += toLambdaString(childForm, toCorrectString(childForm)) + ",\n" } proofStr := makeProofStep(next) @@ -189,7 +190,7 @@ func getRecursionUnivStr(nexts []*gs3.GS3Sequent, children []*AST.FormList) (res return result } -func allRulesQuantExist(rule string, target AST.Form, composingForms *AST.FormList, nexts []*gs3.GS3Sequent, children []*AST.FormList, vars []AST.Var, termGen AST.Term) string { +func allRulesQuantExist(rule string, target AST.Form, composingForms Lib.List[AST.Form], nexts []*gs3.GS3Sequent, children []Lib.List[AST.Form], vars []AST.Var, termGen AST.Term) string { quant := "" typeStr := vars[0].GetTypeApp().ToString() switch typed := target.(type) { @@ -204,7 +205,7 @@ func allRulesQuantExist(rule string, target AST.Form, composingForms *AST.FormLi result := rule + "\n" result += "(" + typeStr + ")\n" - result += "(%s, " + toCorrectString(composingForms.Get(0)) + ")\n" + result += "(%s, " + toCorrectString(composingForms.At(0)) + ")\n" varStrs := []string{} for _, singleVar := range vars { @@ -219,7 +220,7 @@ func allRulesQuantExist(rule string, target AST.Form, composingForms *AST.FormLi return result } -func getRecursionExistStr(nexts []*gs3.GS3Sequent, children []*AST.FormList, termGen AST.Term) (result string) { +func getRecursionExistStr(nexts []*gs3.GS3Sequent, children []Lib.List[AST.Form], termGen AST.Term) (result string) { for i, next := range nexts { result += "(\n" typesStr := "" @@ -227,7 +228,7 @@ func getRecursionExistStr(nexts []*gs3.GS3Sequent, children []*AST.FormList, ter typesStr = mapDefault(typed.GetTypeHint().ToString()) } result += toLambdaIntroString(termGen, typesStr) + ",\n" - for _, childForm := range children[i].Slice() { + for _, childForm := range children[i].GetSlice() { result += toLambdaString(childForm, toCorrectString(childForm)) + ",\n" } proofStr := makeProofStep(next) @@ -238,7 +239,7 @@ func getRecursionExistStr(nexts []*gs3.GS3Sequent, children []*AST.FormList, ter } func alphaNotNot(proof *gs3.GS3Sequent) string { - composingForms := proof.GetTargetForm().GetChildFormulas().Get(0).GetChildFormulas() + composingForms := proof.GetTargetForm().GetChildFormulas().At(0).GetChildFormulas() return allRules("GS3nnot", proof.GetTargetForm(), composingForms, proof.Children(), proof.GetResultFormulasOfChildren()) } @@ -247,12 +248,12 @@ func alphaAnd(proof *gs3.GS3Sequent) string { } func alphaNotOr(proof *gs3.GS3Sequent) string { - composingForms := proof.GetTargetForm().GetChildFormulas().Get(0).GetChildFormulas() + composingForms := proof.GetTargetForm().GetChildFormulas().At(0).GetChildFormulas() return allRules("GS3nor", proof.GetTargetForm(), composingForms, proof.Children(), proof.GetResultFormulasOfChildren()) } func alphaNotImp(proof *gs3.GS3Sequent) string { - composingForms := proof.GetTargetForm().GetChildFormulas().Get(0).GetChildFormulas() + composingForms := proof.GetTargetForm().GetChildFormulas().At(0).GetChildFormulas() return allRules("GS3nimp", proof.GetTargetForm(), composingForms, proof.Children(), proof.GetResultFormulasOfChildren()) } @@ -261,7 +262,7 @@ func betaOr(proof *gs3.GS3Sequent) string { } func betaNotAnd(proof *gs3.GS3Sequent) string { - composingForms := proof.GetTargetForm().GetChildFormulas().Get(0).GetChildFormulas() + composingForms := proof.GetTargetForm().GetChildFormulas().At(0).GetChildFormulas() return allRules("GS3nand", proof.GetTargetForm(), composingForms, proof.Children(), proof.GetResultFormulasOfChildren()) } @@ -274,7 +275,7 @@ func betaEqu(proof *gs3.GS3Sequent) string { } func betaNotEqu(proof *gs3.GS3Sequent) string { - composingForms := proof.GetTargetForm().GetChildFormulas().Get(0).GetChildFormulas() + composingForms := proof.GetTargetForm().GetChildFormulas().At(0).GetChildFormulas() return allRules("GS3nequ", proof.GetTargetForm(), composingForms, proof.Children(), proof.GetResultFormulasOfChildren()) } @@ -294,7 +295,7 @@ func deltaNotAll(proof *gs3.GS3Sequent) string { formulaAll = form } } - composingForms := proof.GetTargetForm().GetChildFormulas().Get(0).GetChildFormulas() + composingForms := proof.GetTargetForm().GetChildFormulas().At(0).GetChildFormulas() return allRulesQuantExist("GS3nall", proof.GetTargetForm(), composingForms, proof.Children(), proof.GetResultFormulasOfChildren(), formulaAll.GetVarList(), proof.TermGenerated()) } @@ -315,40 +316,40 @@ func gammaNotEx(proof *gs3.GS3Sequent) string { formulaEx = form } } - composingForms := proof.GetTargetForm().GetChildFormulas().Get(0).GetChildFormulas() + composingForms := proof.GetTargetForm().GetChildFormulas().At(0).GetChildFormulas() return allRulesQuantUniv("GS3nex", proof.GetTargetForm(), composingForms, proof.Children(), proof.GetResultFormulasOfChildren(), formulaEx.GetVarList(), proof.TermGenerated()) } // Processes the formula that was proven by Goéland. -func processMainFormula(form AST.Form) (*AST.FormList, AST.Form) { - formList := AST.NewFormList() +func processMainFormula(form AST.Form) (Lib.List[AST.Form], AST.Form) { + formList := Lib.NewList[AST.Form]() switch nf := form.(type) { case AST.Not: form = nf.GetForm() case AST.And: - last := nf.FormList.Len() - 1 - formList = AST.NewFormList(nf.FormList.GetElements(0, last)...) - form = nf.FormList.Get(last).(AST.Not).GetForm() + last := nf.GetChildFormulas().Len() - 1 + formList = Lib.MkListV(nf.GetChildFormulas().Get(0, last)...) + form = nf.GetChildFormulas().At(last).(AST.Not).GetForm() } return formList, form } // Prints the theorem's name & properly formats the first formula. -func makeTheorem(axioms *AST.FormList, conjecture AST.Form) string { +func makeTheorem(axioms Lib.List[AST.Form], conjecture AST.Form) string { problemName := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(Glob.GetProblemName(), ".", "_"), "=", "_"), "+", "_") - axioms = axioms.Copy() + axioms = Lib.ListCpy(axioms) axioms.Append(AST.MakerNot(conjecture)) formattedProblem := makeImpChain(axioms) return "symbol goeland_" + problemName + " : \nϵ " + toCorrectString(formattedProblem) + " → ϵ ⊥ ≔ \n" } // If [F1, F2, F3] is a formlist, then this function returns F1 -> (F2 -> F3). -func makeImpChain(forms *AST.FormList) AST.Form { +func makeImpChain(forms Lib.List[AST.Form]) AST.Form { last := forms.Len() - 1 - form := forms.Get(last) + form := forms.At(last) for i := last - 1; i >= 0; i-- { - form = AST.MakerImp(forms.Get(i), form) + form = AST.MakerImp(forms.At(i), form) } return form } diff --git a/src/Mods/rocq/context.go b/src/Mods/rocq/context.go index dca1bf5d..bdfa1d79 100644 --- a/src/Mods/rocq/context.go +++ b/src/Mods/rocq/context.go @@ -102,11 +102,11 @@ func getContextFromFormula(root AST.Form) []string { case AST.AllType: result = getContextFromFormula(nf.GetForm()) case AST.And: - for _, f := range nf.FormList.Slice() { + for _, f := range nf.GetChildFormulas().GetSlice() { result = append(result, clean(result, getContextFromFormula(f))...) } case AST.Or: - for _, f := range nf.FormList.Slice() { + for _, f := range nf.GetChildFormulas().GetSlice() { result = append(result, clean(result, getContextFromFormula(f))...) } case AST.Imp: diff --git a/src/Mods/rocq/proof.go b/src/Mods/rocq/proof.go index e9beda52..b4fe0286 100644 --- a/src/Mods/rocq/proof.go +++ b/src/Mods/rocq/proof.go @@ -42,6 +42,7 @@ import ( "github.com/GoelandProver/Goeland/AST" "github.com/GoelandProver/Goeland/Glob" + "github.com/GoelandProver/Goeland/Lib" "github.com/GoelandProver/Goeland/Mods/dmt" "github.com/GoelandProver/Goeland/Mods/gs3" ) @@ -53,15 +54,15 @@ func makeRocqProofFromGS3(proof *gs3.GS3Sequent) string { axioms, conjecture := processMainFormula(proof.GetTargetForm()) totalAxioms := axioms.Len() if Glob.IsLoaded("dmt") { - axioms.Append(dmt.GetRegisteredAxioms().Slice()...) + axioms.Append(dmt.GetRegisteredAxioms().GetSlice()...) } var resultingString string resultingString = makeTheorem(axioms, conjecture) resultingString += "Proof.\n" - hypotheses := AST.NewFormList() + hypotheses := Lib.NewList[AST.Form]() if axioms.Len() > 0 { indices := make([]int, axioms.Len()) - for i, form := range axioms.Slice() { + for i, form := range axioms.GetSlice() { indices[i], hypotheses = introduce(form, hypotheses) } resultingString += "intros " + strings.Join(Glob.MapTo(indices, func(_ int, index int) string { return introName(index) }), " ") + ". " @@ -76,32 +77,44 @@ func makeRocqProofFromGS3(proof *gs3.GS3Sequent) string { return resultingString + "\nQed.\n" } -func followProofSteps(proof *gs3.GS3Sequent, hypotheses *AST.FormList, constantsCreated []AST.Term) string { +func followProofSteps(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], constantsCreated []AST.Term) string { var resultingString string - var childrenHypotheses []*AST.FormList + var childrenHypotheses []Lib.List[AST.Form] if !proof.IsEmpty() { resultingString, childrenHypotheses, constantsCreated = makeProofStep(proof, hypotheses, constantsCreated) } for i, child := range proof.Children() { if proof.IsEmpty() { - resultingString += "\n" + followProofSteps(child, hypotheses.Copy(), cp(constantsCreated)) + resultingString += "\n" + followProofSteps(child, Lib.ListCpy(hypotheses), cp(constantsCreated)) } else { - resultingString += "\n" + followProofSteps(child, childrenHypotheses[i].Copy(), cp(constantsCreated)) + resultingString += "\n" + followProofSteps(child, Lib.ListCpy(childrenHypotheses[i]), cp(constantsCreated)) } } return resultingString } -func makeProofStep(proof *gs3.GS3Sequent, hypotheses *AST.FormList, constantsCreated []AST.Term) (string, []*AST.FormList, []AST.Term) { +func makeProofStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], constantsCreated []AST.Term) (string, []Lib.List[AST.Form], []AST.Term) { stepResult, childrenHypotheses, constantsCreated := makeStep(proof, hypotheses, constantsCreated) return stepResult, childrenHypotheses, constantsCreated } -func makeStep(proof *gs3.GS3Sequent, hypotheses *AST.FormList, constantsCreated []AST.Term) (string, []*AST.FormList, []AST.Term) { +func makeStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], constantsCreated []AST.Term) (string, []Lib.List[AST.Form], []AST.Term) { var resultingString string - childrenHypotheses := []*AST.FormList{hypotheses} + childrenHypotheses := []Lib.List[AST.Form]{hypotheses} + + target := Lib.ListIndexOf(proof.GetTargetForm(), hypotheses) + var actualTarget int + switch t := target.(type) { + case Lib.Some[int]: + actualTarget = t.Val + case Lib.None[int]: + Glob.Anomaly("coq", fmt.Sprintf( + "Index of %s not found in %s", + proof.GetTargetForm().ToString(), + Lib.ListToString(hypotheses, ", ", "[]"), + )) + } - target, _ := hypotheses.GetIndexOf(proof.GetTargetForm()) switch proof.Rule() { // Closure. case gs3.AX: @@ -113,37 +126,37 @@ func makeStep(proof *gs3.GS3Sequent, hypotheses *AST.FormList, constantsCreated // Alpha rules case gs3.NNOT: - resultingString, childrenHypotheses = alphaStep(proof, hypotheses, target, "%s") + resultingString, childrenHypotheses = alphaStep(proof, hypotheses, actualTarget, "%s") case gs3.AND: - resultingString, childrenHypotheses = alphaStep(proof, hypotheses, target, "(goeland_and_s _ _ %s)") + resultingString, childrenHypotheses = alphaStep(proof, hypotheses, actualTarget, "(goeland_and_s _ _ %s)") case gs3.NOR: - resultingString, childrenHypotheses = alphaStep(proof, hypotheses, target, "(goeland_notor_s _ _ %s)") + resultingString, childrenHypotheses = alphaStep(proof, hypotheses, actualTarget, "(goeland_notor_s _ _ %s)") case gs3.NIMP: - resultingString, childrenHypotheses = alphaStep(proof, hypotheses, target, "(goeland_notimply_s _ _ %s)") + resultingString, childrenHypotheses = alphaStep(proof, hypotheses, actualTarget, "(goeland_notimply_s _ _ %s)") // Beta rules case gs3.NAND: - resultingString, childrenHypotheses = betaStep(proof, hypotheses, target, "(goeland_notand_s _ _ %s)") + resultingString, childrenHypotheses = betaStep(proof, hypotheses, actualTarget, "(goeland_notand_s _ _ %s)") case gs3.NEQU: - resultingString, childrenHypotheses = betaStep(proof, hypotheses, target, "(goeland_notequiv_s _ _ %s)") + resultingString, childrenHypotheses = betaStep(proof, hypotheses, actualTarget, "(goeland_notequiv_s _ _ %s)") case gs3.OR: - resultingString, childrenHypotheses = betaStep(proof, hypotheses, target, "(goeland_or_s _ _ %s)") + resultingString, childrenHypotheses = betaStep(proof, hypotheses, actualTarget, "(goeland_or_s _ _ %s)") case gs3.IMP: - resultingString, childrenHypotheses = betaStep(proof, hypotheses, target, "(goeland_imply_s _ _ %s)") + resultingString, childrenHypotheses = betaStep(proof, hypotheses, actualTarget, "(goeland_imply_s _ _ %s)") case gs3.EQU: - resultingString, childrenHypotheses = betaStep(proof, hypotheses, target, "(goeland_equiv_s _ _ %s)") + resultingString, childrenHypotheses = betaStep(proof, hypotheses, actualTarget, "(goeland_equiv_s _ _ %s)") // Delta rules case gs3.NALL: - resultingString, childrenHypotheses, constantsCreated = deltaStep(proof, hypotheses, target, "apply %s. intros %s. apply NNPP. intros %s. ", constantsCreated) + resultingString, childrenHypotheses, constantsCreated = deltaStep(proof, hypotheses, actualTarget, "apply %s. intros %s. apply NNPP. intros %s. ", constantsCreated) case gs3.EX: - resultingString, childrenHypotheses, constantsCreated = deltaStep(proof, hypotheses, target, "elim %s. intros %s. intros %s. ", constantsCreated) + resultingString, childrenHypotheses, constantsCreated = deltaStep(proof, hypotheses, actualTarget, "elim %s. intros %s. intros %s. ", constantsCreated) // Gamma rules case gs3.ALL: - resultingString, childrenHypotheses = gammaStep(proof, hypotheses, target, "generalize (%s %s). intros %s. ", constantsCreated) + resultingString, childrenHypotheses = gammaStep(proof, hypotheses, actualTarget, "generalize (%s %s). intros %s. ", constantsCreated) case gs3.NEX: - resultingString, childrenHypotheses = gammaStep(proof, hypotheses, target, "apply %s. exists %s. apply NNPP. intros %s. ", constantsCreated) + resultingString, childrenHypotheses = gammaStep(proof, hypotheses, actualTarget, "apply %s. exists %s. apply NNPP. intros %s. ", constantsCreated) // Weakening rule case gs3.W: @@ -154,26 +167,26 @@ func makeStep(proof *gs3.GS3Sequent, hypotheses *AST.FormList, constantsCreated } case gs3.REWRITE: - resultingString, childrenHypotheses = rewriteStep(proof.GetRewriteWith(), hypotheses, target, proof.GetResultFormulasOfChild(0).Get(0)) + resultingString, childrenHypotheses = rewriteStep(proof.GetRewriteWith(), hypotheses, actualTarget, proof.GetResultFormulasOfChild(0).At(0)) } return resultingString, childrenHypotheses, constantsCreated } -func alphaStep(proof *gs3.GS3Sequent, hypotheses *AST.FormList, target int, format string) (string, []*AST.FormList) { +func alphaStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], target int, format string) (string, []Lib.List[AST.Form]) { var indices []int indices, hypotheses = introduceList(proof.GetResultFormulasOfChild(0), hypotheses) resultingString := fmt.Sprintf("apply "+format+". intros %s. ", introName(target), introNames(indices)) - return resultingString, []*AST.FormList{hypotheses} + return resultingString, []Lib.List[AST.Form]{hypotheses} } -func betaStep(proof *gs3.GS3Sequent, hypotheses *AST.FormList, target int, format string) (string, []*AST.FormList) { - resultHyps := []*AST.FormList{} +func betaStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], target int, format string) (string, []Lib.List[AST.Form]) { + resultHyps := []Lib.List[AST.Form]{} var indices []int resultingString := fmt.Sprintf("apply "+format+"; ", introName(target)) introducedNames := make([]string, 0) for i := range proof.Children() { - hypoCopy := hypotheses.Copy() + hypoCopy := Lib.ListCpy(hypotheses) indices, hypoCopy = introduceList(proof.GetResultFormulasOfChild(i), hypoCopy) introducedNames = append(introducedNames, "intros "+introNames(indices, " ")) resultHyps = append(resultHyps, hypoCopy) @@ -182,49 +195,61 @@ func betaStep(proof *gs3.GS3Sequent, hypotheses *AST.FormList, target int, forma return resultingString + "[ " + strings.Join(introducedNames, " | ") + " ].", resultHyps } -func deltaStep(proof *gs3.GS3Sequent, hypotheses *AST.FormList, target int, format string, constantsCreated []AST.Term) (string, []*AST.FormList, []AST.Term) { +func deltaStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], target int, format string, constantsCreated []AST.Term) (string, []Lib.List[AST.Form], []AST.Term) { var indices []int var name string //PrintInfo("DELTA", fmt.Sprintf("%s\n%s", hypotheses[target].ToString(), proof.GetResultFormulasOfChild(0).ToString())) indices, hypotheses = introduceList(proof.GetResultFormulasOfChild(0), hypotheses) constantsCreated, name = addTermGenerated(constantsCreated, proof.TermGenerated()) resultingString := fmt.Sprintf(format, introName(target), name, introNames(indices)) - return resultingString, []*AST.FormList{hypotheses}, constantsCreated + return resultingString, []Lib.List[AST.Form]{hypotheses}, constantsCreated } -func gammaStep(proof *gs3.GS3Sequent, hypotheses *AST.FormList, target int, format string, constantsCreated []AST.Term) (string, []*AST.FormList) { +func gammaStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], target int, format string, constantsCreated []AST.Term) (string, []Lib.List[AST.Form]) { var indices []int indices, hypotheses = introduceList(proof.GetResultFormulasOfChild(0), hypotheses) name := "(" + getRealConstantName(constantsCreated, proof.TermGenerated()) + ")" resultingString := fmt.Sprintf(format, introName(target), name, introNames(indices)) - return resultingString, []*AST.FormList{hypotheses} + return resultingString, []Lib.List[AST.Form]{hypotheses} } -func rewriteStep(rewriteRule AST.Form, hypotheses *AST.FormList, target int, replacementForm AST.Form) (string, []*AST.FormList) { - index, _ := hypotheses.GetIndexOf(rewriteRule) - resultingString := fmt.Sprintf("rewrite %s in %s.", introName(index), introName(target)) - hypotheses.Set(target, replacementForm) - return resultingString, []*AST.FormList{hypotheses} +func rewriteStep(rewriteRule AST.Form, hypotheses Lib.List[AST.Form], target int, replacementForm AST.Form) (string, []Lib.List[AST.Form]) { + index := Lib.ListIndexOf(rewriteRule, hypotheses) + var actualIndex int + switch i := index.(type) { + case Lib.Some[int]: + actualIndex = i.Val + case Lib.None[int]: + Glob.Anomaly("coq", fmt.Sprintf( + "Index of %s not found in %s", + rewriteRule.ToString(), + Lib.ListToString(hypotheses, ", ", "[]"), + )) + } + + resultingString := fmt.Sprintf("rewrite %s in %s.", introName(actualIndex), introName(target)) + hypotheses.Upd(target, replacementForm) + return resultingString, []Lib.List[AST.Form]{hypotheses} } // Processes the formula that was proven by Goéland. -func processMainFormula(form AST.Form) (*AST.FormList, AST.Form) { - formList := AST.NewFormList() +func processMainFormula(form AST.Form) (Lib.List[AST.Form], AST.Form) { + formList := Lib.NewList[AST.Form]() switch nf := form.(type) { case AST.Not: form = nf.GetForm() case AST.And: - last := nf.FormList.Len() - 1 - formList = AST.NewFormList(nf.FormList.GetElements(0, last)...) - form = nf.FormList.Get(last).(AST.Not).GetForm() + last := nf.GetChildFormulas().Len() - 1 + formList = Lib.MkListV(nf.GetChildFormulas().Get(0, last)...) + form = nf.GetChildFormulas().At(last).(AST.Not).GetForm() } return formList, form } // Prints the theorem's name & properly formats the first formula. -func makeTheorem(axioms *AST.FormList, conjecture AST.Form) string { +func makeTheorem(axioms Lib.List[AST.Form], conjecture AST.Form) string { problemName := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(Glob.GetProblemName(), ".", "_"), "=", "_"), "+", "_") - axiomsWithConj := axioms.Copy() + axiomsWithConj := Lib.ListCpy(axioms) axiomsWithConj.Append(AST.MakerNot(AST.MakerNot(conjecture))) formattedProblem := makeImpChain(axiomsWithConj) return "Theorem goeland_proof_of_" + problemName + " : " + @@ -232,25 +257,25 @@ func makeTheorem(axioms *AST.FormList, conjecture AST.Form) string { } // If [F1, F2, F3] is a formlist, then this function returns F1 -> (F2 -> F3). -func makeImpChain(forms *AST.FormList) AST.Form { +func makeImpChain(forms Lib.List[AST.Form]) AST.Form { last := forms.Len() - 1 - form := forms.Get(last) + form := forms.At(last) for i := last - 1; i >= 0; i-- { - form = AST.MakerImp(forms.Get(i), form) + form = AST.MakerImp(forms.At(i), form) } return form } -// Introduces a new formula in rocq's hypotheses. -func introduce(f AST.Form, hypotheses *AST.FormList) (int, *AST.FormList) { +// Introduces a new formula in coq's hypotheses. +func introduce(f AST.Form, hypotheses Lib.List[AST.Form]) (int, Lib.List[AST.Form]) { index := hypotheses.Len() hypotheses.Append(f) return index, hypotheses } -func introduceList(fl, hypotheses *AST.FormList) ([]int, *AST.FormList) { +func introduceList(fl, hypotheses Lib.List[AST.Form]) ([]int, Lib.List[AST.Form]) { indices := make([]int, fl.Len()) - for i, f := range fl.Slice() { + for i, f := range fl.GetSlice() { indices[i], hypotheses = introduce(f, hypotheses) } return indices, hypotheses @@ -332,14 +357,24 @@ func cp[T any](source []T) []T { return arr } -func cleanHypotheses(hypotheses *AST.FormList, form AST.Form) (string, []*AST.FormList) { +func cleanHypotheses(hypotheses Lib.List[AST.Form], form AST.Form) (string, []Lib.List[AST.Form]) { result := "" - index, _ := hypotheses.GetIndexOf(form) - if index != -1 { - hypotheses.Set(index, AST.MakerTop()) - result = fmt.Sprintf("clear %s. ", introName(index)) + index := Lib.ListIndexOf(form, hypotheses) + var actualIndex int + switch i := index.(type) { + case Lib.Some[int]: + actualIndex = i.Val + case Lib.None[int]: + Glob.Anomaly("coq", fmt.Sprintf( + "Index of %s not found in %s", + form.ToString(), + Lib.ListToString(hypotheses, ", ", "[]"), + )) } - return result, []*AST.FormList{hypotheses} + + hypotheses.Upd(actualIndex, AST.MakerTop()) + result = fmt.Sprintf("clear %s. ", introName(actualIndex)) + return result, []Lib.List[AST.Form]{hypotheses} } func getConstantName(id AST.Id) string { diff --git a/src/Mods/tptp/proof.go b/src/Mods/tptp/proof.go index 83475561..f456ffd9 100644 --- a/src/Mods/tptp/proof.go +++ b/src/Mods/tptp/proof.go @@ -48,6 +48,7 @@ import ( "github.com/GoelandProver/Goeland/AST" "github.com/GoelandProver/Goeland/Glob" + "github.com/GoelandProver/Goeland/Lib" "github.com/GoelandProver/Goeland/Mods/gs3" ) @@ -64,7 +65,7 @@ var dummyTerm = AST.MakerConst(AST.MakerId("Goeland_I")) func makeTptpProofFromGS3(proof *gs3.GS3Sequent) string { axioms, conjecture := processMainFormula(proof.GetTargetForm()) resultingString := makeTheorem(axioms, conjecture) - hypotheses := axioms.Copy() + hypotheses := Lib.ListCpy(axioms) hypotheses.Append(AST.MakerNot(conjecture.Copy())) AxiomCut := performCutAxiomStep(axioms, conjecture) @@ -84,31 +85,31 @@ func makeTptpProofFromGS3(proof *gs3.GS3Sequent) string { /*** Proof Steps ***/ -func followProofSteps(proof *gs3.GS3Sequent, hypotheses *AST.FormList, new_current_id int) string { +func followProofSteps(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], new_current_id int) string { var resultingString string var resultingStringParent string - var childrenHypotheses []*AST.FormList + var childrenHypotheses []Lib.List[AST.Form] if !proof.IsEmpty() { resultingStringParent, childrenHypotheses, new_current_id = makeProofStep(proof, hypotheses, new_current_id) } for i, child := range proof.Children() { if proof.IsEmpty() { - resultingString += followProofSteps(child, hypotheses.Copy(), new_current_id) + "\n" + resultingString += followProofSteps(child, Lib.ListCpy(hypotheses), new_current_id) + "\n" } else { - newHypotheses := hypotheses.Copy() - newHypotheses.AppendIfNotContains(childrenHypotheses[i].Slice()...) + newHypotheses := Lib.ListCpy(hypotheses) + newHypotheses = Lib.ListAdd(newHypotheses, childrenHypotheses[i].GetSlice()...) resultingString += followProofSteps(child, newHypotheses, new_current_id) + "\n" } } return resultingString + resultingStringParent } -func makeProofStep(proof *gs3.GS3Sequent, hypotheses *AST.FormList, new_current_id int) (string, []*AST.FormList, int) { +func makeProofStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], new_current_id int) (string, []Lib.List[AST.Form], int) { stepResult, childrenHypotheses, next_child_weakened_id := makeStep(proof, hypotheses, new_current_id) return stepResult, childrenHypotheses, next_child_weakened_id } -func findIndexPos(f AST.Form, hypotheses *AST.FormList, target int) int { +func findIndexPos(f AST.Form, hypotheses Lib.List[AST.Form], target int) int { targetPos := -1 switch initial_formula := f.(type) { @@ -125,9 +126,9 @@ func findIndexPos(f AST.Form, hypotheses *AST.FormList, target int) int { return targetPos } -func makeStep(proof *gs3.GS3Sequent, hypotheses *AST.FormList, new_current_id int) (string, []*AST.FormList, int) { +func makeStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], new_current_id int) (string, []Lib.List[AST.Form], int) { var resultingString string - childrenHypotheses := []*AST.FormList{hypotheses} + childrenHypotheses := []Lib.List[AST.Form]{hypotheses} next_child_weakened_id := -1 updateId(proof, new_current_id) @@ -140,7 +141,7 @@ func makeStep(proof *gs3.GS3Sequent, hypotheses *AST.FormList, new_current_id in if isPredEqual(proof.GetTargetForm()) { resultingString = fmt.Sprintf("fof("+prefix_step+"%d, plain, [%s] --> [], inference(%s, [status(thm)], [%s])).", proof.GetId(), - mapDefault(AST.ListToMappedString(hypotheses.Slice(), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), + mapDefault(AST.ListToMappedString(hypotheses.GetSlice(), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), "congruence", "") } else { @@ -148,7 +149,7 @@ func makeStep(proof *gs3.GS3Sequent, hypotheses *AST.FormList, new_current_id in resultingString = fmt.Sprintf("fof("+prefix_step+"%d, plain, [%s] --> [], inference(%s, [status(thm), %d], [%s])).", proof.GetId(), - mapDefault(AST.ListToMappedString(hypotheses.Slice(), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), + mapDefault(AST.ListToMappedString(hypotheses.GetSlice(), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), "leftHyp", targetPos, "") @@ -197,13 +198,13 @@ func makeStep(proof *gs3.GS3Sequent, hypotheses *AST.FormList, new_current_id in } case gs3.REWRITE: - resultingString, childrenHypotheses = rewriteStep(proof.GetRewriteWith(), hypotheses, target, proof.GetResultFormulasOfChild(0).Get(0)) + resultingString, childrenHypotheses = rewriteStep(proof.GetRewriteWith(), hypotheses, target, proof.GetResultFormulasOfChild(0).At(0)) } return resultingString + "\n", childrenHypotheses, next_child_weakened_id } -func alphaStep(proof *gs3.GS3Sequent, hypotheses *AST.FormList, target int, format string) (string, []*AST.FormList) { +func alphaStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], target int, format string) (string, []Lib.List[AST.Form]) { children_id := []int{} for _, c := range proof.Children() { @@ -215,33 +216,33 @@ func alphaStep(proof *gs3.GS3Sequent, hypotheses *AST.FormList, target int, form resultingString := fmt.Sprintf("fof(%s%d, plain, [%s] --> [], inference(%s, [status(thm), %d], [%s])).", prefix_step, proof.GetId(), - mapDefault(AST.ListToMappedString(hypotheses.Slice(), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), + mapDefault(AST.ListToMappedString(hypotheses.GetSlice(), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), format, target, Glob.IntListToString(children_id, prefix_step)) - newHypotheses := hypotheses.Copy() - newHypotheses.AppendIfNotContains(proof.GetResultFormulasOfChild(0).Slice()...) - return resultingString, []*AST.FormList{newHypotheses} + newHypotheses := Lib.ListCpy(hypotheses) + newHypotheses = Lib.ListAdd(newHypotheses, proof.GetResultFormulasOfChild(0).GetSlice()...) + return resultingString, []Lib.List[AST.Form]{newHypotheses} } -func betaStep(proof *gs3.GS3Sequent, hypotheses *AST.FormList, target int, format string) (string, []*AST.FormList) { - resultHyps := []*AST.FormList{} +func betaStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], target int, format string) (string, []Lib.List[AST.Form]) { + resultHyps := []Lib.List[AST.Form]{} children_id := []int{} for i, c := range proof.Children() { new_id := incrByOne(&id_proof_step, &mutex_proof_step) children_id = append(children_id, new_id) c.SetId(new_id) - newHypotheses := hypotheses.Copy() - newHypotheses.AppendIfNotContains(proof.GetResultFormulasOfChild(i).Slice()...) + newHypotheses := Lib.ListCpy(hypotheses) + newHypotheses = Lib.ListAdd(newHypotheses, proof.GetResultFormulasOfChild(i).GetSlice()...) resultHyps = append(resultHyps, newHypotheses) } resultingString := fmt.Sprintf("fof(%s%d, plain, [%s] --> [], inference(%s, [status(thm), %d], [%s])).", prefix_step, proof.GetId(), - mapDefault(AST.ListToMappedString(hypotheses.Slice(), ", ", "", tptpMapConnectors(), false)), + mapDefault(AST.ListToMappedString(hypotheses.GetSlice(), ", ", "", tptpMapConnectors(), false)), format, target, Glob.IntListToString(children_id, prefix_step)) @@ -249,7 +250,7 @@ func betaStep(proof *gs3.GS3Sequent, hypotheses *AST.FormList, target int, forma return resultingString, resultHyps } -func deltaStep(proof *gs3.GS3Sequent, hypotheses *AST.FormList, target int, format string) (string, []*AST.FormList) { +func deltaStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], target int, format string) (string, []Lib.List[AST.Form]) { children_id := []int{} for _, c := range proof.Children() { new_id := incrByOne(&id_proof_step, &mutex_proof_step) @@ -258,25 +259,25 @@ func deltaStep(proof *gs3.GS3Sequent, hypotheses *AST.FormList, target int, form } new_term := createNewConstant(proof.TermGenerated()) - + proof = updateSkolemSymbol(proof.TermGenerated(), new_term, proof) resultingString := fmt.Sprintf("fof(%s%d, plain, [%s] --> [], inference(%s, [status(thm), %d, '%s'], [%s])).", prefix_step, proof.GetId(), - mapDefault(AST.ListToMappedString(hypotheses.Slice(), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), + mapDefault(AST.ListToMappedString(hypotheses.GetSlice(), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), format, target, new_term.ToMappedString(tptpMapConnectors(), Glob.GetTypeProof()), Glob.IntListToString(children_id, prefix_step)) - newHypotheses := hypotheses.Copy() - newHypotheses.AppendIfNotContains(proof.GetResultFormulasOfChild(0).Slice()...) + newHypotheses := Lib.ListCpy(hypotheses) + newHypotheses = Lib.ListAdd(newHypotheses, proof.GetResultFormulasOfChild(0).GetSlice()...) - return resultingString, []*AST.FormList{newHypotheses} + return resultingString, []Lib.List[AST.Form]{newHypotheses} } -func gammaStep(proof *gs3.GS3Sequent, hypotheses *AST.FormList, target int, format string) (string, []*AST.FormList) { +func gammaStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], target int, format string) (string, []Lib.List[AST.Form]) { children_id := []int{} for _, c := range proof.Children() { new_id := incrByOne(&id_proof_step, &mutex_proof_step) @@ -289,61 +290,61 @@ func gammaStep(proof *gs3.GS3Sequent, hypotheses *AST.FormList, target int, form resultingString := fmt.Sprintf("fof(%s%d, plain, [%s] --> [], inference(%s, [status(thm), %d, $fot(%s)], [%s])).", prefix_step, proof.GetId(), - mapDefault(AST.ListToMappedString(hypotheses.Slice(), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), + mapDefault(AST.ListToMappedString(hypotheses.GetSlice(), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), format, target, findInConstants(proof.TermGenerated()).ToMappedString(tptpMapConnectors(), Glob.GetTypeProof()), Glob.IntListToString(children_id, prefix_step)) - newHypotheses := hypotheses.Copy() - newHypotheses.AppendIfNotContains(proof.GetResultFormulasOfChild(0).Slice()...) + newHypotheses := Lib.ListCpy(hypotheses) + newHypotheses = Lib.ListAdd(newHypotheses, proof.GetResultFormulasOfChild(0).GetSlice()...) - return resultingString, []*AST.FormList{newHypotheses} + return resultingString, []Lib.List[AST.Form]{newHypotheses} } -func weakenStep(proof *gs3.GS3Sequent, hypotheses *AST.FormList, target int, format string) (string, []*AST.FormList, int) { +func weakenStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], target int, format string) (string, []Lib.List[AST.Form], int) { child_id := incrByOne(&id_proof_step, &mutex_proof_step) if target != -1 { - hypotheses.Remove(target) + hypotheses = hypotheses.RemoveAt(target) } resultingString := fmt.Sprintf("fof(%s%d, plain, [%s] --> [], inference(%s, [status(thm), %d], [%s%d])).", prefix_step, proof.GetId(), - mapDefault(AST.ListToMappedString(hypotheses.Slice(), ", ", "", tptpMapConnectors(), false)), + mapDefault(AST.ListToMappedString(hypotheses.GetSlice(), ", ", "", tptpMapConnectors(), false)), format, target, prefix_step, child_id) - return resultingString, []*AST.FormList{hypotheses}, child_id + return resultingString, []Lib.List[AST.Form]{hypotheses}, child_id } -func rewriteStep(rewriteRule AST.Form, hypotheses *AST.FormList, target int, replacementForm AST.Form) (string, []*AST.FormList) { +func rewriteStep(rewriteRule AST.Form, hypotheses Lib.List[AST.Form], target int, replacementForm AST.Form) (string, []Lib.List[AST.Form]) { // resultingString := fmt.Sprintf("rewrite %s in %s.", introName(get(rewriteRule, hypotheses)), introName(target)) // hypotheses[target] = replacementForm - // return resultingString, []*AST.FormList{hypotheses} - return "", []*AST.FormList{} + // return resultingString, []Lib.List[AST.Form]{hypotheses} + return "", []Lib.List[AST.Form]{} } -func EquStep(proof *gs3.GS3Sequent, hypotheses *AST.FormList, target int) (string, []*AST.FormList) { +func EquStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], target int) (string, []Lib.List[AST.Form]) { resultingString := "" - resultHyps := []*AST.FormList{} + resultHyps := []Lib.List[AST.Form]{} children_id := []int{} for i, c := range proof.Children() { new_id := incrByOne(&id_proof_step, &mutex_proof_step) children_id = append(children_id, new_id) c.SetId(new_id) - newHypotheses := hypotheses.Copy() - newHypotheses.AppendIfNotContains(proof.GetResultFormulasOfChild(i).Slice()...) + newHypotheses := Lib.ListCpy(hypotheses) + newHypotheses = Lib.ListAdd(newHypotheses, proof.GetResultFormulasOfChild(i).GetSlice()...) resultHyps = append(resultHyps, newHypotheses) } // Sub-formulas - A := hypotheses.Get(target).(AST.Equ).GetF1() - B := hypotheses.Get(target).(AST.Equ).GetF2() + A := hypotheses.At(target).(AST.Equ).GetF1() + B := hypotheses.At(target).(AST.Equ).GetF2() notA := AST.MakerNot(A) notB := AST.MakerNot(B) A_imp_B := AST.MakerImp(A, B) @@ -352,96 +353,95 @@ func EquStep(proof *gs3.GS3Sequent, hypotheses *AST.FormList, target int) (strin // from A <=> B to A => B, B => A (unary) s1_id := fmt.Sprintf("%s%dext1", prefix_step, proof.GetId()) resultingString = fmt.Sprintf("fof(%s%d, plain, [%s] --> [], inference(%s, [status(thm), %d], [%s])).", - prefix_step, - proof.GetId(), - mapDefault(AST.ListToMappedString(hypotheses.Slice(), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), - "leftIff", - target, - s1_id) + resultingString + prefix_step, + proof.GetId(), + mapDefault(AST.ListToMappedString(hypotheses.GetSlice(), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), + "leftIff", + target, + s1_id) + resultingString // from A => B, B => A to ~A, B => A | B, B => A (binary) s2_id := fmt.Sprintf("%s%dext2", prefix_step, proof.GetId()) s3_id := fmt.Sprintf("%s%dext3", prefix_step, proof.GetId()) - newHyp := hypotheses.Copy() - newHyp.AppendIfNotContains([]AST.Form{A_imp_B, B_imp_A}...) + newHyp := Lib.ListCpy(hypotheses) + newHyp = Lib.ListAdd(newHyp, []AST.Form{A_imp_B, B_imp_A}...) resultingString = fmt.Sprintf("fof(%s, plain, [%s] --> [], inference(%s, [status(thm), %d], [%s, %s])).\n\n", - s1_id, - mapDefault(AST.ListToMappedString(newHyp.Slice(), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), - "leftImp2", - get(A_imp_B, newHyp), - s2_id, - s3_id) + resultingString + s1_id, + mapDefault(AST.ListToMappedString(newHyp.GetSlice(), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), + "leftImp2", + get(A_imp_B, newHyp), + s2_id, + s3_id) + resultingString // Branch s2 : from ~A, B => A to ~A, ~B | ~A, A s2_closure_id := fmt.Sprintf("%sext1", s2_id) - newHypS2 := newHyp.Copy() - newHypS2.AppendIfNotContains(notA) + newHypS2 := Lib.ListCpy(newHyp) + newHypS2 = Lib.ListAdd(newHypS2, notA.Copy()) resultingString = fmt.Sprintf("fof(%s, plain, [%s] --> [], inference(%s, [status(thm), %d], [%s%d, %s])).\n\n", - s2_id, - mapDefault(AST.ListToMappedString(newHypS2.Slice(), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), - "leftImp2", - get(B_imp_A, newHypS2), - prefix_step, - children_id[0], - s2_closure_id) + resultingString - resultHyps[0].AppendIfNotContains(newHypS2.Slice()...) - + s2_id, + mapDefault(AST.ListToMappedString(newHypS2.GetSlice(), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), + "leftImp2", + get(B_imp_A, newHypS2), + prefix_step, + children_id[0], + s2_closure_id) + resultingString + resultHyps[0] = Lib.ListAdd(resultHyps[0], newHypS2.GetSlice()...) // Branch 2.closure : from ~A, A closure - check polarity before - newHypS2Closure := newHypS2.Copy() - newHypS2Closure.AppendIfNotContains(A) + newHypS2Closure := Lib.ListCpy(newHypS2) + newHypS2Closure = Lib.ListAdd(newHypS2Closure, A) targetPosS2 := findIndexPos(A, newHypS2Closure, get(A, newHypS2Closure)) resultingString = fmt.Sprintf("fof(%s, plain, [%s] --> [], inference(%s, [status(thm), %d], [%s])).\n\n", - s2_closure_id, - mapDefault(AST.ListToMappedString(newHypS2Closure.Slice(), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), - "leftHyp", - targetPosS2, - "") + resultingString + s2_closure_id, + mapDefault(AST.ListToMappedString(newHypS2Closure.GetSlice(), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), + "leftHyp", + targetPosS2, + "") + resultingString // Branch s3: from B, B => A to B, ~B | B, A s3_closure_id := fmt.Sprintf("%sext1", s3_id) - newHypS3 := newHyp.Copy() - newHypS3.AppendIfNotContains(B) + newHypS3 := Lib.ListCpy(newHyp) + newHypS3 = Lib.ListAdd(newHypS3, B) resultingString = fmt.Sprintf("fof(%s, plain, [%s] --> [], inference(%s, [status(thm), %d], [%s, %s%d])).\n\n", - s3_id, - mapDefault(AST.ListToMappedString(newHypS3.Slice(), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), - "leftImp2", - get(B_imp_A, newHypS3), - s3_closure_id, - prefix_step, - children_id[1]) + resultingString - resultHyps[1].AppendIfNotContains(newHypS3.Slice()...) + s3_id, + mapDefault(AST.ListToMappedString(newHypS3.GetSlice(), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), + "leftImp2", + get(B_imp_A, newHypS3), + s3_closure_id, + prefix_step, + children_id[1]) + resultingString + resultHyps[1] = Lib.ListAdd(resultHyps[1], newHypS3.GetSlice()...) // Branch 3.closure : from B, ~B closure - check polarity before - newHypS3Closure := newHypS3.Copy() - newHypS3Closure.AppendIfNotContains(notB) + newHypS3Closure := Lib.ListCpy(newHypS3) + newHypS3Closure = Lib.ListAdd(newHypS3Closure, notB.Copy()) targetPosS3 := findIndexPos(B, newHypS3Closure, get(B, newHypS3Closure)) resultingString = fmt.Sprintf("fof(%s, plain, [%s] --> [], inference(%s, [status(thm), %d], [%s])).\n\n", - s3_closure_id, - mapDefault(AST.ListToMappedString(newHypS3Closure.Slice(), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), - "leftHyp", - targetPosS3, - "") + resultingString + s3_closure_id, + mapDefault(AST.ListToMappedString(newHypS3Closure.GetSlice(), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), + "leftHyp", + targetPosS3, + "") + resultingString return resultingString, resultHyps } -func NotEquStep(proof *gs3.GS3Sequent, hypotheses *AST.FormList, target int) (string, []*AST.FormList) { +func NotEquStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], target int) (string, []Lib.List[AST.Form]) { resultingString := "" - resultHyps := []*AST.FormList{} + resultHyps := []Lib.List[AST.Form]{} children_id := []int{} for i, c := range proof.Children() { new_id := incrByOne(&id_proof_step, &mutex_proof_step) children_id = append(children_id, new_id) c.SetId(new_id) - newHypotheses := hypotheses.Copy() - newHypotheses.AppendIfNotContains(proof.GetResultFormulasOfChild(i).Slice()...) + newHypotheses := Lib.ListCpy(hypotheses) + newHypotheses = Lib.ListAdd(newHypotheses, proof.GetResultFormulasOfChild(i).GetSlice()...) resultHyps = append(resultHyps, newHypotheses) } // Sub-formulas - equ := hypotheses.Get(target).(AST.Not).GetForm().(AST.Equ) + equ := hypotheses.At(target).(AST.Not).GetForm().(AST.Equ) A := equ.GetF1() B := equ.GetF2() not_A_imp_B := AST.MakerNot(AST.MakerImp(A, B)) @@ -451,64 +451,63 @@ func NotEquStep(proof *gs3.GS3Sequent, hypotheses *AST.FormList, target int) (st s1_id := fmt.Sprintf("%s%dext1", prefix_step, proof.GetId()) s2_id := fmt.Sprintf("%s%dext2", prefix_step, proof.GetId()) resultingString = fmt.Sprintf("fof(%s%d, plain, [%s] --> [], inference(%s, [status(thm), %d], [%s, %s])).", - prefix_step, - proof.GetId(), - mapDefault(AST.ListToMappedString(hypotheses.Slice(), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), - "leftNotIff", - target, - s1_id, - s2_id) + resultingString + prefix_step, + proof.GetId(), + mapDefault(AST.ListToMappedString(hypotheses.GetSlice(), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), + "leftNotIff", + target, + s1_id, + s2_id) + resultingString // from ~(A => B) to A, ~B - newHyp1 := hypotheses.Copy() - newHyp1.AppendIfNotContains(not_A_imp_B) + newHyp1 := Lib.ListCpy(hypotheses) + newHyp1 = Lib.ListAdd(newHyp1, not_A_imp_B.Copy()) resultingString = fmt.Sprintf("fof(%s, plain, [%s] --> [], inference(%s, [status(thm), %d], [%s%d])).\n\n", - s1_id, - mapDefault(AST.ListToMappedString(newHyp1.Slice(), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), - "leftNotImplies", - get(not_A_imp_B, newHyp1), - prefix_step, - children_id[1]) + resultingString - resultHyps[1].AppendIfNotContains(newHyp1.Slice()...) + s1_id, + mapDefault(AST.ListToMappedString(newHyp1.GetSlice(), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), + "leftNotImplies", + get(not_A_imp_B, newHyp1), + prefix_step, + children_id[1]) + resultingString + resultHyps[1] = Lib.ListAdd(resultHyps[1], newHyp1.GetSlice()...) // from ~(B => A) to B, ~A - newHyp2 := hypotheses.Copy() - newHyp2.AppendIfNotContains(not_B_imp_A) + newHyp2 := Lib.ListCpy(hypotheses) + newHyp2 = Lib.ListAdd(newHyp2, not_B_imp_A.Copy()) resultingString = fmt.Sprintf("fof(%s, plain, [%s] --> [], inference(%s, [status(thm), %d], [%s%d])).\n\n", - s2_id, - mapDefault(AST.ListToMappedString(newHyp2.Slice(), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), - "leftNotImplies", - get(not_B_imp_A, newHyp2), - prefix_step, - children_id[0]) + resultingString - resultHyps[0].AppendIfNotContains(newHyp2.Slice()...) + s2_id, + mapDefault(AST.ListToMappedString(newHyp2.GetSlice(), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), + "leftNotImplies", + get(not_B_imp_A, newHyp2), + prefix_step, + children_id[0]) + resultingString + resultHyps[0] = Lib.ListAdd(resultHyps[0], newHyp2.GetSlice()...) return resultingString, resultHyps } - /*** Initial Formula Management ***/ // Processes the formula that was proven by Goéland. -func processMainFormula(form AST.Form) (*AST.FormList, AST.Form) { - formList := AST.NewFormList() +func processMainFormula(form AST.Form) (Lib.List[AST.Form], AST.Form) { + formList := Lib.NewList[AST.Form]() switch nf := form.(type) { case AST.Not: form = nf.GetForm() case AST.And: - last := nf.FormList.Len() - 1 - formList = AST.NewFormList(nf.FormList.GetElements(0, last)...) - form = nf.FormList.Get(last).(AST.Not).GetForm() + last := nf.GetChildFormulas().Len() - 1 + formList = Lib.MkListV(nf.GetChildFormulas().Get(0, last)...) + form = nf.GetChildFormulas().At(last).(AST.Not).GetForm() } return formList, form } // Prints the theorem's name & properly formats the first formula. -func makeTheorem(axioms *AST.FormList, conjecture AST.Form) string { +func makeTheorem(axioms Lib.List[AST.Form], conjecture AST.Form) string { var resulting_string string problemName := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(Glob.GetProblemName(), ".", "_"), "=", "_"), "+", "_") - for _, ax := range axioms.Slice() { + for _, ax := range axioms.GetSlice() { resulting_string = resulting_string + "fof(" + fmt.Sprintf("ax%d", ax.GetIndex()) + ", axiom, " + mapDefault(ax.ToMappedString(tptpMapConnectors(), Glob.GetTypeProof())) + ").\n\n" } @@ -517,7 +516,7 @@ func makeTheorem(axioms *AST.FormList, conjecture AST.Form) string { } // Perform the first step to go from ax |- c to ax, ~c |- -func performFirstStep(axioms *AST.FormList, conjecture AST.Form, hypothesis *AST.FormList, nextId int) (string, int) { +func performFirstStep(axioms Lib.List[AST.Form], conjecture AST.Form, hypothesis Lib.List[AST.Form], nextId int) (string, int) { cutFormNotId := incrByOne(&id_proof_step, &mutex_proof_step) cutFormHypId := incrByOne(&id_proof_step, &mutex_proof_step) nextFormId := incrByOne(&id_proof_step, &mutex_proof_step) @@ -525,7 +524,7 @@ func performFirstStep(axioms *AST.FormList, conjecture AST.Form, hypothesis *AST // Cut initial formula, |- ~c, c step cutFormNot := fmt.Sprintf("fof("+prefix_step+"%d, plain, [%s] --> [%s, %s], inference(%s, [status(thm), %d], [%s])).", cutFormNotId, - mapDefault(AST.ListToMappedString(axioms.Slice(), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), + mapDefault(AST.ListToMappedString(axioms.GetSlice(), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), mapDefault(conjecture.ToMappedString(tptpMapConnectors(), false)), mapDefault(AST.MakerNot(conjecture).ToMappedString(tptpMapConnectors(), Glob.GetTypeProof())), "rightNot", @@ -535,7 +534,7 @@ func performFirstStep(axioms *AST.FormList, conjecture AST.Form, hypothesis *AST // Cut initial formula, c |- c step cutFormHyp := fmt.Sprintf("fof("+prefix_step+"%d, plain, [%s] --> [%s], inference(%s, [status(thm), %d], [%s])).", cutFormHypId, - mapDefault(AST.ListToMappedString(append(axioms.Slice(), conjecture), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), + mapDefault(AST.ListToMappedString(append(axioms.GetSlice(), conjecture), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), mapDefault(conjecture.ToMappedString(tptpMapConnectors(), Glob.GetTypeProof())), "hyp", axioms.Len(), @@ -546,7 +545,7 @@ func performFirstStep(axioms *AST.FormList, conjecture AST.Form, hypothesis *AST // indexHyp, _ := hypothesis.GetIndexOf(AST.MakerNot(conjecture)) startForm := fmt.Sprintf("fof(f%d, plain, [%s] --> [%s], inference(cut, [status(thm), %d], [%s%d, %s%d])).\n\n", nextId, - mapDefault(AST.ListToMappedString(axioms.Slice(), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), + mapDefault(AST.ListToMappedString(axioms.GetSlice(), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), mapDefault(conjecture.ToMappedString(tptpMapConnectors(), Glob.GetTypeProof())), 1, //indexHyp, @@ -558,14 +557,13 @@ func performFirstStep(axioms *AST.FormList, conjecture AST.Form, hypothesis *AST return cutFormHyp + "\n\n" + cutFormNot + "\n\n" + startForm, nextFormId } - // Perform the cut axiom steps -func performCutAxiomStep(axioms *AST.FormList, conjecture AST.Form) string { +func performCutAxiomStep(axioms Lib.List[AST.Form], conjecture AST.Form) string { resultString := "" // Loop on axioms - for i, ax := range axioms.Slice() { + for i, ax := range axioms.GetSlice() { var nextStep string if i == axioms.Len()-1 { nextStep = "f0" @@ -577,7 +575,7 @@ func performCutAxiomStep(axioms *AST.FormList, conjecture AST.Form) string { prefix_axiom_cut, i, // AST.ListToMappedString(axioms.GetElements(0, i), ", ", "", tptpMapConnectors(), GetTypeProof()), - mapDefault(AST.ListToMappedString(axioms.GetElements(0, i), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), + mapDefault(AST.ListToMappedString(axioms.Get(0, i), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), mapDefault(conjecture.ToMappedString(tptpMapConnectors(), Glob.GetTypeProof())), 0, //i, @@ -592,8 +590,8 @@ func performCutAxiomStep(axioms *AST.FormList, conjecture AST.Form) string { /*** Utility Functions ***/ -func get(f AST.Form, fl *AST.FormList) int { - for i, h := range fl.Slice() { +func get(f AST.Form, fl Lib.List[AST.Form]) int { + for i, h := range fl.GetSlice() { if h.Equals(f) { return i } @@ -638,15 +636,15 @@ func updateSkolemSymbol(old, new AST.Term, proof *gs3.GS3Sequent) *gs3.GS3Sequen proof.SetTermGenerated(new_generated_term) } - new_forms_generated := make([]*AST.FormList, len(proof.GetResultFormulasOfChildren())) + new_forms_generated := make([]Lib.List[AST.Form], len(proof.GetResultFormulasOfChildren())) for i, fg := range proof.GetResultFormulasOfChildren() { - new_forms_generated_bis := AST.NewFormList() - for _, fg_bis := range fg.Slice() { + new_forms_generated_bis := Lib.NewList[AST.Form]() + for _, fg_bis := range fg.GetSlice() { new_term, _ := fg_bis.ReplaceTermByTerm(old, new) new_forms_generated_bis.Append(new_term) } new_forms_generated[i] = new_forms_generated_bis - } + } proof.SetFormGenerated(new_forms_generated) // Update Children @@ -666,7 +664,7 @@ func createNewConstant(term AST.Term) AST.Term { mutex_constant.Lock() new_id := len(constant_created) new_term_name := fmt.Sprintf("%s%d", prefix_const, new_id) - new_term := AST .MakerConst(AST.MakerNewId(new_term_name)) + new_term := AST.MakerConst(AST.MakerNewId(new_term_name)) original_term = append(original_term, term) constant_created = append(constant_created, new_term) mutex_constant.Unlock() diff --git a/src/Search/destructive.go b/src/Search/destructive.go index ba555609..d9867946 100644 --- a/src/Search/destructive.go +++ b/src/Search/destructive.go @@ -965,7 +965,7 @@ func (ds *destructiveSearch) tryRewrite(rewritten []Core.IntSubstAndForm, f Core newRewritten := []Core.IntSubstAndFormAndTerms{} for _, isaf := range rewritten { newFNTs := Core.MakeEmptyFormAndTermsList() - for _, isaf_f := range isaf.GetSaf().GetForm().Slice() { + for _, isaf_f := range isaf.GetSaf().GetForm().GetSlice() { newFNTs = append(newFNTs, Core.MakeFormAndTerm(isaf_f, f.GetTerms())) } newRewritten = append(newRewritten, Core.MakeIntSubstAndFormAndTerms(isaf.GetId_rewrite(), Core.MakeSubstAndFormAndTerms(isaf.GetSaf().GetSubst(), newFNTs))) @@ -1119,7 +1119,7 @@ func (ds *destructiveSearch) ManageClosureRule(father_id uint64, st *State, c Co ) // Create substAndForm with the current form and the subst found - subst_and_form_for_father := Core.MakeSubstAndForm(subst_for_father, AST.NewFormList(f.GetForm())) + subst_and_form_for_father := Core.MakeSubstAndForm(subst_for_father, Lib.MkListV(f.GetForm())) debug( Lib.MkLazy(func() string { diff --git a/src/Search/incremental/rules.go b/src/Search/incremental/rules.go index 4fffd124..f6929cd4 100644 --- a/src/Search/incremental/rules.go +++ b/src/Search/incremental/rules.go @@ -203,7 +203,7 @@ func (aa *AlphaAnd) apply() []RuleList { switch form := aa.GetForm().(type) { case AST.And: - for _, subForm := range form.FormList.Slice() { + for _, subForm := range form.GetChildFormulas().GetSlice() { resultRules = append(resultRules, makeCorrectRule(subForm, aa.GetTerms())) } } @@ -242,7 +242,7 @@ func (ano *AlphaNotOr) apply() []RuleList { case AST.Not: switch subForm := form.GetForm().(type) { case AST.Or: - for _, subForm := range subForm.FormList.Slice() { + for _, subForm := range subForm.GetChildFormulas().GetSlice() { resultRules = append(resultRules, makeCorrectRule(AST.MakerNot(subForm), ano.GetTerms())) } } @@ -283,7 +283,7 @@ func (bna *BetaNotAnd) apply() []RuleList { case AST.Not: switch subForm := form.GetForm().(type) { case AST.And: - for _, andForm := range subForm.FormList.Slice() { + for _, andForm := range subForm.GetChildFormulas().GetSlice() { resultRulesBeta = append(resultRulesBeta, RuleList{makeCorrectRule(AST.MakerNot(andForm), bna.GetTerms())}) } } @@ -326,7 +326,7 @@ func (bo *BetaOr) apply() []RuleList { switch form := bo.GetForm().(type) { case AST.Or: - for _, subForm := range form.FormList.Slice() { + for _, subForm := range form.GetChildFormulas().GetSlice() { resultRulesBeta = append(resultRulesBeta, RuleList{makeCorrectRule(subForm, bo.GetTerms())}) } } @@ -500,8 +500,8 @@ func (de *DeltaExists) apply() []RuleList { type RuleList []Rule -func (rl *RuleList) GetFormList() *AST.FormList { - result := AST.NewFormList() +func (rl *RuleList) GetFormList() Lib.List[AST.Form] { + result := Lib.NewList[AST.Form]() for _, rule := range *rl { result.Append(rule.GetForm()) diff --git a/src/Search/incremental/rulesManager.go b/src/Search/incremental/rulesManager.go index 330a9b6c..1a844cec 100644 --- a/src/Search/incremental/rulesManager.go +++ b/src/Search/incremental/rulesManager.go @@ -255,22 +255,22 @@ func (rm *RulesManager) ToString() string { str := "~~~~Rule Manager~~~~\n" if len(rm.atomicRules) > 0 { - str += "| Atomic Rules: " + rm.atomicRules.GetFormList().ToString() + "\n" + str += "| Atomic Rules: " + Lib.ListToString(rm.atomicRules.GetFormList(), ", ", "[]") + "\n" } if len(rm.atomicNotRules) > 0 { - str += "| Negative Atomic Rules: " + rm.atomicNotRules.GetFormList().ToString() + "\n" + str += "| Negative Atomic Rules: " + Lib.ListToString(rm.atomicNotRules.GetFormList(), ", ", "[]") + "\n" } if len(rm.alphaRules) > 0 { - str += "| Alpha Rules: " + rm.alphaRules.GetFormList().ToString() + "\n" + str += "| Alpha Rules: " + Lib.ListToString(rm.alphaRules.GetFormList(), ", ", "[]") + "\n" } if len(rm.deltaRules) > 0 { - str += "| Delta Rules: " + rm.deltaRules.GetFormList().ToString() + "\n" + str += "| Delta Rules: " + Lib.ListToString(rm.deltaRules.GetFormList(), ", ", "[]") + "\n" } if len(rm.betaRules) > 0 { - str += "| Beta Rules: " + rm.betaRules.GetFormList().ToString() + "\n" + str += "| Beta Rules: " + Lib.ListToString(rm.betaRules.GetFormList(), ", ", "[]") + "\n" } if len(rm.gammaRules) > 0 { - str += "| Gamma Rules: " + rm.gammaRules.GetFormList().ToString() + "\n" + str += "| Gamma Rules: " + Lib.ListToString(rm.gammaRules.GetFormList(), ", ", "[]") + "\n" } if len(rm.reintroRules.reintroRules) > 0 { str += "| Reintro Rules: " + rm.reintroRules.ToString() + "\n" diff --git a/src/Search/nonDestructiveSearch.go b/src/Search/nonDestructiveSearch.go index 46c70f2b..9e1fb9a5 100644 --- a/src/Search/nonDestructiveSearch.go +++ b/src/Search/nonDestructiveSearch.go @@ -180,7 +180,7 @@ func (nds *nonDestructiveSearch) instantiate(fatherId uint64, state *State, c Co if !found { // La meta nouvellement générée n'apparaît pas dans la substitution // Trouver celle de la formula de base - for _, f := range s.GetForm().Slice() { + for _, f := range s.GetForm().GetSlice() { for _, term_formula := range f.GetMetas().Elements().GetSlice() { if !found && term_formula.IsMeta() && term_formula.GetName() == new_meta.GetName() { association_subst.Set(new_meta, term_formula) @@ -205,7 +205,7 @@ func (nds *nonDestructiveSearch) instantiate(fatherId uint64, state *State, c Co return fmt.Sprintf( "Error : No matching found for %v in new formula : %v\n", new_meta.ToString(), - s.GetForm().ToString()) + Lib.ListToString(s.GetForm(), ", ", "[]")) }), ) } diff --git a/src/Search/proof.go b/src/Search/proof.go index 6a3a5e27..1fa3e56f 100644 --- a/src/Search/proof.go +++ b/src/Search/proof.go @@ -111,8 +111,8 @@ func (ifl *IntFormAndTermsList) Copy() IntFormAndTermsList { return MakeIntFormAndTermsList(ifl.i, ifl.fl.Copy()) } -func (ifl *IntFormAndTermsList) GetForms() *AST.FormList { - res := AST.NewFormList() +func (ifl *IntFormAndTermsList) GetForms() Lib.List[AST.Form] { + res := Lib.NewList[AST.Form]() for _, ift := range (*ifl).GetFL() { res.Append(ift.GetForm()) } @@ -126,10 +126,10 @@ func (ifl *IntFormAndTermsList) SubstituteBy( return MakeIntFormAndTermsList(ifl.i, ifl.fl.SubstituteBy(metas, terms)) } -func GetFormulasFromIntFormAndTermList(iftl []IntFormAndTermsList) *AST.FormList { - res := AST.NewFormList() +func GetFormulasFromIntFormAndTermList(iftl []IntFormAndTermsList) Lib.List[AST.Form] { + res := Lib.NewList[AST.Form]() for _, v := range iftl { - res.Append(v.GetForms().Slice()...) + res.Append(v.GetForms().GetSlice()...) } return res } @@ -390,7 +390,7 @@ func RetrieveUninstantiatedMetaFromProof(proofStruct []ProofStruct) Lib.Set[AST. res = res.Union(proofMetas) resResultFormulas := GetFormulasFromIntFormAndTermList(proofElement.GetResultFormulas()) - for _, v := range resResultFormulas.Slice() { + for _, v := range resResultFormulas.GetSlice() { res = res.Union(v.GetMetas()) } diff --git a/src/Search/rules.go b/src/Search/rules.go index a2f653dc..e327a9d1 100644 --- a/src/Search/rules.go +++ b/src/Search/rules.go @@ -289,8 +289,10 @@ func applyAlphaNotOrRule( ) Core.FormAndTermsList { setStateRules(state, "ALPHA", "NOT", "OR") - for i := range formWithoutNot.FormList.Slice() { - result = result.AppendIfNotContains(Core.MakeFormAndTerm(AST.MakerNot(formWithoutNot.FormList.Get(i)), terms)) + for i := range formWithoutNot.GetChildFormulas().GetSlice() { + result = result.AppendIfNotContains( + Core.MakeFormAndTerm(AST.MakerNot(formWithoutNot.GetChildFormulas().At(i)), terms), + ) } return result @@ -318,8 +320,10 @@ func applyAlphaAndRule( ) Core.FormAndTermsList { setStateRules(state, "ALPHA", "AND") - for i := range formTyped.FormList.Slice() { - result = result.AppendIfNotContains(Core.MakeFormAndTerm(formTyped.FormList.Get(i), terms)) + for i := range formTyped.GetChildFormulas().GetSlice() { + result = result.AppendIfNotContains( + Core.MakeFormAndTerm(formTyped.GetChildFormulas().At(i), terms), + ) } return result @@ -377,8 +381,11 @@ func applyBetaNotAndRule( ) []Core.FormAndTermsList { setStateRules(state, "BETA", "NOT", "AND") - for i := range formWithoutNot.FormList.Slice() { - result = append(result, Core.MakeSingleElementFormAndTermList(Core.MakeFormAndTerm(AST.MakerNot(formWithoutNot.FormList.Get(i)), terms))) + for i := range formWithoutNot.GetChildFormulas().GetSlice() { + result = append( + result, + Core.MakeSingleElementFormAndTermList( + Core.MakeFormAndTerm(AST.MakerNot(formWithoutNot.GetChildFormulas().At(i)), terms))) } return result @@ -412,8 +419,9 @@ func applyBetaOrRule( ) []Core.FormAndTermsList { setStateRules(state, "BETA", "OR") - for i := range formTyped.FormList.Slice() { - result = append(result, Core.MakeSingleElementFormAndTermList(Core.MakeFormAndTerm(formTyped.FormList.Get(i), terms))) + for i := range formTyped.GetChildFormulas().GetSlice() { + result = append(result, Core.MakeSingleElementFormAndTermList( + Core.MakeFormAndTerm(formTyped.GetChildFormulas().At(i), terms))) } return result diff --git a/src/Search/state.go b/src/Search/state.go index 9015e430..0b9ee1fd 100644 --- a/src/Search/state.go +++ b/src/Search/state.go @@ -116,13 +116,13 @@ func (st State) GetSubstsFound() []Core.SubstAndForm { func (s State) GetTreePos() Unif.DataStructure { return s.tree_pos } -func (s *State) AddToTreePos(fl *AST.FormList) { +func (s *State) AddToTreePos(fl Lib.List[AST.Form]) { s.tree_pos = s.tree_pos.InsertFormulaListToDataStructure(fl) } func (s State) GetTreeNeg() Unif.DataStructure { return s.tree_neg } -func (s *State) AddToTreeNeg(fl *AST.FormList) { +func (s *State) AddToTreeNeg(fl Lib.List[AST.Form]) { s.tree_neg = s.tree_neg.InsertFormulaListToDataStructure(fl) } func (s State) GetProof() []ProofStruct { diff --git a/src/Typing/form_rules.go b/src/Typing/form_rules.go index c588692f..e177b4a1 100644 --- a/src/Typing/form_rules.go +++ b/src/Typing/form_rules.go @@ -34,6 +34,7 @@ package Typing import ( "github.com/GoelandProver/Goeland/AST" + "github.com/GoelandProver/Goeland/Lib" ) /** @@ -83,20 +84,20 @@ func applyQuantRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) /* Applies OR or AND rule and launches n goroutines waiting its children */ func applyNAryRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { - formList := AST.NewFormList() + formList := Lib.NewList[AST.Form]() // Add rule to prooftree switch f := (state.consequence.f).(type) { case AST.And: root.appliedRule = "∧" - formList = f.FormList + formList = f.GetChildFormulas() case AST.Or: root.appliedRule = "∨" - formList = f.FormList + formList = f.GetChildFormulas() } // Construct children with all the formulas children := []Sequent{} - for _, form := range formList.Slice() { + for _, form := range formList.GetSlice() { children = append(children, Sequent{ globalContext: state.globalContext, localContext: state.localContext.copy(), diff --git a/src/Typing/launch_rules.go b/src/Typing/launch_rules.go index 3eb3299b..369abc5c 100644 --- a/src/Typing/launch_rules.go +++ b/src/Typing/launch_rules.go @@ -46,7 +46,7 @@ import ( type Reconstruct struct { result bool - forms *AST.FormList + forms Lib.List[AST.Form] terms Lib.List[AST.Term] err error } @@ -119,8 +119,8 @@ func selectSequents(chansTab [](chan Reconstruct), chanQuit chan Reconstruct) Re errorFound = res.err } else { // Once the child sends back to the father, it should only have one item. - if res.forms != nil && res.forms.Len() == 1 { - forms[index] = res.forms.Get(0) + if res.forms.Len() == 1 { + forms[index] = res.forms.At(0) } if res.terms.Len() == 1 { terms.Upd(index, res.terms.At(0)) @@ -130,7 +130,7 @@ func selectSequents(chansTab [](chan Reconstruct), chanQuit chan Reconstruct) Re } selectCleanup(errorFound, hasAnswered, chansTab) - return Reconstruct{result: errorFound == nil, forms: AST.NewFormList(forms...), terms: terms, err: errorFound} + return Reconstruct{result: errorFound == nil, forms: Lib.MkListV(forms...), terms: terms, err: errorFound} } /* Utils functions for selectSequents */ @@ -172,6 +172,6 @@ func treatReturns(res Reconstruct) (AST.Form, error) { if res.forms.Len() > 1 { return nil, fmt.Errorf("more than one formula is returned by the typing system") } - return res.forms.Get(0), res.err + return res.forms.At(0), res.err } } diff --git a/src/Typing/rules.go b/src/Typing/rules.go index ea0a22a3..80713c65 100644 --- a/src/Typing/rules.go +++ b/src/Typing/rules.go @@ -135,21 +135,21 @@ func reconstructForm(reconstruction Reconstruct, baseForm AST.Form) Reconstruct var f AST.Form switch form := baseForm.(type) { case AST.All: - f = AST.MakeAll(form.GetIndex(), form.GetVarList(), unquantify(reconstruction.forms.Get(1), form)) + f = AST.MakeAll(form.GetIndex(), form.GetVarList(), unquantify(reconstruction.forms.At(1), form)) case AST.AllType: - f = AST.MakeAllType(form.GetIndex(), form.GetVarList(), unquantify(reconstruction.forms.Get(1), form)) + f = AST.MakeAllType(form.GetIndex(), form.GetVarList(), unquantify(reconstruction.forms.At(1), form)) case AST.Ex: - f = AST.MakeEx(form.GetIndex(), form.GetVarList(), unquantify(reconstruction.forms.Get(1), form)) + f = AST.MakeEx(form.GetIndex(), form.GetVarList(), unquantify(reconstruction.forms.At(1), form)) case AST.And: f = AST.MakeAnd(form.GetIndex(), reconstruction.forms) case AST.Or: f = AST.MakeOr(form.GetIndex(), reconstruction.forms) case AST.Imp: - f = AST.MakeImp(form.GetIndex(), reconstruction.forms.Get(0), reconstruction.forms.Get(1)) + f = AST.MakeImp(form.GetIndex(), reconstruction.forms.At(0), reconstruction.forms.At(1)) case AST.Equ: - f = AST.MakeEqu(form.GetIndex(), reconstruction.forms.Get(0), reconstruction.forms.Get(1)) + f = AST.MakeEqu(form.GetIndex(), reconstruction.forms.At(0), reconstruction.forms.At(1)) case AST.Not: - f = AST.MakeNot(form.GetIndex(), reconstruction.forms.Get(0)) + f = AST.MakeNot(form.GetIndex(), reconstruction.forms.At(0)) case AST.Pred: // The len(form.GetTypeVars()) first children launched are children for typevars. // So the len(form.GetTypeVars()) first children will return @@ -178,7 +178,7 @@ func reconstructForm(reconstruction Reconstruct, baseForm AST.Form) Reconstruct f = baseForm } - return Reconstruct{result: true, forms: AST.NewFormList(f), err: nil} + return Reconstruct{result: true, forms: Lib.MkListV(f), err: nil} } /* Reconstructs a Term depending on what the children has returned */ diff --git a/src/Typing/type.go b/src/Typing/type.go index efb7e599..2d530bef 100644 --- a/src/Typing/type.go +++ b/src/Typing/type.go @@ -75,9 +75,9 @@ func secondPassAux(form AST.Form, vars []AST.Var, types []AST.TypeApp) AST.Form // Real case: classical predicate, it should be given return AST.MakePred(f.GetIndex(), f.GetID(), terms, f.GetTypeVars()) case AST.And: - return AST.MakeAnd(f.GetIndex(), nArySecondPass(f.FormList, vars, types)) + return AST.MakeAnd(f.GetIndex(), nArySecondPass(f.GetChildFormulas(), vars, types)) case AST.Or: - return AST.MakeOr(f.GetIndex(), nArySecondPass(f.FormList, vars, types)) + return AST.MakeOr(f.GetIndex(), nArySecondPass(f.GetChildFormulas(), vars, types)) case AST.Imp: return AST.MakeImp(f.GetIndex(), secondPassAux(f.GetF1(), vars, types), secondPassAux(f.GetF2(), vars, types)) case AST.Equ: @@ -118,10 +118,10 @@ func secondPassTerm(term AST.Term, vars []AST.Var, types []AST.TypeApp) AST.Term return term } -func nArySecondPass(forms *AST.FormList, vars []AST.Var, types []AST.TypeApp) *AST.FormList { - res := AST.NewFormList() +func nArySecondPass(forms Lib.List[AST.Form], vars []AST.Var, types []AST.TypeApp) Lib.List[AST.Form] { + res := Lib.NewList[AST.Form]() - for _, form := range forms.Slice() { + for _, form := range forms.GetSlice() { res.Append(secondPassAux(form, vars, types)) } diff --git a/src/Unif/code-trees.go b/src/Unif/code-trees.go index 0f8687ac..6beb3371 100644 --- a/src/Unif/code-trees.go +++ b/src/Unif/code-trees.go @@ -58,11 +58,11 @@ func (c CodeBlock) Copy() CodeBlock { type Node struct { value CodeBlock children []*Node - formulae *AST.FormList + formulas Lib.List[AST.Form] } func NewNode() *Node { - return &Node{CodeBlock{}, []*Node{}, AST.NewFormList()} + return &Node{CodeBlock{}, []*Node{}, Lib.NewList[AST.Form]()} } func (n Node) getValue() CodeBlock { @@ -71,8 +71,8 @@ func (n Node) getValue() CodeBlock { func (n Node) getChildren() []*Node { return CopyNodeList(n.children) } -func (n Node) getFormulae() *AST.FormList { - return n.formulae.Copy() +func (n Node) getFormulas() Lib.List[AST.Form] { + return Lib.ListCpy(n.formulas) } /* Check if a node is empty */ @@ -81,13 +81,13 @@ func (n Node) IsEmpty() bool { } /* Make data struct */ -func (n Node) MakeDataStruct(fl *AST.FormList, is_pos bool) DataStructure { +func (n Node) MakeDataStruct(fl Lib.List[AST.Form], is_pos bool) DataStructure { return makeCodeTreeFromAtomic(fl, is_pos) } /* Copy a datastruct */ func (n Node) Copy() DataStructure { - return Node{n.getValue(), n.getChildren(), n.getFormulae()} + return Node{n.getValue(), n.getChildren(), n.getFormulas()} } /********************/ @@ -96,14 +96,14 @@ func (n Node) Copy() DataStructure { /* The Node is a leaf when it contains at least one formulae. */ func (n Node) isLeaf() bool { - return n.getFormulae().Len() > 0 + return n.getFormulas().Len() > 0 } /* Make two code trees (tree_pos and tree_neg) from st.atomic */ -func makeCodeTreeFromAtomic(lf *AST.FormList, is_pos bool) *Node { - form := AST.NewFormList() +func makeCodeTreeFromAtomic(lf Lib.List[AST.Form], is_pos bool) *Node { + form := Lib.NewList[AST.Form]() - for _, f := range lf.Slice() { + for _, f := range lf.GetSlice() { switch nf := f.(type) { case AST.Pred: if is_pos { @@ -126,10 +126,10 @@ func makeCodeTreeFromAtomic(lf *AST.FormList, is_pos bool) *Node { } /* Makes a Code Tree from a Sequence of instructions */ -func makeCodeTree(forms *AST.FormList) *Node { +func makeCodeTree(forms Lib.List[AST.Form]) *Node { root := makeNode(nil) - for _, f := range forms.Slice() { + for _, f := range forms.GetSlice() { f_tmp := f.Copy() form_tmp := ParseFormula(f_tmp) root.insert(form_tmp) @@ -152,13 +152,13 @@ func makeNode(block CodeBlock) *Node { n := new(Node) n.value = block.Copy() n.children = []*Node{} - n.formulae = AST.NewFormList() + n.formulas = Lib.NewList[AST.Form]() return n } /* Insert a lsit of formula into the right tree */ -func (n Node) InsertFormulaListToDataStructure(lf *AST.FormList) DataStructure { - for _, f := range lf.Slice() { +func (n Node) InsertFormulaListToDataStructure(lf Lib.List[AST.Form]) DataStructure { + for _, f := range lf.GetSlice() { switch nf := f.Copy().(type) { case AST.Pred: n.insert(ParseFormula(nf)) @@ -198,7 +198,7 @@ func (n Node) printAux(tab int) { } if n.isLeaf() { - for _, form := range n.formulae.Slice() { + for _, form := range n.formulas.GetSlice() { debug(Lib.MkLazy(func() string { return strings.Repeat("\t", tab+1) + form.ToString() })) } } @@ -214,7 +214,7 @@ func (n Node) printAux(tab int) { func (n *Node) insert(sequence Sequence) { if len(n.value) == 0 { n.value = sequence.GetInstructions() - n.formulae = AST.NewFormList(sequence.GetFormula()) + n.formulas = Lib.MkListV(sequence.GetFormula()) } else { n.followInstructions(sequence.GetInstructions(), sequence.GetFormula()) } @@ -236,8 +236,8 @@ func (n *Node) followInstructions(instructions []Instruction, form AST.Form) { // * It's the end of the CodeBlock, but not of the sequence. In this case, check if the following instruction matches with any child. if instr.IsEquivalent(current.value[oui]) { oui += 1 - if i == len(instructions)-1 && oui == len(current.value) && !current.formulae.Contains(form) { - current.formulae.Append(form) + if i == len(instructions)-1 && oui == len(current.value) && !Lib.ListMem(form, current.formulas) { + current.formulas.Append(form) } else if i < len(instructions)-1 && oui == len(current.value) { // If the instruction matches, then continue the algorithm with the child as the current node. @@ -252,7 +252,7 @@ func (n *Node) followInstructions(instructions []Instruction, form AST.Form) { } if !found { newNode := makeNode(instructions[i+1:]) - newNode.formulae = AST.NewFormList(form) + newNode.formulas = Lib.MkListV(form) current.children = append(current.children, newNode) break } @@ -263,13 +263,13 @@ func (n *Node) followInstructions(instructions []Instruction, form AST.Form) { // * The second one contains the remaining instructions of the sequence plus the formulae. child1 := makeNode(current.value[oui:]) child2 := makeNode(instructions[i:]) - child2.formulae = AST.NewFormList(form) + child2.formulas = Lib.MkListV(form) child1.children = current.children - child1.formulae = current.formulae + child1.formulas = current.formulas current.value = current.value[:oui] - current.formulae = AST.NewFormList() + current.formulas = Lib.NewList[AST.Form]() current.children = []*Node{child1, child2} break @@ -284,7 +284,7 @@ func (n *Node) followInstructions(instructions []Instruction, form AST.Form) { child1.children = current.children current.value = current.value[:oui] current.children = []*Node{child1} - current.formulae = AST.NewFormList(form.Copy()) + current.formulas = Lib.MkListV(form.Copy()) } } diff --git a/src/Unif/data_structure.go b/src/Unif/data_structure.go index 77aae7f3..763ae197 100644 --- a/src/Unif/data_structure.go +++ b/src/Unif/data_structure.go @@ -39,13 +39,14 @@ package Unif import ( "github.com/GoelandProver/Goeland/AST" + "github.com/GoelandProver/Goeland/Lib" ) type DataStructure interface { Print() IsEmpty() bool - MakeDataStruct(*AST.FormList, bool) DataStructure - InsertFormulaListToDataStructure(*AST.FormList) DataStructure + MakeDataStruct(Lib.List[AST.Form], bool) DataStructure + InsertFormulaListToDataStructure(Lib.List[AST.Form]) DataStructure Unify(AST.Form) (bool, []MatchingSubstitutions) Copy() DataStructure } diff --git a/src/Unif/matching.go b/src/Unif/matching.go index ce544e2c..c6c540bf 100644 --- a/src/Unif/matching.go +++ b/src/Unif/matching.go @@ -173,7 +173,7 @@ func (m *Machine) unifyAux(node Node) []MatchingSubstitutions { matching := []MatchingSubstitutions{} if node.isLeaf() { - for _, f := range node.formulae.Slice() { + for _, f := range node.formulas.GetSlice() { if reflect.TypeOf(f) == reflect.TypeOf(AST.Pred{}) || reflect.TypeOf(f) == reflect.TypeOf(TermForm{}) { // Rebuild final substitution between meta and subst final_subst := computeSubstitutions(CopySubstPairList(m.subst), m.meta.Copy(), f.Copy()) diff --git a/src/Unif/parsing.go b/src/Unif/parsing.go index 63393721..4907d8a8 100644 --- a/src/Unif/parsing.go +++ b/src/Unif/parsing.go @@ -53,7 +53,7 @@ func (t TermForm) ToMappedStringChild(mapping AST.MapString, displayTypes bool) } func (t TermForm) GetChildrenForMappedString() []AST.MappableString { - return t.GetChildFormulas().ToMappableStringSlice() + return AST.LsToMappableStringSlice(t.GetChildFormulas()) } func (t TermForm) GetTerm() AST.Term { return t.t.Copy() } @@ -68,8 +68,8 @@ func (t TermForm) GetIndex() int { return t.ind func (t TermForm) SubstituteVarByMeta(AST.Var, AST.Meta) AST.Form { return t } func (t TermForm) GetInternalMetas() Lib.List[AST.Meta] { return Lib.NewList[AST.Meta]() } func (t TermForm) SetInternalMetas(Lib.List[AST.Meta]) AST.Form { return t } -func (t TermForm) GetSubFormulasRecur() *AST.FormList { return AST.NewFormList() } -func (t TermForm) GetChildFormulas() *AST.FormList { return AST.NewFormList() } +func (t TermForm) GetSubFormulasRecur() Lib.List[AST.Form] { return Lib.NewList[AST.Form]() } +func (t TermForm) GetChildFormulas() Lib.List[AST.Form] { return Lib.NewList[AST.Form]() } func (t TermForm) Equals(t2 any) bool { switch nt := t2.(type) { diff --git a/src/main.go b/src/main.go index 07107474..dbe14218 100644 --- a/src/main.go +++ b/src/main.go @@ -206,7 +206,7 @@ func initDebuggers() { } func StatementListToFormula(statements []Core.Statement, old_bound int, problemDir string) (form AST.Form, bound int, containsEquality bool) { - and_list := AST.NewFormList() + and_list := Lib.NewList[AST.Form]() var not_form AST.Form bound = old_bound @@ -265,20 +265,20 @@ func StatementListToFormula(statements []Core.Statement, old_bound int, problemD } switch { - case and_list.IsEmpty() && not_form == nil: + case and_list.Empty() && not_form == nil: return nil, bound, containsEquality - case and_list.IsEmpty(): + case and_list.Empty(): return AST.MakerNot(not_form), bound, containsEquality case not_form == nil: return AST.MakerAnd(and_list), bound, containsEquality default: - flattened := and_list.Flatten() + flattened := AST.LsFlatten(and_list) flattened.Append(AST.MakerNot(not_form)) return AST.MakerAnd(flattened), bound, containsEquality } } -func doAxiomStatement(andList *AST.FormList, f AST.Form) *AST.FormList { +func doAxiomStatement(andList Lib.List[AST.Form], f AST.Form) Lib.List[AST.Form] { newForm := f.RenameVariables() // FIXME: dmt should be a plugin and therefore not checked here. From 4bad89baac06c3c1e97561d1bda2db2a292e7081 Mon Sep 17 00:00:00 2001 From: Johann Rosain Date: Sat, 7 Feb 2026 15:47:43 +0100 Subject: [PATCH 02/30] Upd: coq -> rocq in the output --- src/Mods/rocq/proof.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Mods/rocq/proof.go b/src/Mods/rocq/proof.go index b4fe0286..0d1d1bb0 100644 --- a/src/Mods/rocq/proof.go +++ b/src/Mods/rocq/proof.go @@ -108,7 +108,7 @@ func makeStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], constantsCre case Lib.Some[int]: actualTarget = t.Val case Lib.None[int]: - Glob.Anomaly("coq", fmt.Sprintf( + Glob.Anomaly("rocq", fmt.Sprintf( "Index of %s not found in %s", proof.GetTargetForm().ToString(), Lib.ListToString(hypotheses, ", ", "[]"), @@ -220,7 +220,7 @@ func rewriteStep(rewriteRule AST.Form, hypotheses Lib.List[AST.Form], target int case Lib.Some[int]: actualIndex = i.Val case Lib.None[int]: - Glob.Anomaly("coq", fmt.Sprintf( + Glob.Anomaly("rocq", fmt.Sprintf( "Index of %s not found in %s", rewriteRule.ToString(), Lib.ListToString(hypotheses, ", ", "[]"), @@ -266,7 +266,7 @@ func makeImpChain(forms Lib.List[AST.Form]) AST.Form { return form } -// Introduces a new formula in coq's hypotheses. +// Introduces a new formula in rocq's hypotheses. func introduce(f AST.Form, hypotheses Lib.List[AST.Form]) (int, Lib.List[AST.Form]) { index := hypotheses.Len() hypotheses.Append(f) @@ -365,7 +365,7 @@ func cleanHypotheses(hypotheses Lib.List[AST.Form], form AST.Form) (string, []Li case Lib.Some[int]: actualIndex = i.Val case Lib.None[int]: - Glob.Anomaly("coq", fmt.Sprintf( + Glob.Anomaly("rocq", fmt.Sprintf( "Index of %s not found in %s", form.ToString(), Lib.ListToString(hypotheses, ", ", "[]"), From 037d198b2b86b97e79fcaeb7780be062b20bb0a0 Mon Sep 17 00:00:00 2001 From: Johann Rosain Date: Sat, 7 Feb 2026 17:17:46 +0100 Subject: [PATCH 03/30] Fix: avoid keeping formulas in GS3 sequent structure to use less memory --- src/Lib/list.go | 4 ++++ src/Mods/gs3/proof.go | 13 ++++------- src/Mods/gs3/sequent.go | 49 ++++++++++------------------------------- 3 files changed, 20 insertions(+), 46 deletions(-) diff --git a/src/Lib/list.go b/src/Lib/list.go index 9788610b..f8460371 100644 --- a/src/Lib/list.go +++ b/src/Lib/list.go @@ -212,6 +212,10 @@ func (l List[T]) RemoveAt(index int) List[T] { return new_list } +func (l List[T]) Clear() { + l.values = nil +} + func ToStrictlyOrderedList[T StrictlyOrdered](l List[T]) StrictlyOrderedList[T] { return StrictlyOrderedList[T]{values: l} } diff --git a/src/Mods/gs3/proof.go b/src/Mods/gs3/proof.go index abc5f848..551ff2c7 100644 --- a/src/Mods/gs3/proof.go +++ b/src/Mods/gs3/proof.go @@ -175,7 +175,6 @@ func (gs GS3Proof) makeProof(proof []Search.ProofStruct) *GS3Sequent { // Returns a sequent and the result formulas. func (gs *GS3Proof) makeProofOneStep(proofStep Search.ProofStruct, parent *GS3Sequent) []Lib.List[AST.Form] { seq := MakeNewSequent() - seq.setHypotheses(gs.branchForms) seq.nodeId = proofStep.Node_id rule := proofStructRuleToGS3Rule(proofStep.GetRuleName()) @@ -186,7 +185,7 @@ func (gs *GS3Proof) makeProofOneStep(proofStep Search.ProofStruct, parent *GS3Se // Immediate, just apply the rule. case NNOT, NOR, NIMP, AND, NAND, NEQU, OR, IMP, EQU, AX, REWRITE: seq.setAppliedRule(rule) - seq.setAppliedOn(form) + seq.SetTargetForm(form) if rule == REWRITE { seq.setRewrittenWith(proofStep.Id_dmt) } @@ -248,9 +247,8 @@ func (gs *GS3Proof) manageGammaStep(proofStep Search.ProofStruct, rule Rule, seq // Create all the next sequents needed. s := MakeNewSequent() - s.setHypotheses(gs.branchForms) s.setAppliedRule(rule) - s.setAppliedOn(originForm) + s.SetTargetForm(originForm) s.setTermGenerated(term) if seq.IsEmpty() { @@ -427,9 +425,8 @@ func (gs *GS3Proof) weakenForms(forms Lib.List[AST.Form], parent *GS3Sequent) *G func (gs *GS3Proof) weakenForm(form AST.Form) *GS3Sequent { seq := MakeNewSequent() - seq.setHypotheses(gs.branchForms) seq.setAppliedRule(W) - seq.setAppliedOn(form) + seq.SetTargetForm(form) gs.removeHypothesis(form) gs.removeDependency(form) @@ -442,7 +439,6 @@ func (gs *GS3Proof) weakenForm(form AST.Form) *GS3Sequent { func (gs *GS3Proof) weakenTerm(term AST.Term) *GS3Sequent { seq := MakeNewSequent() - seq.setHypotheses(gs.branchForms) seq.setAppliedRule(W) seq.setTermGenerated(term) @@ -494,9 +490,8 @@ func (gs *GS3Proof) removeRuleAppliedOn(form AST.Form) { func (gs *GS3Proof) applyDeltaRule(form, result AST.Form, rule Rule, term AST.Term, nodeId int) *GS3Sequent { seq := MakeNewSequent() - seq.setHypotheses(gs.branchForms) seq.setAppliedRule(rule) - seq.setAppliedOn(form) + seq.SetTargetForm(form) seq.setTermGenerated(term) seq.setFormsGenerated([]Lib.List[AST.Form]{Lib.MkListV(result)}) diff --git a/src/Mods/gs3/sequent.go b/src/Mods/gs3/sequent.go index 88fb3a32..aa1d3d5c 100644 --- a/src/Mods/gs3/sequent.go +++ b/src/Mods/gs3/sequent.go @@ -37,13 +37,13 @@ import ( "github.com/GoelandProver/Goeland/AST" "github.com/GoelandProver/Goeland/Glob" "github.com/GoelandProver/Goeland/Lib" + "github.com/GoelandProver/Goeland/Mods/dmt" ) type GS3Sequent struct { - hypotheses Lib.List[AST.Form] rule Rule - appliedOn int - rewriteWith int + appliedOn AST.Form + rewriteWith AST.Form termGenerated AST.Term formsGenerated []Lib.List[AST.Form] children []*GS3Sequent @@ -77,7 +77,6 @@ const ( func MakeNewSequent() *GS3Sequent { seq := new(GS3Sequent) - seq.hypotheses = Lib.NewList[AST.Form]() seq.children = make([]*GS3Sequent, 0) return seq } @@ -103,7 +102,7 @@ func IsAlphaRule(rule Rule) bool { // ---------------------------------------------------------------------------- func (seq *GS3Sequent) GetTargetForm() AST.Form { - return seq.hypotheses.At(seq.appliedOn) + return seq.appliedOn } func (seq *GS3Sequent) Child(i int) *GS3Sequent { @@ -137,7 +136,7 @@ func (seq *GS3Sequent) TermGenerated() AST.Term { } func (seq *GS3Sequent) IsEmpty() bool { - return seq.hypotheses.Empty() + return seq.appliedOn == nil } func (seq *GS3Sequent) ToString() string { @@ -145,7 +144,7 @@ func (seq *GS3Sequent) ToString() string { } func (seq *GS3Sequent) GetRewriteWith() AST.Form { - return seq.hypotheses.At(seq.rewriteWith) + return seq.rewriteWith } func (seq *GS3Sequent) GetId() int { @@ -165,7 +164,7 @@ func (seq *GS3Sequent) SetChildren(c []*GS3Sequent) { } func (seq *GS3Sequent) SetTargetForm(f AST.Form) { - seq.hypotheses.Upd(seq.appliedOn, f) + seq.appliedOn = f } func (seq *GS3Sequent) SetTermGenerated(t AST.Term) { @@ -176,35 +175,10 @@ func (seq *GS3Sequent) SetTermGenerated(t AST.Term) { // Private methods & functions // ---------------------------------------------------------------------------- -func (seq *GS3Sequent) setHypotheses(forms Lib.List[AST.Form]) { - seq.hypotheses = Lib.ListCpy(forms) - // If equality reasoning has been used to terminate the proof, then an empty predicate is expected - // (see search_destructive, manageClosureRule on eq reasoning). - // As such, add an hypothesis with the empty = - seq.hypotheses.Append(AST.EmptyPredEq) -} - func (seq *GS3Sequent) setAppliedRule(rule Rule) { seq.rule = rule } -func (seq *GS3Sequent) setAppliedOn(hypothesis AST.Form) { - index := -1 - for i, h := range seq.hypotheses.GetSlice() { - if hypothesis.Equals(h) { - index = i - break - } - } - - if index == -1 { - Glob.PrintInfo("APPLIED ON", hypothesis.ToString()) - Glob.Anomaly("GS3", "Failure: tried to apply a missing hypothesis") - } - - seq.appliedOn = index -} - func (seq *GS3Sequent) setTermGenerated(t AST.Term) { seq.termGenerated = t } @@ -215,7 +189,7 @@ func (seq *GS3Sequent) addChild(oth ...*GS3Sequent) { func (seq *GS3Sequent) toStringAux(i int) string { identation := strings.Repeat(" ", i) - status := seq.ruleToString(seq.rule) + " on " + seq.hypotheses.At(seq.appliedOn).ToString() + status := seq.ruleToString(seq.rule) + " on " + seq.appliedOn.ToString() if seq.IsEmpty() { status = "EMPTY" } @@ -298,19 +272,20 @@ func ruleToTableauxString(rule Rule) string { } func (seq *GS3Sequent) setRewrittenWith(rewriteId int) { - for i, h := range seq.hypotheses.GetSlice() { + axioms := dmt.GetRegisteredAxioms() + for _, h := range axioms.GetSlice() { endForm := h for Glob.Is[AST.All](endForm) { endForm = endForm.(AST.All).GetForm() } endForm = getAtomic(endForm) if endForm.GetIndex() == rewriteId { - seq.rewriteWith = i + seq.rewriteWith = h return } } - panic("Failure: tried to rewrite using a missing hypothesis") + panic("Failure: tried to rewrite using a missing axiom") } func getAtomic(f AST.Form) AST.Form { From 09303f728898d0089dd529a770300dac1027f1e1 Mon Sep 17 00:00:00 2001 From: Johann Rosain Date: Sun, 20 Jul 2025 21:41:14 +0200 Subject: [PATCH 04/30] Removal of invasive type system --- src/AST/formsDef.go | 242 +------ src/AST/formula.go | 14 - src/AST/maker.go | 45 +- src/AST/quantifiers.go | 37 +- src/AST/term.go | 115 +--- src/AST/termsDef.go | 84 +-- src/Core/Sko/inner-skolemization.go | 4 +- src/Core/Sko/interface.go | 33 +- src/Core/Sko/outer-skolemization.go | 4 +- src/Core/Sko/preinner-skolemization.go | 14 +- src/Core/instanciation.go | 2 +- src/Core/rules_type.go | 5 +- src/Core/substitutions_search.go | 12 - src/Engine/pretyper.go | 6 +- src/Engine/syntax-translation.go | 25 +- .../equality/bse/equality_problem_list.go | 2 - src/Mods/equality/bse/equality_types.go | 12 +- src/Mods/equality/sateq/subsgatherer.go | 2 +- src/Mods/equality/sateq/termrep.go | 4 - src/Mods/gs3/dependency.go | 4 - src/Mods/lambdapi/context.go | 30 +- src/Mods/lambdapi/formDecorator.go | 2 +- src/Mods/lambdapi/proof.go | 18 +- src/Mods/rocq/context.go | 11 +- src/Search/rules.go | 5 - src/Typing/apply_rules.go | 310 ++++----- src/Typing/contexts.go | 614 +++++++++--------- src/Typing/form_rules.go | 400 ++++++------ src/Typing/launch_rules.go | 286 ++++---- src/Typing/prooftree_dump.go | 234 +++---- src/Typing/rules.go | 404 ++++++------ src/Typing/term_rules.go | 363 +++++------ src/Typing/type.go | 318 +++++---- src/Typing/type_rules.go | 372 +++++------ src/Typing/wf_rules.go | 60 +- src/Unif/matching.go | 11 +- src/Unif/parsing.go | 30 +- src/Unif/substitutions_type.go | 6 +- src/main.go | 16 +- 39 files changed, 1789 insertions(+), 2367 deletions(-) diff --git a/src/AST/formsDef.go b/src/AST/formsDef.go index e8b55413..55ff9ba5 100644 --- a/src/AST/formsDef.go +++ b/src/AST/formsDef.go @@ -119,10 +119,6 @@ func (a All) RenameVariables() Form { return All{a.quantifier.renameVariables()} } -func (a All) ReplaceTypeByMeta(varList []TypeVar, index int) Form { - return All{a.quantifier.replaceTypeByMeta(varList, index)} -} - func (a All) ReplaceTermByTerm(old Term, new Term) (Form, bool) { quant, isReplaced := a.quantifier.replaceTermByTerm(old, new) return All{quant}, isReplaced @@ -175,10 +171,6 @@ func (e Ex) RenameVariables() Form { return Ex{e.quantifier.renameVariables()} } -func (e Ex) ReplaceTypeByMeta(varList []TypeVar, index int) Form { - return Ex{e.quantifier.replaceTypeByMeta(varList, index)} -} - func (e Ex) ReplaceTermByTerm(old Term, new Term) (Form, bool) { quant, isReplaced := e.quantifier.replaceTermByTerm(old, new) return Ex{quant}, isReplaced @@ -192,138 +184,6 @@ func (e Ex) ReplaceMetaByTerm(meta Meta, term Term) Form { return Ex{e.quantifier.replaceMetaByTerm(meta, term)} } -// ----------------------------------------------------------------------------- -// Π-types - -type AllType struct { - *MappedString - index int - tvList []TypeVar - form Form - metas Lib.Cache[Lib.Set[Meta], AllType] -} - -func MakeAllTypeSimple( - i int, - typeVars []TypeVar, - form Form, - metas Lib.Set[Meta], -) AllType { - fms := &MappedString{} - at := AllType{ - fms, - i, - typeVars, - form, - Lib.MkCache(metas, AllType.forceGetMetas), - } - fms.MappableString = &at - return at -} - -func MakeAllType(i int, typeVars []TypeVar, form Form) AllType { - return MakeAllTypeSimple(i, typeVars, form, Lib.EmptySet[Meta]()) -} - -func MakerAllType(typeVars []TypeVar, form Form) AllType { - return MakeAllType(MakerIndexFormula(), typeVars, form) -} - -/* Methods */ - -func (a AllType) GetIndex() int { return a.index } -func (a AllType) GetVarList() []TypeVar { return copyTypeVarList(a.tvList) } -func (a AllType) GetForm() Form { return a.form.Copy() } -func (a AllType) GetType() TypeScheme { return DefaultPropType(0) } - -/* Form interface */ - -func (a AllType) ToMappedString(mapping MapString, displayTypes bool) string { - return mapping[QuantVarOpen] + Glob.ListToString(a.GetVarList(), ", ", "") + " : " + mapping[TypeVarType] + mapping[QuantVarClose] + mapping[QuantVarSep] + " (" + a.GetForm().ToString() + ")" -} - -func (a AllType) ToString() string { - return a.MappedString.ToString() -} - -func (a AllType) ToMappedStringSurround(mapping MapString, displayTypes bool) string { - return "(" + mapping[AllTypeQuant] + " " + mapping[QuantVarOpen] + Glob.ListToString(a.GetVarList(), ", ", "") + " : " + mapping[TypeVarType] + mapping[QuantVarClose] + mapping[QuantVarSep] + " (%s))" -} - -func (a AllType) ToMappedStringChild(mapping MapString, displayTypes bool) (separator, emptyValue string) { - return "", "" -} - -func (a AllType) GetChildrenForMappedString() []MappableString { - return LsToMappableStringSlice(a.GetChildFormulas()) -} - -func (a AllType) forceGetMetas() Lib.Set[Meta] { - return a.GetForm().GetMetas() -} - -func (a AllType) GetMetas() Lib.Set[Meta] { - return a.metas.Get(a) -} - -func (a AllType) Copy() Form { - fms := &MappedString{} - at := AllType{ - fms, - a.index, - copyTypeVarList(a.tvList), - a.form.Copy(), - a.metas.Copy(Lib.Set[Meta].Copy), - } - fms.MappableString = &at - return at -} - -func (a AllType) Equals(f any) bool { - oth, isAll := f.(AllType) - return isAll && - AreEqualsTypeVarList(a.tvList, oth.tvList) && - a.form.Equals(oth.form) -} - -func (a AllType) ReplaceTypeByMeta(varList []TypeVar, index int) Form { - return MakeAllType(a.GetIndex(), a.tvList, a.GetForm().ReplaceTypeByMeta(varList, index)) -} - -func (a AllType) ReplaceTermByTerm(old Term, new Term) (Form, bool) { - f, res := a.GetForm().ReplaceTermByTerm(old, new) - na := MakeAllTypeSimple(a.GetIndex(), a.GetVarList(), f, a.metas.Raw()) - if !res && !a.metas.NeedsUpd() { - na.metas.AvoidUpd() - } - return na, res -} - -func (a AllType) RenameVariables() Form { - return MakeAllType(a.GetIndex(), a.GetVarList(), a.GetForm().RenameVariables()) -} - -func (a AllType) GetSubTerms() Lib.List[Term] { - return a.GetForm().GetSubTerms() -} - -func (a AllType) SubstituteVarByMeta(old Var, new Meta) Form { - f := a.GetForm().SubstituteVarByMeta(old, new) - return MakeAllTypeSimple(a.index, a.tvList, f, a.metas.Raw()) -} - -func (a AllType) GetSubFormulasRecur() Lib.List[Form] { - return getAllSubFormulasAppended(a) -} - -func (a AllType) GetChildFormulas() Lib.List[Form] { - return Lib.MkListV(a.GetForm()) -} - -func (e AllType) ReplaceMetaByTerm(meta Meta, term Term) Form { - return MakeAllType(e.GetIndex(), e.GetVarList(), e.GetForm().ReplaceMetaByTerm(meta, term)) -} - // ----------------------------------------------------------------------------- // Or @@ -367,10 +227,6 @@ func (o Or) GetMetas() Lib.Set[Meta] { return o.metas.Get(o) } -func (o Or) GetType() TypeScheme { - return DefaultPropType(0) -} - func (o Or) GetSubTerms() Lib.List[Term] { res := Lib.NewList[Term]() @@ -414,10 +270,6 @@ func (o Or) GetChildrenForMappedString() []MappableString { return LsToMappableStringSlice(o.GetChildFormulas()) } -func (o Or) ReplaceTypeByMeta(varList []TypeVar, index int) Form { - return MakeOr(o.GetIndex(), replaceList(o.forms, varList, index)) -} - func (o Or) ReplaceTermByTerm(old Term, new Term) (Form, bool) { formList, res := replaceTermInFormList(o.forms, old, new) no := MakeOrSimple(o.GetIndex(), formList, o.metas.Raw()) @@ -508,10 +360,6 @@ func (a And) GetMetas() Lib.Set[Meta] { return a.metas.Get(a) } -func (a And) GetType() TypeScheme { - return DefaultPropType(0) -} - func (a And) GetSubTerms() Lib.List[Term] { res := Lib.NewList[Term]() @@ -558,10 +406,6 @@ func (a And) GetChildrenForMappedString() []MappableString { return LsToMappableStringSlice(a.GetChildFormulas()) } -func (a And) ReplaceTypeByMeta(varList []TypeVar, index int) Form { - return MakeAnd(a.GetIndex(), replaceList(a.forms, varList, index)) -} - func (a And) ReplaceTermByTerm(old Term, new Term) (Form, bool) { varList, res := replaceTermInFormList(a.forms, old, new) na := MakeAndSimple(a.index, varList, a.metas.Raw()) @@ -662,8 +506,7 @@ func (e Equ) GetMetas() Lib.Set[Meta] { return e.metas.Get(e) } -func (e Equ) GetType() TypeScheme { return DefaultPropType(0) } -func (e Equ) ToString() string { return e.ToMappedString(DefaultMapString, true) } +func (e Equ) ToString() string { return e.ToMappedString(DefaultMapString, true) } func (e Equ) Equals(f any) bool { oth, isEqu := f.(Equ) @@ -671,10 +514,6 @@ func (e Equ) Equals(f any) bool { e.f1.Equals(oth.f1) && e.f2.Equals(oth.f2) } -func (e Equ) ReplaceTypeByMeta(varList []TypeVar, index int) Form { - return MakeEqu(e.GetIndex(), e.GetF1().ReplaceTypeByMeta(varList, index), e.GetF2().ReplaceTypeByMeta(varList, index)) -} - func (e Equ) ReplaceTermByTerm(old Term, new Term) (Form, bool) { f1, res1 := e.GetF1().ReplaceTermByTerm(old, new) f2, res2 := e.GetF2().ReplaceTermByTerm(old, new) @@ -785,8 +624,7 @@ func (i Imp) GetMetas() Lib.Set[Meta] { return i.metas.Get(i) } -func (i Imp) GetType() TypeScheme { return DefaultPropType(0) } -func (i Imp) ToString() string { return i.ToMappedString(DefaultMapString, true) } +func (i Imp) ToString() string { return i.ToMappedString(DefaultMapString, true) } func (i Imp) Equals(other any) bool { if typed, ok := other.(Imp); ok { @@ -796,10 +634,6 @@ func (i Imp) Equals(other any) bool { return false } -func (i Imp) ReplaceTypeByMeta(varList []TypeVar, index int) Form { - return MakeImp(i.GetIndex(), i.GetF1().ReplaceTypeByMeta(varList, index), i.GetF2().ReplaceTypeByMeta(varList, index)) -} - func (i Imp) ReplaceTermByTerm(old Term, new Term) (Form, bool) { f1, res1 := i.GetF1().ReplaceTermByTerm(old, new) f2, res2 := i.GetF2().ReplaceTermByTerm(old, new) @@ -884,10 +718,6 @@ func (n Not) GetMetas() Lib.Set[Meta] { return n.metas.Get(n) } -func (n Not) GetType() TypeScheme { - return DefaultPropType(0) -} - func (n Not) GetSubTerms() Lib.List[Term] { return n.GetForm().GetSubTerms() } @@ -924,10 +754,6 @@ func (n Not) GetChildrenForMappedString() []MappableString { return LsToMappableStringSlice(n.GetChildFormulas()) } -func (n Not) ReplaceTypeByMeta(varList []TypeVar, index int) Form { - return MakeNot(n.GetIndex(), n.f.ReplaceTypeByMeta(varList, index)) -} - func (n Not) ReplaceTermByTerm(old Term, new Term) (Form, bool) { f, res := n.f.ReplaceTermByTerm(old, new) @@ -998,37 +824,24 @@ func getDeepFormWithoutNot(form Form, isEven bool) (Form, bool) { type Pred struct { *MappedString - index int - id Id - args Lib.List[Term] - typeVars []TypeApp - typeHint TypeScheme - metas Lib.Cache[Lib.Set[Meta], Pred] + index int + id Id + args Lib.List[Term] + metas Lib.Cache[Lib.Set[Meta], Pred] } func MakePredSimple( index int, id Id, terms Lib.List[Term], - typeApps []TypeApp, metas Lib.Set[Meta], - typeSchemes ...TypeScheme, ) Pred { - var ts TypeScheme - // FIXME: this condition is very suspect - if len(typeSchemes) == 1 { - ts = typeSchemes[0] - } else { - ts = DefaultPropType(terms.Len()) - } fms := &MappedString{} pred := Pred{ fms, index, id, terms, - typeApps, - ts, Lib.MkCache(metas, Pred.forceGetMetas), } fms.MappableString = &pred @@ -1039,26 +852,20 @@ func MakePred( index int, id Id, terms Lib.List[Term], - typeApps []TypeApp, - typeSchemes ...TypeScheme, ) Pred { return MakePredSimple( index, id, terms, - typeApps, Lib.EmptySet[Meta](), - typeSchemes..., ) } func MakerPred( id Id, terms Lib.List[Term], - typeApps []TypeApp, - typeSchemes ...TypeScheme, ) Pred { - return MakePred(MakerIndexFormula(), id, terms, typeApps, typeSchemes...) + return MakePred(MakerIndexFormula(), id, terms) } /* Pred attributes getters */ @@ -1066,11 +873,9 @@ func MakerPred( func (p Pred) GetIndex() int { return p.index } func (p Pred) GetID() Id { return p.id.Copy().(Id) } func (p Pred) GetArgs() Lib.List[Term] { return p.args } -func (p Pred) GetTypeVars() []TypeApp { return CopyTypeAppList(p.typeVars) } /* Formula methods */ -func (p Pred) GetType() TypeScheme { return p.typeHint } func (p Pred) RenameVariables() Form { return p } func (p Pred) ToString() string { @@ -1078,16 +883,11 @@ func (p Pred) ToString() string { } func (p Pred) ToMappedStringSurround(mapping MapString, displayTypes bool) string { - if len(p.typeVars) == 0 && p.GetArgs().Len() == 0 { + if p.GetArgs().Len() == 0 { return p.GetID().ToMappedString(mapping, displayTypes) + "%s" } args := []string{} - if len(p.typeVars) > 0 { - if tv := Glob.ListToString(p.typeVars, ", ", mapping[PredEmpty]); tv != "" { - args = append(args, tv) - } - } args = append(args, "%s") if p.GetID().GetName() == "=" { @@ -1115,9 +915,7 @@ func (p Pred) Copy() Form { p.index, p.id, p.GetArgs(), - CopyTypeAppList(p.GetTypeVars()), p.metas.Raw().Copy(), - p.GetType(), ) if !p.metas.NeedsUpd() { @@ -1129,10 +927,7 @@ func (p Pred) Copy() Form { func (p Pred) Equals(other any) bool { if typed, ok := other.(Pred); ok { - return typed.id.Equals(p.id) && - Lib.ComparableList[TypeApp](p.typeVars).Equals(typed.typeVars) && - Lib.ListEquals(typed.args, p.args) && - p.typeHint.Equals(typed.typeHint) + return typed.id.Equals(p.id) && Lib.ListEquals(typed.args, p.args) } return false @@ -1167,15 +962,6 @@ func (p Pred) GetMetaList() Lib.List[Meta] { return metas } -func (p Pred) ReplaceTypeByMeta(varList []TypeVar, index int) Form { - return MakePred( - p.GetIndex(), - p.GetID(), - replaceTermListTypesByMeta(p.GetArgs(), varList, index), - instanciateTypeAppList(p.typeVars, varList, index), p.GetType(), - ) -} - func (p Pred) ReplaceTermByTerm(old Term, new Term) (Form, bool) { termList, res := replaceTermInTermList(p.GetArgs(), old, new) @@ -1183,9 +969,7 @@ func (p Pred) ReplaceTermByTerm(old Term, new Term) (Form, bool) { p.GetIndex(), p.GetID(), termList, - p.GetTypeVars(), p.metas.Raw(), - p.GetType(), ) if !res && !p.metas.NeedsUpd() { @@ -1216,9 +1000,7 @@ func (p Pred) SubstituteVarByMeta(old Var, new Meta) Form { nf.index, nf.id, nf.args, - nf.typeVars, nf.metas.Raw(), - nf.typeHint, ) } return nf @@ -1249,7 +1031,7 @@ func (p Pred) ReplaceMetaByTerm(meta Meta, term Term) Form { } } - return MakePred(p.GetIndex(), p.id, newTerms, p.typeVars, p.GetType()) + return MakePred(p.GetIndex(), p.id, newTerms) } // ----------------------------------------------------------------------------- @@ -1283,11 +1065,9 @@ func (t Top) GetChildrenForMappedString() []MappableString { return LsToMappableStringSlice(t.GetChildFormulas()) } -func (t Top) GetType() TypeScheme { return DefaultPropType(0) } func (t Top) Copy() Form { return MakeTop(t.GetIndex()) } func (Top) Equals(f any) bool { _, isTop := f.(Top); return isTop } func (Top) GetMetas() Lib.Set[Meta] { return Lib.EmptySet[Meta]() } -func (t Top) ReplaceTypeByMeta([]TypeVar, int) Form { return MakeTop(t.GetIndex()) } func (t Top) ReplaceTermByTerm(Term, Term) (Form, bool) { return MakeTop(t.GetIndex()), false } func (t Top) RenameVariables() Form { return MakeTop(t.GetIndex()) } func (t Top) GetIndex() int { return t.index } @@ -1327,11 +1107,9 @@ func (b Bot) GetChildrenForMappedString() []MappableString { return LsToMappableStringSlice(b.GetChildFormulas()) } -func (b Bot) GetType() TypeScheme { return DefaultPropType(0) } func (b Bot) Copy() Form { return MakeBot(b.GetIndex()) } func (Bot) Equals(f any) bool { _, isBot := f.(Bot); return isBot } func (Bot) GetMetas() Lib.Set[Meta] { return Lib.EmptySet[Meta]() } -func (b Bot) ReplaceTypeByMeta([]TypeVar, int) Form { return MakeBot(b.GetIndex()) } func (b Bot) ReplaceTermByTerm(Term, Term) (Form, bool) { return MakeBot(b.GetIndex()), false } func (b Bot) RenameVariables() Form { return MakeBot(b.GetIndex()) } func (b Bot) GetIndex() int { return b.index } diff --git a/src/AST/formula.go b/src/AST/formula.go index 0b50c2f6..0a1b37d5 100644 --- a/src/AST/formula.go +++ b/src/AST/formula.go @@ -46,7 +46,6 @@ import ( type Form interface { GetIndex() int GetMetas() Lib.Set[Meta] - GetType() TypeScheme GetSubTerms() Lib.List[Term] GetSubFormulasRecur() Lib.List[Form] GetChildFormulas() Lib.List[Form] @@ -54,7 +53,6 @@ type Form interface { Lib.Copyable[Form] MappableString - ReplaceTypeByMeta([]TypeVar, int) Form ReplaceTermByTerm(old Term, new Term) (Form, bool) RenameVariables() Form SubstituteVarByMeta(old Var, new Meta) Form @@ -92,8 +90,6 @@ func replaceTermInTermList( newTermList.Upd(i, MakerFun( nf.GetP(), termList, - nf.GetTypeVars(), - nf.GetTypeHint(), )) res = res || r } @@ -142,16 +138,6 @@ func metasUnion(forms Lib.List[Form]) Lib.Set[Meta] { return res } -func replaceList(oldForms Lib.List[Form], vars []TypeVar, index int) Lib.List[Form] { - newForms := Lib.MkList[Form](oldForms.Len()) - - for i, form := range oldForms.GetSlice() { - newForms.Upd(i, form.ReplaceTypeByMeta(vars, index)) - } - - return newForms -} - // Returns whether the term has been replaced in a subformula or not func replaceTermInFormList(oldForms Lib.List[Form], oldTerm Term, newTerm Term) (Lib.List[Form], bool) { newForms := Lib.MkList[Form](oldForms.Len()) diff --git a/src/AST/maker.go b/src/AST/maker.go index 1289206e..a514c277 100644 --- a/src/AST/maker.go +++ b/src/AST/maker.go @@ -68,12 +68,11 @@ func Init() { Reset() initTypes() Id_eq = MakerId("=") - EmptyPredEq = MakerPred(Id_eq, Lib.NewList[Term](), make([]TypeApp, 0)) + EmptyPredEq = MakerPred(Id_eq, Lib.NewList[Term]()) // Eq/Neq types - tv := MkTypeVar("α") - scheme := MkQuantifiedType([]TypeVar{tv}, MkTypeArrow(MkTypeCross(tv, tv), tv)) - SavePolymorphScheme(Id_eq.GetName(), scheme) + // FIXME: Register the type of equality in the global context + // --- (call an internal function like SaveEqType()) initDefaultMap() } @@ -113,28 +112,28 @@ func MakerNewId(s string) Id { } /* Var maker */ -func MakerVar(s string, t ...TypeApp) Var { +func MakerVar(s string) Var { lock_term.Lock() i, ok := idVar[s] lock_term.Unlock() if ok { - return MakeVar(i, s, getType(t)) + return MakeVar(i, s) } else { - return MakerNewVar(s, getType(t)) + return MakerNewVar(s) } } -func MakerNewVar(s string, t ...TypeApp) Var { +func MakerNewVar(s string) Var { lock_term.Lock() idVar[s] = cpt_term - vr := MakeVar(cpt_term, s, getType(t)) + vr := MakeVar(cpt_term, s) cpt_term += 1 lock_term.Unlock() return vr } /* Meta maker */ -func MakerMeta(s string, formula int, t ...TypeApp) Meta { +func MakerMeta(s string, formula int) Meta { lock_term.Lock() i, ok := occurenceMeta[s] lock_term.Unlock() @@ -144,39 +143,25 @@ func MakerMeta(s string, formula int, t ...TypeApp) Meta { new_index := cpt_term cpt_term += 1 lock_term.Unlock() - return MakeMeta(new_index, i, s, formula, getType(t)) + return MakeMeta(new_index, i, s, formula) } else { lock_term.Lock() occurenceMeta[s] = 1 new_index := cpt_term cpt_term += 1 lock_term.Unlock() - return MakeMeta(new_index, 0, s, formula, getType(t)) + return MakeMeta(new_index, 0, s, formula) } } /* Const maker (given a id, create a fun without args) */ -func MakerConst(id Id, t ...TypeApp) Fun { - return MakeFun(id, Lib.NewList[Term](), []TypeApp{}, getType(t).(TypeScheme), Lib.EmptySet[Meta]()) +func MakerConst(id Id) Fun { + return MakeFun(id, Lib.NewList[Term](), Lib.EmptySet[Meta]()) } /* Fun maker, with given id and args */ -func MakerFun(id Id, terms Lib.List[Term], typeVars []TypeApp, t ...TypeScheme) Fun { - var ts TypeScheme - if len(t) == 1 { - ts = t[0] - } else { - ts = DefaultFunType(terms.Len()) - } - return MakeFun(id, terms, typeVars, ts, Lib.EmptySet[Meta]()) -} - -func getType(t []TypeApp) TypeApp { - if len(t) == 1 { - return t[0] - } else { - return DefaultType() - } +func MakerFun(id Id, terms Lib.List[Term]) Fun { + return MakeFun(id, terms, Lib.EmptySet[Meta]()) } /* Index make for formula */ diff --git a/src/AST/quantifiers.go b/src/AST/quantifiers.go index 6872063e..e6d3e009 100644 --- a/src/AST/quantifiers.go +++ b/src/AST/quantifiers.go @@ -40,7 +40,6 @@ import ( "fmt" "strings" - "github.com/GoelandProver/Goeland/Glob" "github.com/GoelandProver/Goeland/Lib" ) @@ -109,33 +108,11 @@ func ChangeVarSeparator(sep string) string { } func (q quantifier) ToMappedStringSurround(mapping MapString, displayTypes bool) string { - type VarType struct { - vars []Var - type_ TypeApp - } - - varsType := []VarType{} - for _, v := range q.GetVarList() { - found := false - for _, vt := range varsType { - if vt.type_.Equals(v.GetTypeApp()) { - vt.vars = append(vt.vars, v) - found = true - } - } - if !found { - varsType = append(varsType, VarType{[]Var{v}, v.GetTypeApp()}) - } - } - varStrings := []string{} - for _, vt := range varsType { + for _ = range q.GetVarList() { str := mapping[QuantVarOpen] str += ListToMappedString(q.GetVarList(), varSeparator, "", mapping, false) - if displayTypes || Glob.IsRocqOutput() { - str += " : " + vt.type_.ToString() - } varStrings = append(varStrings, str+mapping[QuantVarClose]) } @@ -178,16 +155,6 @@ func (q quantifier) copy() quantifier { return nq } -func (q quantifier) replaceTypeByMeta(varList []TypeVar, index int) quantifier { - return makeQuantifier( - q.GetIndex(), - q.GetVarList(), - q.GetForm().ReplaceTypeByMeta(varList, index), - q.metas.Raw().Copy(), - q.symbol, - ) -} - func (q quantifier) replaceTermByTerm(old Term, new Term) (quantifier, bool) { f, res := q.GetForm().ReplaceTermByTerm(old, new) return makeQuantifier( @@ -205,7 +172,7 @@ func (q quantifier) renameVariables() quantifier { for _, v := range q.GetVarList() { newVar := MakerNewVar(v.GetName()) - newVar = MakerVar(fmt.Sprintf("%s%d", newVar.GetName(), newVar.GetIndex()), v.typeHint) + newVar = MakerVar(fmt.Sprintf("%s%d", newVar.GetName(), newVar.GetIndex())) newVarList = append(newVarList, newVar) newForm, _ = newForm.RenameVariables().ReplaceTermByTerm(v, newVar) } diff --git a/src/AST/term.go b/src/AST/term.go index 4ebc116a..6b4160d6 100644 --- a/src/AST/term.go +++ b/src/AST/term.go @@ -37,7 +37,6 @@ package AST import ( - "github.com/GoelandProver/Goeland/Glob" "github.com/GoelandProver/Goeland/Lib" ) @@ -57,11 +56,6 @@ type Term interface { Less(any) bool } -type TypedTerm interface { - GetTypeHint() TypeScheme - GetTypeApp() TypeApp -} - /*** Makers ***/ func MakeId(i int, s string) Id { fms := &MappedString{} @@ -77,123 +71,28 @@ func MakeQuotedId(i int, s string) Id { return id } -func MakeVar(i int, s string, t ...TypeApp) Var { +func MakeVar(i int, s string) Var { fms := &MappedString{} - newVar := Var{fms, i, s, getType(t)} + newVar := Var{fms, i, s} fms.MappableString = &newVar return newVar } -func MakeMeta(index, occurence int, s string, f int, t ...TypeApp) Meta { +func MakeMeta(index, occurence int, s string, f int) Meta { fms := &MappedString{} - meta := Meta{fms, index, occurence, s, f, getType(t)} + meta := Meta{fms, index, occurence, s, f} fms.MappableString = &meta return meta } -func MakeFun(p Id, args Lib.List[Term], typeVars []TypeApp, t TypeScheme, metas Lib.Set[Meta]) Fun { +func MakeFun(p Id, args Lib.List[Term], metas Lib.Set[Meta]) Fun { fms := &MappedString{} - fun := Fun{fms, p, args, typeVars, t, Lib.MkCache(metas, Fun.forceGetMetas)} + fun := Fun{fms, p, args, Lib.MkCache(metas, Fun.forceGetMetas)} fms.MappableString = fun return fun } -/*** Functions ***/ - -func TypeAppArrToTerm(typeApps []TypeApp) Lib.List[Term] { - terms := Lib.MkList[Term](len(typeApps)) - - for i, typeApp := range typeApps { - terms.Upd(i, TypeAppToTerm(typeApp)) - } - - return terms -} - -/* Creates a Term from a TypeApp to unify it properly */ -func TypeAppToTerm(typeApp TypeApp) Term { - var term Term - switch nt := typeApp.(type) { - case TypeVar: - if nt.IsMeta() { - term = typeVarToMeta(nt) - } else { - Glob.PrintError("TERM", "A TypeVar should be only converted to terms if it has been instantiated.") - term = nil - } - case TypeHint: - term = MakerFun( - MakerId(nt.ToString()), - Lib.NewList[Term](), - []TypeApp{}, - MkTypeHint("$tType"), - ) - case TypeCross: - underlyingTypes := nt.GetAllUnderlyingTypes() - args := Lib.MkList[Term](len(underlyingTypes)) - - for i, type_ := range nt.GetAllUnderlyingTypes() { - args.Upd(i, TypeAppToTerm(type_)) - } - - term = MakeFun( - MakerId("$$tCross"), - args, - []TypeApp{}, - MkTypeHint("$tType"), - Lib.EmptySet[Meta](), - ) - case ParameterizedType: - parameters := nt.GetParameters() - args := Lib.MkList[Term](len(parameters)) - - for i, type_ := range nt.GetParameters() { - args.Upd(i, TypeAppToTerm(type_)) - } - - term = MakeFun( - MakerId(nt.ToString()), - args, - []TypeApp{}, - MkTypeHint("$tType"), - Lib.EmptySet[Meta](), - ) - } - return term -} - -func typeVarToMeta(typeVar TypeVar) Meta { - var meta Meta - index, formula, occurence := typeVar.MetaInfos() - if !typeVar.Instantiated() { - meta = MakerMeta(typeVar.ToString(), formula, MkTypeHint("$tType")) - typeVar.Instantiate(meta.index) - } else { - meta = MakeMeta(index, occurence, typeVar.ToString(), formula, MkTypeHint("$tType")) - } - return meta -} - -func replaceTermListTypesByMeta(tl Lib.List[Term], varList []TypeVar, index int) Lib.List[Term] { - res := Lib.MkList[Term](tl.Len()) - - for i, term := range tl.GetSlice() { - if Glob.Is[Fun](term) { - t := Glob.To[Fun](term) - res.Upd(i, MakeFun( - t.GetID(), - replaceTermListTypesByMeta(t.GetArgs(), varList, index), - instanciateTypeAppList(t.GetTypeVars(), varList, index), - t.GetTypeHint(), - t.metas.Raw(), - )) - } else { - res.Upd(i, term) - } - } - - return res -} +/*** Functions **/ func TermEquals(x, y Term) bool { return x.Equals(y) diff --git a/src/AST/termsDef.go b/src/AST/termsDef.go index 8b240000..544c2aff 100644 --- a/src/AST/termsDef.go +++ b/src/AST/termsDef.go @@ -146,11 +146,9 @@ func (i Id) Less(u any) bool { type Fun struct { *MappedString - p Id - args Lib.List[Term] - typeVars []TypeApp - typeHint TypeScheme - metas Lib.Cache[Lib.Set[Meta], Fun] + p Id + args Lib.List[Term] + metas Lib.Cache[Lib.Set[Meta], Fun] } func (f Fun) ToMappedStringSurround(mapping MapString, displayTypes bool) string { @@ -162,44 +160,25 @@ func (f Fun) ToMappedStringChild(mapping MapString, displayTypes bool) (separato } func (f Fun) ToMappedStringSurroundWithId(idString string, mapping MapString, displayTypes bool) string { - if len(f.typeVars) == 0 && f.GetArgs().Len() == 0 { + if f.GetArgs().Len() == 0 { return idString + "%s" } args := []string{} - - if len(f.typeVars) > 0 { - if tv := Glob.ListToString(f.typeVars, ", ", mapping[PredEmpty]); tv != "" { - args = append(args, tv) - } - } args = append(args, "%s") str := idString + "(" + strings.Join(args, mapping[PredTypeVarSep]) + ")" - if displayTypes { - str += " : " + f.typeHint.ToString() - } return str } func ToFlatternStringSurrountWithId(f Fun, idString string, mapping MapString, displayTypes bool) string { - - if len(f.typeVars) == 0 && f.GetArgs().Len() == 0 { + if f.GetArgs().Len() == 0 { return idString + "%s" } args := []string{} - - if len(f.typeVars) > 0 { - if tv := Glob.ListToString(f.typeVars, "_", mapping[PredEmpty]); tv != "" { - args = append(args, tv) - } - } args = append(args, "%s") str := idString + "_" + strings.Join(args, mapping[PredTypeVarSep]) - if displayTypes { - str += " : " + f.typeHint.ToString() - } return str } @@ -213,39 +192,33 @@ func (f Fun) GetID() Id { return f.p.Copy().(Id) } func (f Fun) GetP() Id { return f.p.Copy().(Id) } func (f Fun) GetArgs() Lib.List[Term] { return f.args } -func (f *Fun) SetArgs(tl Lib.List[Term]) { f.args = tl } -func (f *Fun) SetTypeScheme(ts TypeScheme) { f.typeHint = ts } +func (f *Fun) SetArgs(tl Lib.List[Term]) { f.args = tl } -func (f Fun) GetTypeVars() []TypeApp { return f.typeVars } -func (f Fun) GetTypeApp() TypeApp { return nil } -func (f Fun) GetTypeHint() TypeScheme { return f.typeHint } -func (f Fun) GetIndex() int { return f.GetID().GetIndex() } -func (f Fun) GetName() string { return f.GetID().GetName() } -func (f Fun) IsMeta() bool { return false } -func (f Fun) IsFun() bool { return true } -func (Fun) ToMeta() Meta { return MakeEmptyMeta() } +func (f Fun) GetIndex() int { return f.GetID().GetIndex() } +func (f Fun) GetName() string { return f.GetID().GetName() } +func (f Fun) IsMeta() bool { return false } +func (f Fun) IsFun() bool { return true } +func (Fun) ToMeta() Meta { return MakeEmptyMeta() } func (f Fun) Equals(t any) bool { switch typed := t.(type) { case Fun: return typed.GetID().Equals(f.GetID()) && - Lib.ListEquals(typed.GetArgs(), f.GetArgs()) && - f.typeHint.Equals(typed.typeHint) + Lib.ListEquals(typed.GetArgs(), f.GetArgs()) case *Fun: return typed.GetID().Equals(f.GetID()) && - Lib.ListEquals(typed.GetArgs(), f.GetArgs()) && - f.typeHint.Equals(typed.typeHint) + Lib.ListEquals(typed.GetArgs(), f.GetArgs()) default: return false } } func (f Fun) Copy() Term { - return MakeFun(f.GetP(), f.GetArgs(), CopyTypeAppList(f.GetTypeVars()), f.GetTypeHint(), f.metas.Raw()) + return MakeFun(f.GetP(), f.GetArgs(), f.metas.Raw()) } func (f Fun) PointerCopy() *Fun { - nf := MakeFun(f.GetP(), f.GetArgs(), CopyTypeAppList(f.GetTypeVars()), f.GetTypeHint(), f.metas.Raw()) + nf := MakeFun(f.GetP(), f.GetArgs(), f.metas.Raw()) return &nf } @@ -283,7 +256,7 @@ func (f Fun) ReplaceSubTermBy(oldTerm, newTerm Term) Term { return newTerm.Copy() } else { tl, res := replaceFirstOccurrenceTermList(f.GetArgs(), oldTerm, newTerm) - nf := MakeFun(f.GetID(), tl, f.GetTypeVars(), f.GetTypeHint(), f.metas.Raw()) + nf := MakeFun(f.GetID(), tl, f.metas.Raw()) if !res && !f.metas.NeedsUpd() { nf.metas.AvoidUpd() } @@ -296,7 +269,7 @@ func (f Fun) ReplaceAllSubTerm(oldTerm, newTerm Term) Term { return newTerm.Copy() } else { tl, res := ReplaceOccurrence(f.GetArgs(), oldTerm, newTerm) - nf := MakeFun(f.GetID(), tl, f.GetTypeVars(), f.GetTypeHint(), f.metas.Raw()) + nf := MakeFun(f.GetID(), tl, f.metas.Raw()) if !res && !f.metas.NeedsUpd() { nf.metas.AvoidUpd() } @@ -330,18 +303,15 @@ func (f Fun) Less(u any) bool { type Var struct { *MappedString - index int - name string - typeHint TypeApp + index int + name string } -func (v Var) GetTypeApp() TypeApp { return v.typeHint } -func (v Var) GetTypeHint() TypeScheme { return v.typeHint.(TypeScheme) } func (v Var) GetIndex() int { return v.index } func (v Var) GetName() string { return v.name } func (v Var) IsMeta() bool { return false } func (v Var) IsFun() bool { return false } -func (v Var) Copy() Term { return MakeVar(v.GetIndex(), v.GetName(), v.typeHint) } +func (v Var) Copy() Term { return MakeVar(v.GetIndex(), v.GetName()) } func (Var) ToMeta() Meta { return MakeEmptyMeta() } func (Var) GetMetas() Lib.Set[Meta] { return Lib.EmptySet[Meta]() } func (Var) GetMetaList() Lib.List[Meta] { return Lib.NewList[Meta]() } @@ -366,7 +336,7 @@ func (v Var) ReplaceSubTermBy(original_term, new_term Term) Term { func (v Var) ToMappedString(map_ MapString, type_ bool) string { if type_ { - return fmt.Sprintf("%s_%d : %s", v.GetName(), v.GetIndex(), v.typeHint.ToString()) + return fmt.Sprintf("%s_%d : %s", v.GetName(), v.GetIndex()) } return v.GetName() } @@ -377,7 +347,7 @@ func (v Var) ToMappedStringSurround(mapping MapString, displayTypes bool) string func (v Var) ToMappedStringChild(mapping MapString, displayTypes bool) (separator, emptyValue string) { if displayTypes { - return "", fmt.Sprintf("%s_%d : %s", v.GetName(), v.GetIndex(), v.typeHint.ToString()) + return "", fmt.Sprintf("%s_%d : %s", v.GetName(), v.GetIndex()) } else { return "", v.GetName() } @@ -406,13 +376,11 @@ type Meta struct { occurence int name string formula int - typeHint TypeApp + // FIXME: remember the type of a Meta } func (m Meta) GetFormula() int { return m.formula } -func (m Meta) GetTypeApp() TypeApp { return m.typeHint } -func (m Meta) GetTypeHint() TypeScheme { return m.typeHint.(TypeScheme) } func (m Meta) GetName() string { return m.name } func (m Meta) GetIndex() int { return m.index } func (m Meta) GetOccurence() int { return m.occurence } @@ -428,7 +396,7 @@ func (m Meta) ToMappedStringSurround(mapping MapString, displayTypes bool) strin func (m Meta) ToMappedStringChild(mapping MapString, displayTypes bool) (separator, emptyValue string) { if displayTypes { - return "", fmt.Sprintf("%s_%d : %s", m.GetName(), m.GetIndex(), m.GetTypeHint().ToString()) + return "", fmt.Sprintf("%s_%d : %s", m.GetName(), m.GetIndex()) } else { return "", fmt.Sprintf("%s_%d", m.GetName(), m.GetIndex()) } @@ -446,7 +414,7 @@ func (m Meta) Equals(t any) bool { } func (m Meta) Copy() Term { - return MakeMeta(m.GetIndex(), m.GetOccurence(), m.GetName(), m.GetFormula(), m.GetTypeApp()) + return MakeMeta(m.GetIndex(), m.GetOccurence(), m.GetName(), m.GetFormula()) } func (m Meta) ReplaceSubTermBy(original_term, new_term Term) Term { @@ -471,7 +439,7 @@ func (m Meta) Less(u any) bool { } func MakeEmptyMeta() Meta { - return MakeMeta(-1, -1, "-1", -1, nil, DefaultType()) + return MakeMeta(-1, -1, "-1", -1) } func MetaEquals(x, y Meta) bool { diff --git a/src/Core/Sko/inner-skolemization.go b/src/Core/Sko/inner-skolemization.go index 4d3d9ac8..93abe49d 100644 --- a/src/Core/Sko/inner-skolemization.go +++ b/src/Core/Sko/inner-skolemization.go @@ -63,7 +63,7 @@ func (sko InnerSkolemization) Skolemize( _ Lib.Set[AST.Meta], ) (Skolemization, AST.Form) { sko.mu.Lock() - symbol := genFreshSymbol(&sko.existingSymbols, sko.mu, x) + symbol := genFreshSymbol(&sko.existingSymbols, &sko.mu, x) sko.mu.Unlock() internalMetas := form.GetMetas().Elements() @@ -71,8 +71,6 @@ func (sko InnerSkolemization) Skolemize( skolemFunc := AST.MakerFun( symbol, Lib.ListMap(internalMetas, Glob.To[AST.Term]), - []AST.TypeApp{}, - mkSkoFuncType(internalMetas, x.GetTypeApp()), ) skolemizedForm, _ := form.ReplaceTermByTerm( diff --git a/src/Core/Sko/interface.go b/src/Core/Sko/interface.go index a79ba10e..984e345f 100644 --- a/src/Core/Sko/interface.go +++ b/src/Core/Sko/interface.go @@ -37,7 +37,6 @@ import ( "sync" "github.com/GoelandProver/Goeland/AST" - "github.com/GoelandProver/Goeland/Glob" "github.com/GoelandProver/Goeland/Lib" ) @@ -59,40 +58,10 @@ type Skolemization interface { ) (Skolemization, AST.Form) } -func mkSkoFuncType( - relevantMetas Lib.List[AST.Meta], - varType AST.TypeApp, -) AST.TypeScheme { - var resultingScheme AST.TypeScheme - - switch relevantMetas.Len() { - case 0: - if typ, ok := varType.(AST.TypeScheme); ok { - resultingScheme = typ - } else { - Glob.Anomaly("Skolemization", "Variable has an illegal type") - } - case 1: - metaType := relevantMetas.At(0).GetTypeApp() - resultingScheme = AST.MkTypeArrow(metaType, varType) - default: - argTypes := Lib.ListMap( - relevantMetas, - func(x AST.Meta) AST.TypeApp { return x.GetTypeApp() }, - ) - resultingScheme = AST.MkTypeArrow( - AST.MkTypeCross(argTypes.GetSlice()...), - varType, - ) - } - - return resultingScheme -} - /* If every Skolem symbol is created using this function, then it will generate * a fresh symbol for sure. Otherwise, nothing is guaranteed. */ -func genFreshSymbol(existingSymbols *Lib.Set[AST.Id], mu sync.Mutex, x AST.Var) AST.Id { +func genFreshSymbol(existingSymbols *Lib.Set[AST.Id], mu *sync.Mutex, x AST.Var) AST.Id { symbol := AST.MakerNewId( fmt.Sprintf("skolem@%v", x.GetName()), ) diff --git a/src/Core/Sko/outer-skolemization.go b/src/Core/Sko/outer-skolemization.go index 14c7bfa9..1e199fe4 100644 --- a/src/Core/Sko/outer-skolemization.go +++ b/src/Core/Sko/outer-skolemization.go @@ -63,7 +63,7 @@ func (sko OuterSkolemization) Skolemize( fvs Lib.Set[AST.Meta], ) (Skolemization, AST.Form) { sko.mu.Lock() - symbol := genFreshSymbol(&sko.existingSymbols, sko.mu, x) + symbol := genFreshSymbol(&sko.existingSymbols, &sko.mu, x) sko.mu.Unlock() metas := fvs.Elements() @@ -71,8 +71,6 @@ func (sko OuterSkolemization) Skolemize( skolemFunc := AST.MakerFun( symbol, Lib.ListMap(metas, Glob.To[AST.Term]), - []AST.TypeApp{}, - mkSkoFuncType(metas, x.GetTypeApp()), ) skolemizedForm, _ := form.ReplaceTermByTerm( diff --git a/src/Core/Sko/preinner-skolemization.go b/src/Core/Sko/preinner-skolemization.go index 8ac9fab2..84e36676 100644 --- a/src/Core/Sko/preinner-skolemization.go +++ b/src/Core/Sko/preinner-skolemization.go @@ -75,7 +75,7 @@ func (sko PreInnerSkolemization) Skolemize( ); ok { symbol = val.Snd } else { - symbol = genFreshSymbol(&sko.existingSymbols, sko.mu, x) + symbol = genFreshSymbol(&sko.existingSymbols, &sko.mu, x) sko.linkedSymbols.Append(Glob.MakePair(realDelta, symbol)) } sko.mu.Unlock() @@ -85,8 +85,6 @@ func (sko PreInnerSkolemization) Skolemize( skolemFunc := AST.MakerFun( symbol, Lib.ListMap(internalMetas, Glob.To[AST.Term]), - []AST.TypeApp{}, - mkSkoFuncType(internalMetas, x.GetTypeApp()), ) skolemizedForm, _ := form.ReplaceTermByTerm( @@ -118,8 +116,6 @@ func alphaConvert( f.GetIndex(), f.GetID(), mappedTerms, - f.GetTypeVars(), - f.GetType(), ) case AST.Not: return AST.MakeNot( @@ -164,6 +160,10 @@ func alphaConvert( k, substitution, vl := makeConvertedVarList(k, substitution, f.GetVarList()) return AST.MakeEx(f.GetIndex(), vl, alphaConvert(f.GetForm(), k, substitution)) } + Glob.Anomaly( + "preinner", + fmt.Sprintf("On alpha-conversion of %s: form does not correspond to any known ones", form.ToString()), + ) return form } @@ -174,7 +174,7 @@ func makeConvertedVarList( ) (int, map[int]AST.Var, []AST.Var) { newVarList := []AST.Var{} for i, v := range vl { - nv := AST.MakeVar(k+i, fresh(k+i), v.GetTypeApp()) + nv := AST.MakeVar(k+i, fresh(k+i)) newVarList = append(newVarList, nv) substitution[v.GetIndex()] = nv } @@ -197,8 +197,6 @@ func alphaConvertTerm(t AST.Term, substitution map[int]AST.Var) AST.Term { return AST.MakerFun( nt.GetID(), mappedTerms, - nt.GetTypeVars(), - nt.GetTypeHint(), ) } return t diff --git a/src/Core/instanciation.go b/src/Core/instanciation.go index 44721858..5df870d8 100644 --- a/src/Core/instanciation.go +++ b/src/Core/instanciation.go @@ -71,7 +71,7 @@ func RealInstantiate( terms Lib.List[AST.Term], ) (FormAndTerms, AST.Meta) { v := varList[0] - meta := AST.MakerMeta(strings.ToUpper(v.GetName()), index, v.GetTypeHint().(AST.TypeApp)) + meta := AST.MakerMeta(strings.ToUpper(v.GetName()), index) subForm = subForm.SubstituteVarByMeta(v, meta) terms = terms.Copy(AST.Term.Copy) diff --git a/src/Core/rules_type.go b/src/Core/rules_type.go index f4e9935f..08a399ea 100644 --- a/src/Core/rules_type.go +++ b/src/Core/rules_type.go @@ -37,7 +37,6 @@ package Core import ( "github.com/GoelandProver/Goeland/AST" - "github.com/GoelandProver/Goeland/Glob" ) /******************/ @@ -86,8 +85,6 @@ func ShowKindOfRule(f AST.Form) KindOfRule { res = Gamma case AST.All: res = Delta - case AST.AllType: - Glob.Anomaly("Kind of rule", "not forall(type) found when it shouldn't happen.") } case AST.And: res = Alpha @@ -95,7 +92,7 @@ func ShowKindOfRule(f AST.Form) KindOfRule { res = Beta case AST.Ex: res = Delta - case AST.All, AST.AllType: + case AST.All: res = Gamma } return res diff --git a/src/Core/substitutions_search.go b/src/Core/substitutions_search.go index 15df6500..2a2169b5 100644 --- a/src/Core/substitutions_search.go +++ b/src/Core/substitutions_search.go @@ -210,8 +210,6 @@ func ApplySubstitutionOnTerm(old_symbol AST.Meta, new_symbol, t AST.Term) AST.Te res = AST.MakerFun( nf.GetP(), ApplySubstitutionOnTermList(old_symbol, new_symbol, nf.GetArgs()), - nf.GetTypeVars(), - nf.GetTypeHint(), ) } return res @@ -269,14 +267,6 @@ func ApplySubstitutionOnTermList( return res } -func applySubstitutionOnTypeList(old_symbol AST.Meta, new_symbol AST.Term, tl []AST.TypeApp) []AST.TypeApp { - res := make([]AST.TypeApp, len(tl)) - for i, t := range tl { - res[i] = applySubstitutionOnType(old_symbol.GetTypeApp(), new_symbol.(AST.TypedTerm).GetTypeApp(), t) - } - return res -} - /* Apply a substitution on a formula */ func ApplySubstitutionOnFormula(old_symbol AST.Meta, new_symbol AST.Term, f AST.Form) AST.Form { var res AST.Form @@ -287,8 +277,6 @@ func ApplySubstitutionOnFormula(old_symbol AST.Meta, new_symbol AST.Term, f AST. nf.GetIndex(), nf.GetID(), ApplySubstitutionOnTermList(old_symbol, new_symbol, nf.GetArgs()), - applySubstitutionOnTypeList(old_symbol, new_symbol, nf.GetTypeVars()), - nf.GetType(), ) case AST.Not: res = AST.MakeNot(f.GetIndex(), ApplySubstitutionOnFormula(old_symbol, new_symbol, nf.GetForm())) diff --git a/src/Engine/pretyper.go b/src/Engine/pretyper.go index 1b077b51..86c8d69e 100644 --- a/src/Engine/pretyper.go +++ b/src/Engine/pretyper.go @@ -145,11 +145,7 @@ func splitTypeVars( if isTType(ty.Snd.(Parser.PType)) { tyvars = append(tyvars, AST.MkTypeVar(ty.Fst)) } else { - varTy := ty.Snd.(Parser.PType) - others = append( - others, - AST.MakerVar(ty.Fst, elaborateType(varTy, varTy).(AST.TypeApp)), - ) + others = append(others, AST.MakerVar(ty.Fst)) } } return tyvars, others diff --git a/src/Engine/syntax-translation.go b/src/Engine/syntax-translation.go index 0e27ead9..9ad5a737 100644 --- a/src/Engine/syntax-translation.go +++ b/src/Engine/syntax-translation.go @@ -145,16 +145,10 @@ func elaborateForm(con Context, f, source_form Parser.PForm) AST.Form { case Parser.PPred: typed_arguments := pretype(con, pform.Args()) - type_args, real_args := splitTypes(typed_arguments) + _, real_args := splitTypes(typed_arguments) return AST.MakerPred( AST.MakerId(pform.Symbol()), Lib.ListMap(real_args, aux), - Lib.ListMap( - type_args, - func(pty Parser.PType) AST.TypeApp { - return elaborateType(pty, pty).(AST.TypeApp) - }, - ).GetSlice(), ) case Parser.PUnary: @@ -195,9 +189,6 @@ func elaborateForm(con Context, f, source_form Parser.PForm) AST.Form { if len(vars) != 0 { form = AST.MakerAll(vars, form) } - if len(type_vars) != 0 { - form = AST.MakerAllType(type_vars, form) - } return form case Parser.PQuantEx: if len(type_vars) != 0 { @@ -321,25 +312,15 @@ func elaborateTerm(con Context, t, source_term Parser.PTerm) AST.Term { fail(ty) } // FIXME: get some error function over here - return AST.MakerVar(pterm.Name(), elaborateType(t.Val, t.Val).(AST.TypeApp)) + return AST.MakerVar(pterm.Name()) } case Parser.PFun: typed_arguments := pretype(con, pterm.Args()) - type_args, real_args := splitTypes(typed_arguments) + _, real_args := splitTypes(typed_arguments) fun := AST.MakerFun( AST.MakerId(pterm.Symbol()), Lib.ListMap(real_args, aux), - Lib.ListMap( - type_args, - func(pty Parser.PType) AST.TypeApp { - ty := elaborateType(pty, pty) - if _, ok := ty.(AST.TypeApp); !ok { - fail(ty) - } - return elaborateType(pty, pty).(AST.TypeApp) - }, - ).GetSlice(), ) switch oty := pterm.DefinedType().(type) { case Lib.Some[Parser.PTypeFun]: diff --git a/src/Mods/equality/bse/equality_problem_list.go b/src/Mods/equality/bse/equality_problem_list.go index 52d77e74..689b3ad8 100644 --- a/src/Mods/equality/bse/equality_problem_list.go +++ b/src/Mods/equality/bse/equality_problem_list.go @@ -215,8 +215,6 @@ func buildEqualityProblemMultiListFromPredList(pred AST.Pred, tn Unif.DataStruct newTerm := AST.MakerPred( predId.Copy().(AST.Id), AST.MetaListToTermList(metas), - pred.GetTypeVars(), - pred.GetType(), ) found, complementaryPredList := tn.Unify(newTerm) diff --git a/src/Mods/equality/bse/equality_types.go b/src/Mods/equality/bse/equality_types.go index ac16dd5c..2c1deb91 100644 --- a/src/Mods/equality/bse/equality_types.go +++ b/src/Mods/equality/bse/equality_types.go @@ -124,15 +124,13 @@ func retrieveEqualities(dt Unif.DataStructure) Equalities { MetaEQ2 := AST.MakerMeta("METAEQ2", -1) // TODO: type this tv := AST.MkTypeVar("EQ") - eq_pred := AST.MakerPred(AST.Id_eq, Lib.NewList[AST.Term](), []AST.TypeApp{}) + eq_pred := AST.MakerPred(AST.Id_eq, Lib.NewList[AST.Term]()) tv.ShouldBeMeta(eq_pred.GetIndex()) tv.Instantiate(1) eq_pred = AST.MakePred( eq_pred.GetIndex(), AST.Id_eq, Lib.MkListV[AST.Term](MetaEQ1, MetaEQ2), - []AST.TypeApp{}, - AST.GetPolymorphicType(AST.Id_eq.GetName(), 1, 2), ) _, eq_list := dt.Unify(eq_pred) @@ -156,18 +154,12 @@ func retrieveInequalities(dt Unif.DataStructure) Inequalities { res := Inequalities{} MetaNEQ1 := AST.MakerMeta("META_NEQ_1", -1) MetaNEQ2 := AST.MakerMeta("META_NEQ_2", -1) - // TODO: type this - tv := AST.MkTypeVar("EQ") - neq_pred := AST.MakerPred(AST.Id_eq, Lib.NewList[AST.Term](), []AST.TypeApp{}) - tv.ShouldBeMeta(neq_pred.GetIndex()) - tv.Instantiate(1) + neq_pred := AST.MakerPred(AST.Id_eq, Lib.NewList[AST.Term]()) neq_pred = AST.MakePred( neq_pred.GetIndex(), AST.Id_eq, Lib.MkListV[AST.Term](MetaNEQ1, MetaNEQ2), - []AST.TypeApp{}, - AST.GetPolymorphicType(AST.Id_eq.GetName(), 1, 2), ) _, neq_list := dt.Unify(neq_pred) diff --git a/src/Mods/equality/sateq/subsgatherer.go b/src/Mods/equality/sateq/subsgatherer.go index 3fd60f13..995193a4 100644 --- a/src/Mods/equality/sateq/subsgatherer.go +++ b/src/Mods/equality/sateq/subsgatherer.go @@ -83,7 +83,7 @@ func translate(toTranslate *eqClass, correspondence map[*eqClass]*termRecord) AS for i, s := range tr.args { args.Upd(i, translate(s, correspondence)) } - return AST.MakerFun(tr.symbolId, args, tr.typeVars, tr.typeHint) + return AST.MakerFun(tr.symbolId, args) } } diff --git a/src/Mods/equality/sateq/termrep.go b/src/Mods/equality/sateq/termrep.go index 8d1a2b84..36c8a42a 100644 --- a/src/Mods/equality/sateq/termrep.go +++ b/src/Mods/equality/sateq/termrep.go @@ -130,8 +130,6 @@ func funTermRecord(t AST.Fun, args []*eqClass) *termRecord { meta: nil, symbolId: t.GetID(), args: args, - typeHint: t.GetTypeHint(), - typeVars: t.GetTypeVars(), } } @@ -141,8 +139,6 @@ type termRecord struct { meta *AST.Meta symbolId AST.Id args []*eqClass - typeHint AST.TypeScheme - typeVars []AST.TypeApp } func (t *termRecord) isMeta() bool { diff --git a/src/Mods/gs3/dependency.go b/src/Mods/gs3/dependency.go index 9bf39d78..06a865d1 100644 --- a/src/Mods/gs3/dependency.go +++ b/src/Mods/gs3/dependency.go @@ -139,8 +139,6 @@ func getVariableOccurrencesForm(v AST.Var, form AST.Form, currentOcc occurrences currentOcc = getUnaryOcc(v, f.GetForm(), currentOcc, workingPath) case AST.Ex: currentOcc = getUnaryOcc(v, f.GetForm(), currentOcc, workingPath) - case AST.AllType: - currentOcc = getUnaryOcc(v, f.GetForm(), currentOcc, workingPath) } return currentOcc } @@ -209,8 +207,6 @@ func getTermAux(form AST.Form, occ occurrence) AST.Term { term = getUnaryTerm(f.GetForm(), occ) case AST.Ex: term = getUnaryTerm(f.GetForm(), occ) - case AST.AllType: - term = getUnaryTerm(f.GetForm(), occ) } return term } diff --git a/src/Mods/lambdapi/context.go b/src/Mods/lambdapi/context.go index b1359413..ca42bd43 100644 --- a/src/Mods/lambdapi/context.go +++ b/src/Mods/lambdapi/context.go @@ -178,8 +178,6 @@ func getContextFromFormula(root AST.Form) []string { result = getContextFromFormula(nf.GetForm()) case AST.Ex: result = getContextFromFormula(nf.GetForm()) - case AST.AllType: - result = getContextFromFormula(nf.GetForm()) case AST.And: for _, f := range nf.GetChildFormulas().GetSlice() { result = append(result, clean(result, getContextFromFormula(f))...) @@ -198,18 +196,7 @@ func getContextFromFormula(root AST.Form) []string { result = append(result, getContextFromFormula(nf.GetForm())...) case AST.Pred: if !nf.GetID().Equals(AST.Id_eq) { - primitives := nf.GetType().GetPrimitives() - typesStr := "" - - for i, prim := range primitives { - if i != len(primitives)-1 { - typesStr += "τ (" + prim.ToString() + ") → " - } else { - typesStr += prim.ToString() - } - } - - result = append(result, mapDefault(fmt.Sprintf("symbol %s : %s;", nf.GetID().ToMappedString(lambdaPiMapConnectors, false), typesStr))) + result = append(result, mapDefault(fmt.Sprintf("symbol %s;", nf.GetID().ToMappedString(lambdaPiMapConnectors, false)))) } for _, term := range nf.GetArgs().GetSlice() { result = append(result, clean(result, getContextFromTerm(term))...) @@ -226,8 +213,6 @@ func getIdsFromFormula(root AST.Form) []Glob.Pair[string, string] { result = getIdsFromFormula(nf.GetForm()) case AST.Ex: result = getIdsFromFormula(nf.GetForm()) - case AST.AllType: - result = getIdsFromFormula(nf.GetForm()) case AST.And: for _, f := range nf.GetChildFormulas().GetSlice() { result = append(result, getIdsFromFormula(f)...) @@ -257,18 +242,7 @@ func getContextFromTerm(trm AST.Term) []string { result := []string{} if fun, isFun := trm.(AST.Fun); isFun { - - primitives := fun.GetTypeHint().GetPrimitives() - typesStr := "" - for i, prim := range primitives { - if i != len(primitives)-1 { - typesStr += "τ (" + prim.ToString() + ") → " - } else { - typesStr += "τ (" + prim.ToString() + ")" - } - } - - result = append(result, mapDefault(fmt.Sprintf("symbol %s : %s;", fun.GetID().ToMappedString(lambdaPiMapConnectors, false), typesStr))) + result = append(result, mapDefault(fmt.Sprintf("symbol %s;", fun.GetID().ToMappedString(lambdaPiMapConnectors, false)))) for _, term := range fun.GetArgs().GetSlice() { result = append(result, clean(result, getContextFromTerm(term))...) } diff --git a/src/Mods/lambdapi/formDecorator.go b/src/Mods/lambdapi/formDecorator.go index 9838a873..2ea14429 100644 --- a/src/Mods/lambdapi/formDecorator.go +++ b/src/Mods/lambdapi/formDecorator.go @@ -58,7 +58,7 @@ func QuantifierToMappedString(quant string, varList []AST.Var) string { if len(varList) == 0 { return "%s" } else { - result := "(" + quant + " (" + toLambdaIntroString(varList[0], varList[0].GetTypeHint().ToString()) + ", %s))" + result := "(" + quant + " (" + toLambdaIntroString(varList[0], "") + ", %s))" result = fmt.Sprintf(result, QuantifierToMappedString(quant, varList[1:])) return result } diff --git a/src/Mods/lambdapi/proof.go b/src/Mods/lambdapi/proof.go index 9c78f47b..c0d16dbb 100644 --- a/src/Mods/lambdapi/proof.go +++ b/src/Mods/lambdapi/proof.go @@ -147,11 +147,10 @@ func allRules(rule string, target AST.Form, composingForms Lib.List[AST.Form], n func allRulesQuantUniv(rule string, target AST.Form, composingForms Lib.List[AST.Form], nexts []*gs3.GS3Sequent, children []Lib.List[AST.Form], vars []AST.Var, termGen AST.Term) string { quant := "" - typeStr := vars[0].GetTypeApp().ToString() - switch typed := target.(type) { + typeStr := "" + switch target.(type) { case AST.All: quant = lambdaPiMapConnectors[AST.AllQuant] - typeStr = typed.GetVarList()[0].GetTypeHint().ToString() case AST.Not: quant = lambdaPiMapConnectors[AST.ExQuant] } @@ -164,7 +163,7 @@ func allRulesQuantUniv(rule string, target AST.Form, composingForms Lib.List[AST varStrs := []string{} for _, singleVar := range vars { - varStrs = append(varStrs, toLambdaIntroString(singleVar, singleVar.GetTypeHint().ToString())) + varStrs = append(varStrs, toLambdaIntroString(singleVar, "")) } result = fmt.Sprintf(result, strings.Join(varStrs, ", "+quant+" ")) @@ -192,11 +191,10 @@ func getRecursionUnivStr(nexts []*gs3.GS3Sequent, children []Lib.List[AST.Form]) func allRulesQuantExist(rule string, target AST.Form, composingForms Lib.List[AST.Form], nexts []*gs3.GS3Sequent, children []Lib.List[AST.Form], vars []AST.Var, termGen AST.Term) string { quant := "" - typeStr := vars[0].GetTypeApp().ToString() - switch typed := target.(type) { + typeStr := "" + switch target.(type) { case AST.Ex: quant = lambdaPiMapConnectors[AST.ExQuant] - typeStr = typed.GetVarList()[0].GetTypeHint().ToString() case AST.Not: quant = lambdaPiMapConnectors[AST.AllQuant] } @@ -209,7 +207,7 @@ func allRulesQuantExist(rule string, target AST.Form, composingForms Lib.List[AS varStrs := []string{} for _, singleVar := range vars { - varStrs = append(varStrs, toLambdaIntroString(singleVar, singleVar.GetTypeHint().ToString())) + varStrs = append(varStrs, toLambdaIntroString(singleVar, "")) } result = fmt.Sprintf(result, strings.Join(varStrs, ", "+quant+" ")) @@ -224,8 +222,8 @@ func getRecursionExistStr(nexts []*gs3.GS3Sequent, children []Lib.List[AST.Form] for i, next := range nexts { result += "(\n" typesStr := "" - if typed, ok := termGen.(AST.Fun); ok { - typesStr = mapDefault(typed.GetTypeHint().ToString()) + if _, ok := termGen.(AST.Fun); ok { + typesStr = mapDefault("") } result += toLambdaIntroString(termGen, typesStr) + ",\n" for _, childForm := range children[i].GetSlice() { diff --git a/src/Mods/rocq/context.go b/src/Mods/rocq/context.go index bdfa1d79..1fe3360a 100644 --- a/src/Mods/rocq/context.go +++ b/src/Mods/rocq/context.go @@ -99,8 +99,6 @@ func getContextFromFormula(root AST.Form) []string { result = getContextFromFormula(nf.GetForm()) case AST.Ex: result = getContextFromFormula(nf.GetForm()) - case AST.AllType: - result = getContextFromFormula(nf.GetForm()) case AST.And: for _, f := range nf.GetChildFormulas().GetSlice() { result = append(result, clean(result, getContextFromFormula(f))...) @@ -119,8 +117,8 @@ func getContextFromFormula(root AST.Form) []string { result = clean(result, getContextFromFormula(nf.GetForm())) case AST.Pred: if !nf.GetID().Equals(AST.Id_eq) { - result = append(result, mapDefault(fmt.Sprintf("Parameter %s : %s.", - nf.GetID().ToMappedString(rocqMapConnectors(), false), nf.GetType().ToString()))) + result = append(result, mapDefault( + fmt.Sprintf("Parameter %s.", nf.GetID().ToMappedString(rocqMapConnectors(), false)))) } for _, term := range nf.GetArgs().GetSlice() { result = append(result, clean(result, getContextFromTerm(term))...) @@ -132,8 +130,9 @@ func getContextFromFormula(root AST.Form) []string { func getContextFromTerm(trm AST.Term) []string { result := []string{} if fun, isFun := trm.(AST.Fun); isFun { - result = append(result, mapDefault(fmt.Sprintf("Parameter %s : %s.", - fun.GetID().ToMappedString(rocqMapConnectors(), false), fun.GetTypeHint().ToString()))) + result = append(result, + mapDefault(fmt.Sprintf( + "Parameter %s.", fun.GetID().ToMappedString(rocqMapConnectors(), false)))) for _, term := range fun.GetArgs().GetSlice() { result = append(result, clean(result, getContextFromTerm(term))...) } diff --git a/src/Search/rules.go b/src/Search/rules.go index e327a9d1..855aafcb 100644 --- a/src/Search/rules.go +++ b/src/Search/rules.go @@ -43,7 +43,6 @@ import ( "github.com/GoelandProver/Goeland/Glob" "github.com/GoelandProver/Goeland/Lib" "github.com/GoelandProver/Goeland/Unif" - "os" ) var strToPrintMap map[string]string = map[string]string{ @@ -503,10 +502,6 @@ func ApplyGammaRules(fnt Core.FormAndTerms, index int, state *State) (Core.FormA case AST.All: setStateRules(state, "GAMMA", "FORALL") - - case AST.AllType: - Glob.PrintError("search", "Typed search not handled yet") - os.Exit(3) } fnt, mm := Core.Instantiate(fnt, index) diff --git a/src/Typing/apply_rules.go b/src/Typing/apply_rules.go index 16a7313f..828b7ae9 100644 --- a/src/Typing/apply_rules.go +++ b/src/Typing/apply_rules.go @@ -32,158 +32,158 @@ package Typing -import ( - "fmt" - - "github.com/GoelandProver/Goeland/AST" -) - -/** - * This file contains all the rules of the typing system. - **/ - -const ( - formIsSet = iota - termIsSet = iota - typeIsSet = iota - schemeIsSet = iota - noConsequence = iota -) - -/* Launch the rules depending on what's on the right side of the sequent. */ -func applyRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { - // Only one of the three should be set - if !onlyOneConsequenceIsSet(state) { - return Reconstruct{ - result: false, - err: fmt.Errorf("multiple elements on the right-side of the sequent. Cannot type this system"), - } - } - - // The applicable rules depend on what is set: the form, the term, or the type ? - switch whatIsSet(state.consequence) { - case formIsSet: - return applyFormRule(state, root, fatherChan) - case termIsSet: - return applyTermRule(state, root, fatherChan) - case typeIsSet: - return applyTypeRule(state, root, fatherChan) - case schemeIsSet: - return applySymRule(state, root, fatherChan) - case noConsequence: - return applyWFRule(state, root, fatherChan) - } - - return Reconstruct{result: true, err: nil} -} - -/* Applies one of the forms rule based on the type of the form. */ -func applyFormRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { - var rec Reconstruct - switch (state.consequence.f).(type) { - case AST.All, AST.AllType, AST.Ex: - rec = applyQuantRule(state, root, fatherChan) - case AST.And, AST.Or: - rec = applyNAryRule(state, root, fatherChan) - case AST.Imp, AST.Equ: - rec = applyBinaryRule(state, root, fatherChan) - case AST.Top, AST.Bot: - rec = applyBotTopRule(state, root, fatherChan) - case AST.Not: - rec = applyNotRule(state, root, fatherChan) - case AST.Pred: - rec = applyAppRule(state, root, fatherChan) - } - return rec -} - -/* Applies one of the terms rule based on the type of the form. */ -func applyTermRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { - var rec Reconstruct - switch (state.consequence.t).(type) { - case AST.Fun: - rec = applyAppRule(state, root, fatherChan) - case AST.Var: - rec = applyVarRule(state, root, fatherChan) - // Metas shoudln't appear in the formula yet. - // IDs are not a real Term. - } - return rec -} - -/* Applies one of the types rule based on the type of the form. */ -func applyTypeRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { - var rec Reconstruct - switch type_ := (state.consequence.a).(type) { - case AST.TypeHint: - if type_.Equals(metaType) { - rec = applyTypeWFRule(state, root, fatherChan) - } else { - rec = applyGlobalTypeVarRule(state, root, fatherChan) - } - case AST.TypeVar: - rec = applyLocalTypeVarRule(state, root, fatherChan) - case AST.TypeCross: - // Apply composed rule: launch a child for each TypeHint of the composed type. - rec = applyCrossRule(state, root, fatherChan) - // There shouldn't be any TypeArrow: can not type a variable with it in first order. - case AST.ParameterizedType: - // Apply app rule, we only need to check if the name of the type exists. - rec = applyAppTypeRule(state, root, fatherChan) - } - return rec -} - -/* Applies one of the WF rule based on the type of the form. */ -func applyWFRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { - if state.localContext.isEmpty() && state.globalContext.isEmpty() { - root.appliedRule = "WF_0" - return Reconstruct{result: true, err: nil} - } - if state.localContext.isEmpty() { - root.appliedRule = "WF_1" - return Reconstruct{result: true, err: nil} - } - - return applyWF2(state, root, fatherChan) -} - -/* Checks that at most one consequence of the sequent is set. */ -func onlyOneConsequenceIsSet(state Sequent) bool { - numberSet := 0 - if state.consequence.f != nil { - numberSet++ - } - if state.consequence.t != nil { - numberSet++ - } - if state.consequence.a != nil { - numberSet++ - } - if state.consequence.s != nil { - numberSet++ - } - - return numberSet < 2 -} - -/** - * Returns what is set in the consequence of the sequent. Either it's the form, - * the term, or the type. - * It doesn't check if multiple elements are set, it should be done before. - **/ -func whatIsSet(cons Consequence) int { - var set int - if cons.f != nil { - set = formIsSet - } else if cons.t != nil { - set = termIsSet - } else if cons.a != nil { - set = typeIsSet - } else if cons.s != nil { - set = schemeIsSet - } else { - set = noConsequence - } - return set -} +// import ( +// "fmt" + +// "github.com/GoelandProver/Goeland/AST" +// ) + +// /** +// * This file contains all the rules of the typing system. +// **/ + +// const ( +// formIsSet = iota +// termIsSet = iota +// typeIsSet = iota +// schemeIsSet = iota +// noConsequence = iota +// ) + +// /* Launch the rules depending on what's on the right side of the sequent. */ +// func applyRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { +// // Only one of the three should be set +// if !onlyOneConsequenceIsSet(state) { +// return Reconstruct{ +// result: false, +// err: fmt.Errorf("multiple elements on the right-side of the sequent. Cannot type this system"), +// } +// } + +// // The applicable rules depend on what is set: the form, the term, or the type ? +// switch whatIsSet(state.consequence) { +// case formIsSet: +// return applyFormRule(state, root, fatherChan) +// case termIsSet: +// return applyTermRule(state, root, fatherChan) +// case typeIsSet: +// return applyTypeRule(state, root, fatherChan) +// case schemeIsSet: +// return applySymRule(state, root, fatherChan) +// case noConsequence: +// return applyWFRule(state, root, fatherChan) +// } + +// return Reconstruct{result: true, err: nil} +// } + +// /* Applies one of the forms rule based on the type of the form. */ +// func applyFormRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { +// var rec Reconstruct +// switch (state.consequence.f).(type) { +// case AST.All, AST.AllType, AST.Ex: +// rec = applyQuantRule(state, root, fatherChan) +// case AST.And, AST.Or: +// rec = applyNAryRule(state, root, fatherChan) +// case AST.Imp, AST.Equ: +// rec = applyBinaryRule(state, root, fatherChan) +// case AST.Top, AST.Bot: +// rec = applyBotTopRule(state, root, fatherChan) +// case AST.Not: +// rec = applyNotRule(state, root, fatherChan) +// case AST.Pred: +// rec = applyAppRule(state, root, fatherChan) +// } +// return rec +// } + +// /* Applies one of the terms rule based on the type of the form. */ +// func applyTermRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { +// var rec Reconstruct +// switch (state.consequence.t).(type) { +// case AST.Fun: +// rec = applyAppRule(state, root, fatherChan) +// case AST.Var: +// rec = applyVarRule(state, root, fatherChan) +// // Metas shoudln't appear in the formula yet. +// // IDs are not a real Term. +// } +// return rec +// } + +// /* Applies one of the types rule based on the type of the form. */ +// func applyTypeRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { +// var rec Reconstruct +// switch type_ := (state.consequence.a).(type) { +// case AST.TypeHint: +// if type_.Equals(metaType) { +// rec = applyTypeWFRule(state, root, fatherChan) +// } else { +// rec = applyGlobalTypeVarRule(state, root, fatherChan) +// } +// case AST.TypeVar: +// rec = applyLocalTypeVarRule(state, root, fatherChan) +// case AST.TypeCross: +// // Apply composed rule: launch a child for each TypeHint of the composed type. +// rec = applyCrossRule(state, root, fatherChan) +// // There shouldn't be any TypeArrow: can not type a variable with it in first order. +// case AST.ParameterizedType: +// // Apply app rule, we only need to check if the name of the type exists. +// rec = applyAppTypeRule(state, root, fatherChan) +// } +// return rec +// } + +// /* Applies one of the WF rule based on the type of the form. */ +// func applyWFRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { +// if state.localContext.isEmpty() && state.globalContext.isEmpty() { +// root.appliedRule = "WF_0" +// return Reconstruct{result: true, err: nil} +// } +// if state.localContext.isEmpty() { +// root.appliedRule = "WF_1" +// return Reconstruct{result: true, err: nil} +// } + +// return applyWF2(state, root, fatherChan) +// } + +// /* Checks that at most one consequence of the sequent is set. */ +// func onlyOneConsequenceIsSet(state Sequent) bool { +// numberSet := 0 +// if state.consequence.f != nil { +// numberSet++ +// } +// if state.consequence.t != nil { +// numberSet++ +// } +// if state.consequence.a != nil { +// numberSet++ +// } +// if state.consequence.s != nil { +// numberSet++ +// } + +// return numberSet < 2 +// } + +// /** +// * Returns what is set in the consequence of the sequent. Either it's the form, +// * the term, or the type. +// * It doesn't check if multiple elements are set, it should be done before. +// **/ +// func whatIsSet(cons Consequence) int { +// var set int +// if cons.f != nil { +// set = formIsSet +// } else if cons.t != nil { +// set = termIsSet +// } else if cons.a != nil { +// set = typeIsSet +// } else if cons.s != nil { +// set = schemeIsSet +// } else { +// set = noConsequence +// } +// return set +// } diff --git a/src/Typing/contexts.go b/src/Typing/contexts.go index ae9faeac..1a78e62f 100644 --- a/src/Typing/contexts.go +++ b/src/Typing/contexts.go @@ -32,310 +32,310 @@ package Typing -import ( - "fmt" - - "github.com/GoelandProver/Goeland/AST" - "github.com/GoelandProver/Goeland/Glob" - "github.com/GoelandProver/Goeland/Lib" -) - -/** - * This file defines the global & local contexts types. - **/ - -/* Stores the local context */ -type LocalContext struct { - vars []AST.Var - typeVars []AST.TypeVar -} - -/* LocalContext methods */ - -/* Adds a var to a copy of the local context and returns it. */ -func (lc LocalContext) addVar(var_ AST.Var) LocalContext { - newLc := lc.copy() - newLc.vars = append(newLc.vars, var_) - return newLc -} - -/* Adds a type var to a copy of the local context and returns it. */ -func (lc LocalContext) addTypeVar(var_ AST.TypeVar) LocalContext { - newLc := lc.copy() - newLc.typeVars = append(newLc.typeVars, var_) - return newLc -} - -/* Copies a LocalContext. */ -func (lc LocalContext) copy() LocalContext { - newVars := make([]AST.Var, len(lc.vars)) - newTypeVars := make([]AST.TypeVar, len(lc.typeVars)) - copy(newVars, lc.vars) - copy(newTypeVars, lc.typeVars) - return LocalContext{vars: newVars, typeVars: newTypeVars} -} - -/* True if all the slices are cleared */ -func (lc LocalContext) isEmpty() bool { - return len(lc.vars)+len(lc.typeVars) == 0 -} - -/** - * Copies the context and pops the first var (and returns it with the new local context). - * It doesn't check if the size of the array is positive, it should be checked before. - **/ -func (lc LocalContext) popVar() (AST.Var, LocalContext) { - newLc := lc.copy() - newLc.vars = newLc.vars[1:] - return lc.vars[0], newLc -} - -/** - * Copies the context and pops the first type var (and returns it with the new local context). - * It doesn't check if the size of the array is positive, it should be checked before. - **/ -func (lc LocalContext) popTypeVar() (AST.TypeVar, LocalContext) { - newLc := lc.copy() - newLc.typeVars = newLc.typeVars[1:] - return lc.typeVars[0], newLc -} - -/* Stores the global context */ -type GlobalContext struct { - primitiveTypes []AST.TypeHint - parameterizedTypes []string - composedType map[string]AST.TypeCross - simpleSchemes map[string][]AST.TypeScheme - polymorphSchemes map[string][]AST.QuantifiedType -} - -/* Copies a GlobalContext into a new variable and returns it. */ -func (gc GlobalContext) copy() GlobalContext { - context := GlobalContext{ - primitiveTypes: make([]AST.TypeHint, len(gc.primitiveTypes)), - parameterizedTypes: make([]string, len(gc.parameterizedTypes)), - simpleSchemes: make(map[string][]AST.TypeScheme), - polymorphSchemes: make(map[string][]AST.QuantifiedType), - } - copy(context.primitiveTypes, gc.primitiveTypes) - copy(context.parameterizedTypes, gc.parameterizedTypes) - - for name, list := range gc.simpleSchemes { - context.simpleSchemes[name] = make([]AST.TypeScheme, len(list)) - copy(context.simpleSchemes[name], list) - } - - for name, list := range gc.polymorphSchemes { - context.polymorphSchemes[name] = make([]AST.QuantifiedType, len(list)) - copy(context.polymorphSchemes[name], list) - } - - return context -} - -/* Gets a simple / polymorphic type scheme from an ID, type variables, and terms */ -func (gc GlobalContext) getTypeScheme( - id AST.Id, - vars []AST.TypeApp, - terms Lib.List[AST.Term], -) (AST.TypeScheme, error) { - args, err := getArgsTypes(gc, terms) - if err != nil { - return nil, err - } - - typeScheme, err := gc.getSimpleTypeScheme(id.GetName(), args) - - if typeScheme == nil { - typeScheme, err = gc.getPolymorphicTypeScheme( - id.GetName(), - len(vars), - terms.Len(), - ) - // Instantiate type scheme with actual types - if typeScheme != nil { - typeScheme = Glob.To[AST.QuantifiedType](typeScheme).Instanciate(vars) - } - } - - if err != nil { - return nil, err - } - - return typeScheme, nil -} - -func flattenCross(ty AST.TypeApp) []AST.TypeApp { - switch nty := ty.(type) { - case AST.TypeCross: - flattened := []AST.TypeApp{} - for _, uty := range nty.GetAllUnderlyingTypes() { - flattened = append(flattened, flattenCross(uty)...) - } - return []AST.TypeApp{AST.MkTypeCross(flattened...)} - } - return []AST.TypeApp{ty} -} - -/* Search for a TypeScheme with the name & the arguments type */ -func (gc GlobalContext) getSimpleTypeScheme(name string, termsType AST.TypeApp) (AST.TypeScheme, error) { - if termsType == nil { - if typeScheme, found := gc.simpleSchemes[name]; found { - return typeScheme[0], nil - } else { - return nil, fmt.Errorf("no constant function with the name %s in the global context", name) - } - } - - termsType = flattenCross(termsType)[0] - if typeSchemeList, found := gc.simpleSchemes[name]; found { - for _, typeScheme := range typeSchemeList { - if AST.GetInputType(typeScheme).Equals(Lib.ComparableList[AST.TypeApp]{termsType}) { - return typeScheme, nil - } - } - } - return nil, fmt.Errorf("no predicate/function with the name %s in the global context and arguments of type %s", name, termsType.ToString()) -} - -/* Gets the polymorphic type scheme corresponding to the input. */ -func (gc GlobalContext) getPolymorphicTypeScheme(name string, varsLen, termsLen int) (AST.TypeScheme, error) { - if typeSchemeList, found := gc.polymorphSchemes[name]; found { - for _, typeScheme := range typeSchemeList { - if termsLen == typeScheme.Size()-1 && varsLen == typeScheme.QuantifiedVarsLen() { - return typeScheme, nil - } - } - } - return nil, fmt.Errorf("no predicate/function with the name %s in the global context", name) -} - -/* Returns true if the TypeHint is found in the context */ -func (gc GlobalContext) isTypeInContext(typeApp AST.TypeScheme) bool { - for _, type_ := range gc.primitiveTypes { - if type_.Equals(typeApp) { - return true - } - } - for _, type_ := range gc.composedType { - if type_.Equals(typeApp) { - return true - } - } - return false -} - -/* Tests if there are no more TypeScheme stored (doesn't check for primitive types) */ -func (gc GlobalContext) isEmpty() bool { - result := true - - for _, app := range gc.simpleSchemes { - result = result && (len(app) == 0) - } - for _, app := range gc.polymorphSchemes { - result = result && (len(app) == 0) - } - - return result -} - -/* Checks if the parameterized types contains the given name */ -func (gc GlobalContext) parameterizedTypesContains(name string) bool { - for _, parameterTypeName := range gc.parameterizedTypes { - if name == parameterTypeName { - return true - } - } - return false -} - -/* Utils */ - -/** - * Creates a global context from all the types / type schemes recorded in the map of types. - * Incrementally verifies if the context is well typed. - * If not, an error is returned. - **/ -func createGlobalContext(context map[string][]AST.App) (GlobalContext, error) { - globalContext := GlobalContext{ - primitiveTypes: []AST.TypeHint{}, - parameterizedTypes: []string{}, - composedType: make(map[string]AST.TypeCross), - simpleSchemes: make(map[string][]AST.TypeScheme), - polymorphSchemes: make(map[string][]AST.QuantifiedType), - } - - // Fill first the primitive types - for name, appList := range context { - if len(appList) == 0 { - globalContext.parameterizedTypes = append(globalContext.parameterizedTypes, name) - } - for _, app := range appList { - if type_, isTypeHint := app.App.(AST.TypeHint); isTypeHint { - if !AST.IsConstant(name) { - globalContext.primitiveTypes = append(globalContext.primitiveTypes, type_) - } - } - } - } - - for name, appList := range context { - // Then, fill everything else - for _, app := range appList { - switch type_ := app.App.(type) { - case AST.TypeHint: - if AST.IsConstant(name) { - globalContext.simpleSchemes[name] = append(globalContext.simpleSchemes[name], type_) - } - case AST.TypeCross: - globalContext.composedType[name] = type_ - case AST.TypeArrow: - globalContext.simpleSchemes[name] = append(globalContext.simpleSchemes[name], type_) - case AST.QuantifiedType: - globalContext.polymorphSchemes[name] = append(globalContext.polymorphSchemes[name], type_) - case AST.ParameterizedType: - globalContext.simpleSchemes[name] = append(globalContext.simpleSchemes[name], type_) - } - if err := incrementalVerificationOfGlobalContext(globalContext.copy(), name, app.App); err != nil { - return GlobalContext{}, err - } - } - } - - if !globalContextIsWellTyped { - globalContextIsWellTyped = true - } - return globalContext, nil -} - -/** - * Triggers rules to verify the global context while it's constructed. - * It will avoid combinatorial explosion on global context well formedness verification. - **/ -func incrementalVerificationOfGlobalContext(globalContext GlobalContext, name string, app AST.TypeScheme) error { - if globalContextIsWellTyped { - return nil - } - - sequent := Sequent{ - globalContext: globalContext, - localContext: LocalContext{}, - } - rec := Reconstruct{err: nil} - proofTree, chan_ := new(ProofTree), make(chan Reconstruct) - - switch type_ := app.(type) { - case AST.TypeCross: - sequent.consequence = Consequence{a: type_} - rec = applyCrossRule(sequent, proofTree, chan_) - case AST.QuantifiedType, AST.TypeArrow: - sequent.consequence = Consequence{s: app} - rec = applySymRule(sequent, proofTree, chan_) - case AST.TypeHint: - if AST.IsConstant(name) { - sequent.consequence = Consequence{a: type_} - rec = applyGlobalTypeVarRule(sequent, proofTree, chan_) - } - } - return rec.err -} +// import ( +// "fmt" + +// "github.com/GoelandProver/Goeland/AST" +// "github.com/GoelandProver/Goeland/Glob" +// "github.com/GoelandProver/Goeland/Lib" +// ) + +// /** +// * This file defines the global & local contexts types. +// **/ + +// /* Stores the local context */ +// type LocalContext struct { +// vars []AST.Var +// typeVars []AST.TypeVar +// } + +// /* LocalContext methods */ + +// /* Adds a var to a copy of the local context and returns it. */ +// func (lc LocalContext) addVar(var_ AST.Var) LocalContext { +// newLc := lc.copy() +// newLc.vars = append(newLc.vars, var_) +// return newLc +// } + +// /* Adds a type var to a copy of the local context and returns it. */ +// func (lc LocalContext) addTypeVar(var_ AST.TypeVar) LocalContext { +// newLc := lc.copy() +// newLc.typeVars = append(newLc.typeVars, var_) +// return newLc +// } + +// /* Copies a LocalContext. */ +// func (lc LocalContext) copy() LocalContext { +// newVars := make([]AST.Var, len(lc.vars)) +// newTypeVars := make([]AST.TypeVar, len(lc.typeVars)) +// copy(newVars, lc.vars) +// copy(newTypeVars, lc.typeVars) +// return LocalContext{vars: newVars, typeVars: newTypeVars} +// } + +// /* True if all the slices are cleared */ +// func (lc LocalContext) isEmpty() bool { +// return len(lc.vars)+len(lc.typeVars) == 0 +// } + +// /** +// * Copies the context and pops the first var (and returns it with the new local context). +// * It doesn't check if the size of the array is positive, it should be checked before. +// **/ +// func (lc LocalContext) popVar() (AST.Var, LocalContext) { +// newLc := lc.copy() +// newLc.vars = newLc.vars[1:] +// return lc.vars[0], newLc +// } + +// /** +// * Copies the context and pops the first type var (and returns it with the new local context). +// * It doesn't check if the size of the array is positive, it should be checked before. +// **/ +// func (lc LocalContext) popTypeVar() (AST.TypeVar, LocalContext) { +// newLc := lc.copy() +// newLc.typeVars = newLc.typeVars[1:] +// return lc.typeVars[0], newLc +// } + +// /* Stores the global context */ +// type GlobalContext struct { +// primitiveTypes []AST.TypeHint +// parameterizedTypes []string +// composedType map[string]AST.TypeCross +// simpleSchemes map[string][]AST.TypeScheme +// polymorphSchemes map[string][]AST.QuantifiedType +// } + +// /* Copies a GlobalContext into a new variable and returns it. */ +// func (gc GlobalContext) copy() GlobalContext { +// context := GlobalContext{ +// primitiveTypes: make([]AST.TypeHint, len(gc.primitiveTypes)), +// parameterizedTypes: make([]string, len(gc.parameterizedTypes)), +// simpleSchemes: make(map[string][]AST.TypeScheme), +// polymorphSchemes: make(map[string][]AST.QuantifiedType), +// } +// copy(context.primitiveTypes, gc.primitiveTypes) +// copy(context.parameterizedTypes, gc.parameterizedTypes) + +// for name, list := range gc.simpleSchemes { +// context.simpleSchemes[name] = make([]AST.TypeScheme, len(list)) +// copy(context.simpleSchemes[name], list) +// } + +// for name, list := range gc.polymorphSchemes { +// context.polymorphSchemes[name] = make([]AST.QuantifiedType, len(list)) +// copy(context.polymorphSchemes[name], list) +// } + +// return context +// } + +// /* Gets a simple / polymorphic type scheme from an ID, type variables, and terms */ +// func (gc GlobalContext) getTypeScheme( +// id AST.Id, +// vars []AST.TypeApp, +// terms Lib.List[AST.Term], +// ) (AST.TypeScheme, error) { +// args, err := getArgsTypes(gc, terms) +// if err != nil { +// return nil, err +// } + +// typeScheme, err := gc.getSimpleTypeScheme(id.GetName(), args) + +// if typeScheme == nil { +// typeScheme, err = gc.getPolymorphicTypeScheme( +// id.GetName(), +// len(vars), +// terms.Len(), +// ) +// // Instantiate type scheme with actual types +// if typeScheme != nil { +// typeScheme = Glob.To[AST.QuantifiedType](typeScheme).Instanciate(vars) +// } +// } + +// if err != nil { +// return nil, err +// } + +// return typeScheme, nil +// } + +// func flattenCross(ty AST.TypeApp) []AST.TypeApp { +// switch nty := ty.(type) { +// case AST.TypeCross: +// flattened := []AST.TypeApp{} +// for _, uty := range nty.GetAllUnderlyingTypes() { +// flattened = append(flattened, flattenCross(uty)...) +// } +// return []AST.TypeApp{AST.MkTypeCross(flattened...)} +// } +// return []AST.TypeApp{ty} +// } + +// /* Search for a TypeScheme with the name & the arguments type */ +// func (gc GlobalContext) getSimpleTypeScheme(name string, termsType AST.TypeApp) (AST.TypeScheme, error) { +// if termsType == nil { +// if typeScheme, found := gc.simpleSchemes[name]; found { +// return typeScheme[0], nil +// } else { +// return nil, fmt.Errorf("no constant function with the name %s in the global context", name) +// } +// } + +// termsType = flattenCross(termsType)[0] +// if typeSchemeList, found := gc.simpleSchemes[name]; found { +// for _, typeScheme := range typeSchemeList { +// if AST.GetInputType(typeScheme).Equals(Lib.ComparableList[AST.TypeApp]{termsType}) { +// return typeScheme, nil +// } +// } +// } +// return nil, fmt.Errorf("no predicate/function with the name %s in the global context and arguments of type %s", name, termsType.ToString()) +// } + +// /* Gets the polymorphic type scheme corresponding to the input. */ +// func (gc GlobalContext) getPolymorphicTypeScheme(name string, varsLen, termsLen int) (AST.TypeScheme, error) { +// if typeSchemeList, found := gc.polymorphSchemes[name]; found { +// for _, typeScheme := range typeSchemeList { +// if termsLen == typeScheme.Size()-1 && varsLen == typeScheme.QuantifiedVarsLen() { +// return typeScheme, nil +// } +// } +// } +// return nil, fmt.Errorf("no predicate/function with the name %s in the global context", name) +// } + +// /* Returns true if the TypeHint is found in the context */ +// func (gc GlobalContext) isTypeInContext(typeApp AST.TypeScheme) bool { +// for _, type_ := range gc.primitiveTypes { +// if type_.Equals(typeApp) { +// return true +// } +// } +// for _, type_ := range gc.composedType { +// if type_.Equals(typeApp) { +// return true +// } +// } +// return false +// } + +// /* Tests if there are no more TypeScheme stored (doesn't check for primitive types) */ +// func (gc GlobalContext) isEmpty() bool { +// result := true + +// for _, app := range gc.simpleSchemes { +// result = result && (len(app) == 0) +// } +// for _, app := range gc.polymorphSchemes { +// result = result && (len(app) == 0) +// } + +// return result +// } + +// /* Checks if the parameterized types contains the given name */ +// func (gc GlobalContext) parameterizedTypesContains(name string) bool { +// for _, parameterTypeName := range gc.parameterizedTypes { +// if name == parameterTypeName { +// return true +// } +// } +// return false +// } + +// /* Utils */ + +// /** +// * Creates a global context from all the types / type schemes recorded in the map of types. +// * Incrementally verifies if the context is well typed. +// * If not, an error is returned. +// **/ +// func createGlobalContext(context map[string][]AST.App) (GlobalContext, error) { +// globalContext := GlobalContext{ +// primitiveTypes: []AST.TypeHint{}, +// parameterizedTypes: []string{}, +// composedType: make(map[string]AST.TypeCross), +// simpleSchemes: make(map[string][]AST.TypeScheme), +// polymorphSchemes: make(map[string][]AST.QuantifiedType), +// } + +// // Fill first the primitive types +// for name, appList := range context { +// if len(appList) == 0 { +// globalContext.parameterizedTypes = append(globalContext.parameterizedTypes, name) +// } +// for _, app := range appList { +// if type_, isTypeHint := app.App.(AST.TypeHint); isTypeHint { +// if !AST.IsConstant(name) { +// globalContext.primitiveTypes = append(globalContext.primitiveTypes, type_) +// } +// } +// } +// } + +// for name, appList := range context { +// // Then, fill everything else +// for _, app := range appList { +// switch type_ := app.App.(type) { +// case AST.TypeHint: +// if AST.IsConstant(name) { +// globalContext.simpleSchemes[name] = append(globalContext.simpleSchemes[name], type_) +// } +// case AST.TypeCross: +// globalContext.composedType[name] = type_ +// case AST.TypeArrow: +// globalContext.simpleSchemes[name] = append(globalContext.simpleSchemes[name], type_) +// case AST.QuantifiedType: +// globalContext.polymorphSchemes[name] = append(globalContext.polymorphSchemes[name], type_) +// case AST.ParameterizedType: +// globalContext.simpleSchemes[name] = append(globalContext.simpleSchemes[name], type_) +// } +// if err := incrementalVerificationOfGlobalContext(globalContext.copy(), name, app.App); err != nil { +// return GlobalContext{}, err +// } +// } +// } + +// if !globalContextIsWellTyped { +// globalContextIsWellTyped = true +// } +// return globalContext, nil +// } + +// /** +// * Triggers rules to verify the global context while it's constructed. +// * It will avoid combinatorial explosion on global context well formedness verification. +// **/ +// func incrementalVerificationOfGlobalContext(globalContext GlobalContext, name string, app AST.TypeScheme) error { +// if globalContextIsWellTyped { +// return nil +// } + +// sequent := Sequent{ +// globalContext: globalContext, +// localContext: LocalContext{}, +// } +// rec := Reconstruct{err: nil} +// proofTree, chan_ := new(ProofTree), make(chan Reconstruct) + +// switch type_ := app.(type) { +// case AST.TypeCross: +// sequent.consequence = Consequence{a: type_} +// rec = applyCrossRule(sequent, proofTree, chan_) +// case AST.QuantifiedType, AST.TypeArrow: +// sequent.consequence = Consequence{s: app} +// rec = applySymRule(sequent, proofTree, chan_) +// case AST.TypeHint: +// if AST.IsConstant(name) { +// sequent.consequence = Consequence{a: type_} +// rec = applyGlobalTypeVarRule(sequent, proofTree, chan_) +// } +// } +// return rec.err +// } diff --git a/src/Typing/form_rules.go b/src/Typing/form_rules.go index e177b4a1..772ec291 100644 --- a/src/Typing/form_rules.go +++ b/src/Typing/form_rules.go @@ -32,203 +32,203 @@ package Typing -import ( - "github.com/GoelandProver/Goeland/AST" - "github.com/GoelandProver/Goeland/Lib" -) - -/** - * This file contains all the rules that the typing system can apply on a formula. - **/ - -/* Applies quantification rule and launches 2 goroutines waiting its children. */ -func applyQuantRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { - // Add rule to prooftree - switch (state.consequence.f).(type) { - case AST.All, AST.AllType: - root.appliedRule = "∀" - case AST.Ex: - root.appliedRule = "∃" - } - - var newForm AST.Form - var varTreated AST.Var - var typeTreated AST.TypeVar - - varInstantiated := false - - switch f := (state.consequence.f).(type) { - case AST.All, AST.Ex: - varTreated, newForm = removeOneVar(state.consequence.f) - varInstantiated = true - case AST.AllType: - v := f.GetVarList()[0] - if len(f.GetVarList()) > 1 { - typeTreated, newForm = v, AST.MakeAllType(f.GetIndex(), f.GetVarList()[1:], f.GetForm()) - } else { - typeTreated, newForm = v, f.GetForm() - } - } - - // Create 2 children: - // 1 - First one with the type of the quantified variable. It should be a TypeApp. - // 2 - Second one with the quantified variable added in the local context. - // => copy the local context and use the function to get the global context (copy or not). - // The underlying form should be gotten to be properly typed. - children := mkQuantChildren(state, varInstantiated, varTreated, typeTreated, newForm) - - // Launch the children in a goroutine, and wait for it to close. - // If one branch closes with an error, then the system is not well-typed. - return reconstructForm(launchChildren(children, root, fatherChan), state.consequence.f) -} - -/* Applies OR or AND rule and launches n goroutines waiting its children */ -func applyNAryRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { - formList := Lib.NewList[AST.Form]() - // Add rule to prooftree - switch f := (state.consequence.f).(type) { - case AST.And: - root.appliedRule = "∧" - formList = f.GetChildFormulas() - case AST.Or: - root.appliedRule = "∨" - formList = f.GetChildFormulas() - } - - // Construct children with all the formulas - children := []Sequent{} - for _, form := range formList.GetSlice() { - children = append(children, Sequent{ - globalContext: state.globalContext, - localContext: state.localContext.copy(), - consequence: Consequence{f: form}, - }) - } - - // Launch the children in a goroutine, and wait for it to close. - // If one branch closes with an error, then the system is not well-typed. - return reconstructForm(launchChildren(children, root, fatherChan), state.consequence.f) -} - -/* Applies => or <=> rule and launches 2 goroutines waiting its children */ -func applyBinaryRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { - var f1, f2 AST.Form - // Add rule to prooftree - switch f := (state.consequence.f).(type) { - case AST.Imp: - root.appliedRule = "⇒" - f1, f2 = f.GetF1(), f.GetF2() - case AST.Equ: - root.appliedRule = "⇔" - f1, f2 = f.GetF1(), f.GetF2() - } - - // Construct children with the 2 formulas - children := []Sequent{ - { - globalContext: state.globalContext, - localContext: state.localContext.copy(), - consequence: Consequence{f: f1}, - }, - { - globalContext: state.globalContext, - localContext: state.localContext.copy(), - consequence: Consequence{f: f2}, - }, - } - - // Launch the children in a goroutine, and wait for it to close. - // If one branch closes with an error, then the system is not well-typed. - return reconstructForm(launchChildren(children, root, fatherChan), state.consequence.f) -} - -/* Applies BOT or TOP rule and does not create a new goroutine */ -func applyBotTopRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { - // Add rule to prooftree - switch (state.consequence.f).(type) { - case AST.Top: - root.appliedRule = "⊤" - case AST.Bot: - root.appliedRule = "⊥" - } - - // Construct children with the contexts - children := []Sequent{ - { - globalContext: state.globalContext, - localContext: state.localContext.copy(), - consequence: Consequence{}, - }, - } - - // If the branch closes with an error, then the system is not well-typed. - return reconstructForm(launchChildren(children, root, fatherChan), state.consequence.f) -} - -func applyNotRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { - // Add rule to prooftree - root.appliedRule = "¬" - form := (state.consequence.f).(AST.Not).GetForm() - - // Construct children with the contexts - children := []Sequent{ - { - globalContext: state.globalContext, - localContext: state.localContext.copy(), - consequence: Consequence{f: form}, - }, - } - - // If the branch closes with an error, then the system is not well-typed. - return reconstructForm(launchChildren(children, root, fatherChan), state.consequence.f) -} - -/** - * Removes the first variable of an exitential or universal form, and returns a - * universal / existential form iff it still possesses other vars. - * Otherwise, it returns the form gotten with GetForm(). - **/ -func removeOneVar(form AST.Form) (AST.Var, AST.Form) { - // It's pretty much the same thing, but I don't have a clue on how to factorize this.. - switch f := form.(type) { - case AST.Ex: - v := f.GetVarList()[0] - if len(f.GetVarList()) > 1 { - return v, AST.MakeEx(f.GetIndex(), f.GetVarList()[1:], f.GetForm()) - } - return v, f.GetForm() - case AST.All: - v := f.GetVarList()[0] - if len(f.GetVarList()) > 1 { - return v, AST.MakeAll(f.GetIndex(), f.GetVarList()[1:], f.GetForm()) - } - return v, f.GetForm() - } - return AST.Var{}, nil -} - -/* Makes the child treating the variable depending on which is set. */ -func mkQuantChildren(state Sequent, varInstantiated bool, varTreated AST.Var, typeTreated AST.TypeVar, newForm AST.Form) []Sequent { - var type_ AST.TypeApp - var newLocalContext LocalContext - if varInstantiated { - type_ = varTreated.GetTypeApp() - newLocalContext = state.localContext.addVar(varTreated) - } else { - type_ = metaType - newLocalContext = state.localContext.addTypeVar(typeTreated) - } - - return []Sequent{ - { - globalContext: state.globalContext, - localContext: state.localContext.copy(), - consequence: Consequence{a: type_}, - }, - { - globalContext: state.globalContext, - localContext: newLocalContext, - consequence: Consequence{f: newForm}, - }, - } -} +// import ( +// "github.com/GoelandProver/Goeland/AST" +// "github.com/GoelandProver/Goeland/Lib" +// ) + +// /** +// * This file contains all the rules that the typing system can apply on a formula. +// **/ + +// /* Applies quantification rule and launches 2 goroutines waiting its children. */ +// func applyQuantRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { +// // Add rule to prooftree +// switch (state.consequence.f).(type) { +// case AST.All, AST.AllType: +// root.appliedRule = "∀" +// case AST.Ex: +// root.appliedRule = "∃" +// } + +// var newForm AST.Form +// var varTreated AST.Var +// var typeTreated AST.TypeVar + +// varInstantiated := false + +// switch f := (state.consequence.f).(type) { +// case AST.All, AST.Ex: +// varTreated, newForm = removeOneVar(state.consequence.f) +// varInstantiated = true +// case AST.AllType: +// v := f.GetVarList()[0] +// if len(f.GetVarList()) > 1 { +// typeTreated, newForm = v, AST.MakeAllType(f.GetIndex(), f.GetVarList()[1:], f.GetForm()) +// } else { +// typeTreated, newForm = v, f.GetForm() +// } +// } + +// // Create 2 children: +// // 1 - First one with the type of the quantified variable. It should be a TypeApp. +// // 2 - Second one with the quantified variable added in the local context. +// // => copy the local context and use the function to get the global context (copy or not). +// // The underlying form should be gotten to be properly typed. +// children := mkQuantChildren(state, varInstantiated, varTreated, typeTreated, newForm) + +// // Launch the children in a goroutine, and wait for it to close. +// // If one branch closes with an error, then the system is not well-typed. +// return reconstructForm(launchChildren(children, root, fatherChan), state.consequence.f) +// } + +// /* Applies OR or AND rule and launches n goroutines waiting its children */ +// func applyNAryRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { +// formList := Lib.NewList[AST.Form]() +// // Add rule to prooftree +// switch f := (state.consequence.f).(type) { +// case AST.And: +// root.appliedRule = "∧" +// formList = f.GetChildFormulas() +// case AST.Or: +// root.appliedRule = "∨" +// formList = f.GetChildFormulas() +// } + +// // Construct children with all the formulas +// children := []Sequent{} +// for _, form := range formList.GetSlice() { +// children = append(children, Sequent{ +// globalContext: state.globalContext, +// localContext: state.localContext.copy(), +// consequence: Consequence{f: form}, +// }) +// } + +// // Launch the children in a goroutine, and wait for it to close. +// // If one branch closes with an error, then the system is not well-typed. +// return reconstructForm(launchChildren(children, root, fatherChan), state.consequence.f) +// } + +// /* Applies => or <=> rule and launches 2 goroutines waiting its children */ +// func applyBinaryRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { +// var f1, f2 AST.Form +// // Add rule to prooftree +// switch f := (state.consequence.f).(type) { +// case AST.Imp: +// root.appliedRule = "⇒" +// f1, f2 = f.GetF1(), f.GetF2() +// case AST.Equ: +// root.appliedRule = "⇔" +// f1, f2 = f.GetF1(), f.GetF2() +// } + +// // Construct children with the 2 formulas +// children := []Sequent{ +// { +// globalContext: state.globalContext, +// localContext: state.localContext.copy(), +// consequence: Consequence{f: f1}, +// }, +// { +// globalContext: state.globalContext, +// localContext: state.localContext.copy(), +// consequence: Consequence{f: f2}, +// }, +// } + +// // Launch the children in a goroutine, and wait for it to close. +// // If one branch closes with an error, then the system is not well-typed. +// return reconstructForm(launchChildren(children, root, fatherChan), state.consequence.f) +// } + +// /* Applies BOT or TOP rule and does not create a new goroutine */ +// func applyBotTopRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { +// // Add rule to prooftree +// switch (state.consequence.f).(type) { +// case AST.Top: +// root.appliedRule = "⊤" +// case AST.Bot: +// root.appliedRule = "⊥" +// } + +// // Construct children with the contexts +// children := []Sequent{ +// { +// globalContext: state.globalContext, +// localContext: state.localContext.copy(), +// consequence: Consequence{}, +// }, +// } + +// // If the branch closes with an error, then the system is not well-typed. +// return reconstructForm(launchChildren(children, root, fatherChan), state.consequence.f) +// } + +// func applyNotRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { +// // Add rule to prooftree +// root.appliedRule = "¬" +// form := (state.consequence.f).(AST.Not).GetForm() + +// // Construct children with the contexts +// children := []Sequent{ +// { +// globalContext: state.globalContext, +// localContext: state.localContext.copy(), +// consequence: Consequence{f: form}, +// }, +// } + +// // If the branch closes with an error, then the system is not well-typed. +// return reconstructForm(launchChildren(children, root, fatherChan), state.consequence.f) +// } + +// /** +// * Removes the first variable of an exitential or universal form, and returns a +// * universal / existential form iff it still possesses other vars. +// * Otherwise, it returns the form gotten with GetForm(). +// **/ +// func removeOneVar(form AST.Form) (AST.Var, AST.Form) { +// // It's pretty much the same thing, but I don't have a clue on how to factorize this.. +// switch f := form.(type) { +// case AST.Ex: +// v := f.GetVarList()[0] +// if len(f.GetVarList()) > 1 { +// return v, AST.MakeEx(f.GetIndex(), f.GetVarList()[1:], f.GetForm()) +// } +// return v, f.GetForm() +// case AST.All: +// v := f.GetVarList()[0] +// if len(f.GetVarList()) > 1 { +// return v, AST.MakeAll(f.GetIndex(), f.GetVarList()[1:], f.GetForm()) +// } +// return v, f.GetForm() +// } +// return AST.Var{}, nil +// } + +// /* Makes the child treating the variable depending on which is set. */ +// func mkQuantChildren(state Sequent, varInstantiated bool, varTreated AST.Var, typeTreated AST.TypeVar, newForm AST.Form) []Sequent { +// var type_ AST.TypeApp +// var newLocalContext LocalContext +// if varInstantiated { +// type_ = varTreated.GetTypeApp() +// newLocalContext = state.localContext.addVar(varTreated) +// } else { +// type_ = metaType +// newLocalContext = state.localContext.addTypeVar(typeTreated) +// } + +// return []Sequent{ +// { +// globalContext: state.globalContext, +// localContext: state.localContext.copy(), +// consequence: Consequence{a: type_}, +// }, +// { +// globalContext: state.globalContext, +// localContext: newLocalContext, +// consequence: Consequence{f: newForm}, +// }, +// } +// } diff --git a/src/Typing/launch_rules.go b/src/Typing/launch_rules.go index 369abc5c..7e78036b 100644 --- a/src/Typing/launch_rules.go +++ b/src/Typing/launch_rules.go @@ -32,146 +32,146 @@ package Typing -import ( - "fmt" - "reflect" - - "github.com/GoelandProver/Goeland/AST" - "github.com/GoelandProver/Goeland/Lib" -) - -/** - * This file manages everything related to parallelism / concurrency. - **/ - -type Reconstruct struct { - result bool - forms Lib.List[AST.Form] - terms Lib.List[AST.Term] - err error -} - -/* Launches the first instance of applyRule. Do this to launch the typing system. */ -func launchRuleApplication(state Sequent, root *ProofTree) (AST.Form, error) { - superFatherChan := make(chan Reconstruct) - go tryApplyRule(state, root, superFatherChan) - res := <-superFatherChan - return treatReturns(res) -} - -/* Launches applyRule and manages the error return. */ -func tryApplyRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) { - select { - case <-fatherChan: // Message from the father received: it can only be a kill order. - default: - // No kill order, it's still properly typed, let's apply the next rules. - reconstruct := applyRule(state, root, fatherChan) - select { - case <-fatherChan: // Kill order received, it's finished anyway. - case fatherChan <- reconstruct: // Otherwise, send result to father. - } - } -} - -/* Launch each sequent in a goroutine if sequent length > 1. */ -func launchChildren(sequents []Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { - if len(sequents) == 1 { - // Do not launch another goroutine if the applied rule has only 1 child. - return applyRule(sequents[0], root.addChildWith(sequents[0]), fatherChan) - } else { - // Create a channel for each child, and launch it in a goroutine. - chanTab := make([](chan Reconstruct), len(sequents)) - for i := range sequents { - childChan := make(chan Reconstruct) - chanTab[i] = childChan - go tryApplyRule(sequents[i], root.addChildWith(sequents[i]), childChan) - } - // If a child dies with an error, stops the typesearch procedure. - return selectSequents(chanTab, fatherChan) - } -} - -/** - * Waits for all the children to close. - * If an error is received, stops the type-search of every children and sends an error - * to the parent. - **/ -func selectSequents(chansTab [](chan Reconstruct), chanQuit chan Reconstruct) Reconstruct { - // Instantiation - cases := makeCases(chansTab, chanQuit) - hasAnswered := make([]bool, len(chansTab)) // Everything to false - remaining, indexQuit := len(chansTab), len(chansTab) - var errorFound error = nil - - forms := make([]AST.Form, len(chansTab)) - terms := Lib.MkList[AST.Term](len(chansTab)) - - // Wait for all children to finish. - for remaining > 0 && errorFound == nil { - index, value, _ := reflect.Select(cases) - remaining-- - if index == indexQuit { - errorFound = fmt.Errorf("father detected an error") - } else { - res := value.Interface().(Reconstruct) - hasAnswered[index] = true - if !res.result { - errorFound = res.err - } else { - // Once the child sends back to the father, it should only have one item. - if res.forms.Len() == 1 { - forms[index] = res.forms.At(0) - } - if res.terms.Len() == 1 { - terms.Upd(index, res.terms.At(0)) - } - } - } - } - - selectCleanup(errorFound, hasAnswered, chansTab) - return Reconstruct{result: errorFound == nil, forms: Lib.MkListV(forms...), terms: terms, err: errorFound} -} - -/* Utils functions for selectSequents */ - -/* Makes the array of cases from the channels */ -func makeCases(chansTab [](chan Reconstruct), chanQuit chan Reconstruct) []reflect.SelectCase { - cases := make([]reflect.SelectCase, len(chansTab)+1) - // Children - for i, chan_ := range chansTab { - cases[i] = reflect.SelectCase{Dir: reflect.SelectRecv, Chan: reflect.ValueOf(chan_)} - } - // Father - cases[len(chansTab)] = reflect.SelectCase{Dir: reflect.SelectRecv, Chan: reflect.ValueOf(chanQuit)} - return cases -} - -/* If an error was found, kills all the children. */ -func selectCleanup(errorFound error, hasAnswered []bool, chansTab [](chan Reconstruct)) { - if errorFound != nil { - for i, answered := range hasAnswered { - if !answered { - select { - case <-chansTab[i]: // Filter out, he already responded - case chansTab[i] <- Reconstruct{result: false, err: errorFound}: // Kill child - } - } - } - } -} - -/* Treats the different return types of the system. */ -func treatReturns(res Reconstruct) (AST.Form, error) { - if !res.result { - return nil, res.err - } else { - if res.forms.Len() == 0 { - return nil, res.err - } - if res.forms.Len() > 1 { - return nil, fmt.Errorf("more than one formula is returned by the typing system") - } - return res.forms.At(0), res.err - } -} +// import ( +// "fmt" +// "reflect" + +// "github.com/GoelandProver/Goeland/AST" +// "github.com/GoelandProver/Goeland/Lib" +// ) + +// /** +// * This file manages everything related to parallelism / concurrency. +// **/ + +// type Reconstruct struct { +// result bool +// forms Lib.List[AST.Form] +// terms Lib.List[AST.Term] +// err error +// } + +// /* Launches the first instance of applyRule. Do this to launch the typing system. */ +// func launchRuleApplication(state Sequent, root *ProofTree) (AST.Form, error) { +// superFatherChan := make(chan Reconstruct) +// go tryApplyRule(state, root, superFatherChan) +// res := <-superFatherChan +// return treatReturns(res) +// } + +// /* Launches applyRule and manages the error return. */ +// func tryApplyRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) { +// select { +// case <-fatherChan: // Message from the father received: it can only be a kill order. +// default: +// // No kill order, it's still properly typed, let's apply the next rules. +// reconstruct := applyRule(state, root, fatherChan) +// select { +// case <-fatherChan: // Kill order received, it's finished anyway. +// case fatherChan <- reconstruct: // Otherwise, send result to father. +// } +// } +// } + +// /* Launch each sequent in a goroutine if sequent length > 1. */ +// func launchChildren(sequents []Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { +// if len(sequents) == 1 { +// // Do not launch another goroutine if the applied rule has only 1 child. +// return applyRule(sequents[0], root.addChildWith(sequents[0]), fatherChan) +// } else { +// // Create a channel for each child, and launch it in a goroutine. +// chanTab := make([](chan Reconstruct), len(sequents)) +// for i := range sequents { +// childChan := make(chan Reconstruct) +// chanTab[i] = childChan +// go tryApplyRule(sequents[i], root.addChildWith(sequents[i]), childChan) +// } +// // If a child dies with an error, stops the typesearch procedure. +// return selectSequents(chanTab, fatherChan) +// } +// } + +// /** +// * Waits for all the children to close. +// * If an error is received, stops the type-search of every children and sends an error +// * to the parent. +// **/ +// func selectSequents(chansTab [](chan Reconstruct), chanQuit chan Reconstruct) Reconstruct { +// // Instantiation +// cases := makeCases(chansTab, chanQuit) +// hasAnswered := make([]bool, len(chansTab)) // Everything to false +// remaining, indexQuit := len(chansTab), len(chansTab) +// var errorFound error = nil + +// forms := make([]AST.Form, len(chansTab)) +// terms := Lib.MkList[AST.Term](len(chansTab)) + +// // Wait for all children to finish. +// for remaining > 0 && errorFound == nil { +// index, value, _ := reflect.Select(cases) +// remaining-- +// if index == indexQuit { +// errorFound = fmt.Errorf("father detected an error") +// } else { +// res := value.Interface().(Reconstruct) +// hasAnswered[index] = true +// if !res.result { +// errorFound = res.err +// } else { +// // Once the child sends back to the father, it should only have one item. +// if res.forms.Len() == 1 { +// forms[index] = res.forms.At(0) +// } +// if res.terms.Len() == 1 { +// terms.Upd(index, res.terms.At(0)) +// } +// } +// } +// } + +// selectCleanup(errorFound, hasAnswered, chansTab) +// return Reconstruct{result: errorFound == nil, forms: Lib.MkListV(forms...), terms: terms, err: errorFound} +// } + +// /* Utils functions for selectSequents */ + +// /* Makes the array of cases from the channels */ +// func makeCases(chansTab [](chan Reconstruct), chanQuit chan Reconstruct) []reflect.SelectCase { +// cases := make([]reflect.SelectCase, len(chansTab)+1) +// // Children +// for i, chan_ := range chansTab { +// cases[i] = reflect.SelectCase{Dir: reflect.SelectRecv, Chan: reflect.ValueOf(chan_)} +// } +// // Father +// cases[len(chansTab)] = reflect.SelectCase{Dir: reflect.SelectRecv, Chan: reflect.ValueOf(chanQuit)} +// return cases +// } + +// /* If an error was found, kills all the children. */ +// func selectCleanup(errorFound error, hasAnswered []bool, chansTab [](chan Reconstruct)) { +// if errorFound != nil { +// for i, answered := range hasAnswered { +// if !answered { +// select { +// case <-chansTab[i]: // Filter out, he already responded +// case chansTab[i] <- Reconstruct{result: false, err: errorFound}: // Kill child +// } +// } +// } +// } +// } + +// /* Treats the different return types of the system. */ +// func treatReturns(res Reconstruct) (AST.Form, error) { +// if !res.result { +// return nil, res.err +// } else { +// if res.forms.Len() == 0 { +// return nil, res.err +// } +// if res.forms.Len() > 1 { +// return nil, fmt.Errorf("more than one formula is returned by the typing system") +// } +// return res.forms.At(0), res.err +// } +// } diff --git a/src/Typing/prooftree_dump.go b/src/Typing/prooftree_dump.go index b2e82f5d..60a50da4 100644 --- a/src/Typing/prooftree_dump.go +++ b/src/Typing/prooftree_dump.go @@ -32,120 +32,120 @@ package Typing -import ( - "encoding/json" - "errors" - "fmt" - "os" - "strings" - - "github.com/GoelandProver/Goeland/AST" - "github.com/GoelandProver/Goeland/Glob" -) - -/** - * This file contains the methods to dump a prooftree in a json. - **/ - -/* Dumps the prooftree in a json. */ -func (root *ProofTree) DumpJson() error { - // Dump folder should be a flag in the future - dump := "../visualization/types/" - // Create a new file - i := 0 - for fileExists(getFileName(dump, i)) { - i++ - } - - f, err := os.OpenFile(getFileName(dump, i), os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) - if err != nil { - return err - } - json, err := root.dump() - - if err != nil { - return err - } - - _, err = f.WriteString(json) - Glob.PrintInfo("DUMP", fmt.Sprintf("Dumped type proof in %s\n", f.Name())) - return err -} - -/* Creates file if not exists, dump informations in it, and calls recursively on each child */ -func (root *ProofTree) dump() (string, error) { - varsString := []string{} - var consequence string = "" - var ts string - if root.typeScheme != nil { - ts = root.typeScheme.ToString() - } - - for _, var_ := range root.sequent.localContext.vars { - varsString = append(varsString, var_.ToString()) - } - for _, var_ := range root.sequent.localContext.typeVars { - varsString = append(varsString, fmt.Sprintf("%s: Type", var_.ToString())) - } - - switch whatIsSet(root.sequent.consequence) { - case formIsSet: - consequence = root.sequent.consequence.f.ToString() - if root.typeScheme == nil { - ts = root.sequent.consequence.f.GetType().ToString() - } - case termIsSet: - consequence = root.sequent.consequence.t.ToString() - if root.typeScheme == nil { - if root.sequent.consequence.t.(AST.TypedTerm).GetTypeHint() == nil { - ts = root.sequent.consequence.t.(AST.TypedTerm).GetTypeApp().ToString() - } else { - ts = root.sequent.consequence.t.(AST.TypedTerm).GetTypeHint().ToString() - } - } - case typeIsSet: - consequence = root.sequent.consequence.a.ToString() - if root.typeScheme == nil { - ts = "Type" - } - } - - childrenProofs := []string{} - - for _, child := range root.children { - bytes, err := child.dump() - if err != nil { - return "", err - } - childrenProofs = append(childrenProofs, bytes) - } - - bytes, err := json.Marshal(&struct { - LocalContext string `json:"localContext"` - Consequence string `json:"consequence"` - TypeScheme string `json:"typeScheme"` - Rule string `json:"rule"` - Children []string `json:"children"` - }{ - LocalContext: strings.Join(varsString, ", "), - Consequence: consequence, - TypeScheme: ts, - Rule: root.appliedRule, - Children: childrenProofs, - }) - - return strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(string(bytes), "\\", ""), "\"{", "{"), "}\"", "}"), err -} - -/* Utils */ - -/* Checks if file exists at given path */ -func fileExists(path string) bool { - _, err := os.Stat(path) - return !errors.Is(err, os.ErrNotExist) -} - -/* Create a formated file name */ -func getFileName(folder string, i int) string { - return fmt.Sprintf("%sproof_%d.json", folder, i) -} +// import ( +// "encoding/json" +// "errors" +// "fmt" +// "os" +// "strings" + +// "github.com/GoelandProver/Goeland/AST" +// "github.com/GoelandProver/Goeland/Glob" +// ) + +// /** +// * This file contains the methods to dump a prooftree in a json. +// **/ + +// /* Dumps the prooftree in a json. */ +// func (root *ProofTree) DumpJson() error { +// // Dump folder should be a flag in the future +// dump := "../visualization/types/" +// // Create a new file +// i := 0 +// for fileExists(getFileName(dump, i)) { +// i++ +// } + +// f, err := os.OpenFile(getFileName(dump, i), os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) +// if err != nil { +// return err +// } +// json, err := root.dump() + +// if err != nil { +// return err +// } + +// _, err = f.WriteString(json) +// Glob.PrintInfo("DUMP", fmt.Sprintf("Dumped type proof in %s\n", f.Name())) +// return err +// } + +// /* Creates file if not exists, dump informations in it, and calls recursively on each child */ +// func (root *ProofTree) dump() (string, error) { +// varsString := []string{} +// var consequence string = "" +// var ts string +// if root.typeScheme != nil { +// ts = root.typeScheme.ToString() +// } + +// for _, var_ := range root.sequent.localContext.vars { +// varsString = append(varsString, var_.ToString()) +// } +// for _, var_ := range root.sequent.localContext.typeVars { +// varsString = append(varsString, fmt.Sprintf("%s: Type", var_.ToString())) +// } + +// switch whatIsSet(root.sequent.consequence) { +// case formIsSet: +// consequence = root.sequent.consequence.f.ToString() +// if root.typeScheme == nil { +// ts = root.sequent.consequence.f.GetType().ToString() +// } +// case termIsSet: +// consequence = root.sequent.consequence.t.ToString() +// if root.typeScheme == nil { +// if root.sequent.consequence.t.(AST.TypedTerm).GetTypeHint() == nil { +// ts = root.sequent.consequence.t.(AST.TypedTerm).GetTypeApp().ToString() +// } else { +// ts = root.sequent.consequence.t.(AST.TypedTerm).GetTypeHint().ToString() +// } +// } +// case typeIsSet: +// consequence = root.sequent.consequence.a.ToString() +// if root.typeScheme == nil { +// ts = "Type" +// } +// } + +// childrenProofs := []string{} + +// for _, child := range root.children { +// bytes, err := child.dump() +// if err != nil { +// return "", err +// } +// childrenProofs = append(childrenProofs, bytes) +// } + +// bytes, err := json.Marshal(&struct { +// LocalContext string `json:"localContext"` +// Consequence string `json:"consequence"` +// TypeScheme string `json:"typeScheme"` +// Rule string `json:"rule"` +// Children []string `json:"children"` +// }{ +// LocalContext: strings.Join(varsString, ", "), +// Consequence: consequence, +// TypeScheme: ts, +// Rule: root.appliedRule, +// Children: childrenProofs, +// }) + +// return strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(string(bytes), "\\", ""), "\"{", "{"), "}\"", "}"), err +// } + +// /* Utils */ + +// /* Checks if file exists at given path */ +// func fileExists(path string) bool { +// _, err := os.Stat(path) +// return !errors.Is(err, os.ErrNotExist) +// } + +// /* Create a formated file name */ +// func getFileName(folder string, i int) string { +// return fmt.Sprintf("%sproof_%d.json", folder, i) +// } diff --git a/src/Typing/rules.go b/src/Typing/rules.go index 80713c65..2850fcc2 100644 --- a/src/Typing/rules.go +++ b/src/Typing/rules.go @@ -32,205 +32,205 @@ package Typing -import ( - "reflect" - - "github.com/GoelandProver/Goeland/AST" - "github.com/GoelandProver/Goeland/Glob" - "github.com/GoelandProver/Goeland/Lib" -) - -/** - * This file contains the functions to create a typing proof tree. - * It defines the TypingProofTree structure and all the rules to check if a - * system is well-typed. - **/ - -/* Stores the consequence of the sequent */ -type Consequence struct { - f AST.Form - t AST.Term - a AST.TypeApp - s AST.TypeScheme -} - -/* A Sequent is formed of a global context, local context, and a formula or a term to type */ -type Sequent struct { - globalContext GlobalContext - localContext LocalContext - consequence Consequence -} - -/* Makes a typing prooftree to output. */ -type ProofTree struct { - sequent Sequent - appliedRule string - typeScheme AST.TypeScheme - children []*ProofTree -} - -/* ProofTree meta-type */ -var metaType AST.TypeHint - -/* ProofTree methods */ - -/* Creates and adds a child to the prooftree and returns it. */ -func (pt *ProofTree) addChildWith(sequent Sequent) *ProofTree { - child := ProofTree{ - sequent: sequent, - children: []*ProofTree{}, - } - pt.children = append(pt.children, &child) - return &child -} - -var globalContextIsWellTyped bool = false - -/** - * Tries to type form. - * If not well-typed, will return an error. - **/ -func WellFormedVerification(form AST.Form, dump bool) error { - // Instanciate meta type - metaType = AST.MkTypeHint("$tType") - - // Second pass to type variables & to give the typevars to functions and predicates - form = SecondPass(form) - - globalContext, err := createGlobalContext(AST.GetGlobalContext()) - if err != nil { - return err - } - - // Sequent creation - state := Sequent{ - globalContext: globalContext, - localContext: LocalContext{vars: []AST.Var{}, typeVars: []AST.TypeVar{}}, - consequence: Consequence{f: form}, - } - - // Prooftree creation - root := ProofTree{ - sequent: state, - children: []*ProofTree{}, - } - - // Launch the typing system - _, err = launchRuleApplication(state, &root) - - // Dump prooftree in json if it's asked & there is no error - if dump && err == nil { - err = root.DumpJson() - } - - return err -} - -/* Reconstructs a Form depending on what the children has returned */ -func reconstructForm(reconstruction Reconstruct, baseForm AST.Form) Reconstruct { - if !reconstruction.result { - return reconstruction - } - - var f AST.Form - switch form := baseForm.(type) { - case AST.All: - f = AST.MakeAll(form.GetIndex(), form.GetVarList(), unquantify(reconstruction.forms.At(1), form)) - case AST.AllType: - f = AST.MakeAllType(form.GetIndex(), form.GetVarList(), unquantify(reconstruction.forms.At(1), form)) - case AST.Ex: - f = AST.MakeEx(form.GetIndex(), form.GetVarList(), unquantify(reconstruction.forms.At(1), form)) - case AST.And: - f = AST.MakeAnd(form.GetIndex(), reconstruction.forms) - case AST.Or: - f = AST.MakeOr(form.GetIndex(), reconstruction.forms) - case AST.Imp: - f = AST.MakeImp(form.GetIndex(), reconstruction.forms.At(0), reconstruction.forms.At(1)) - case AST.Equ: - f = AST.MakeEqu(form.GetIndex(), reconstruction.forms.At(0), reconstruction.forms.At(1)) - case AST.Not: - f = AST.MakeNot(form.GetIndex(), reconstruction.forms.At(0)) - case AST.Pred: - // The len(form.GetTypeVars()) first children launched are children for typevars. - // So the len(form.GetTypeVars()) first children will return - if reconstruction.terms.Len() > len(form.GetTypeVars()) { - terms := Lib.MkListV(reconstruction.terms.Get( - len(form.GetTypeVars()), - reconstruction.terms.Len(), - )...) - f = AST.MakePred( - form.GetIndex(), - form.GetID(), - terms, - form.GetTypeVars(), - form.GetType(), - ) - } else { - f = AST.MakePred( - form.GetIndex(), - form.GetID(), - Lib.NewList[AST.Term](), - form.GetTypeVars(), - form.GetType(), - ) - } - case AST.Top, AST.Bot: - f = baseForm - } - - return Reconstruct{result: true, forms: Lib.MkListV(f), err: nil} -} - -/* Reconstructs a Term depending on what the children has returned */ -func reconstructTerm(reconstruction Reconstruct, baseTerm AST.Term) Reconstruct { - if !reconstruction.result { - return reconstruction - } - - // fun: reconstruct with children terms - if Glob.Is[AST.Fun](baseTerm) { - termFun := Glob.To[AST.Fun](baseTerm) - var fun AST.Fun - // The len(form.GetTypeVars()) first children launched are children for typevars. - // So the len(form.GetTypeVars()) first children will return - if reconstruction.terms.Len() > len(termFun.GetTypeVars()) { - terms := Lib.MkListV(reconstruction.terms.Get( - len(termFun.GetTypeVars()), - reconstruction.terms.Len(), - )...) - fun = AST.MakerFun( - termFun.GetID(), - terms, - termFun.GetTypeVars(), - termFun.GetTypeHint(), - ) - } else { - fun = AST.MakerFun( - termFun.GetID(), - Lib.NewList[AST.Term](), - termFun.GetTypeVars(), - termFun.GetTypeHint(), - ) - } - return Reconstruct{result: true, terms: Lib.MkListV[AST.Term](fun), err: nil} - } - - return Reconstruct{result: true, terms: Lib.MkListV(baseTerm), err: nil} -} - -/* Utils for reconstructions function */ - -/* Removes all the quantifiers of form of the same type of quant. */ -func unquantify(form AST.Form, quant AST.Form) AST.Form { - for reflect.TypeOf(form) == reflect.TypeOf(quant) { - switch quant.(type) { - case AST.All: - form = Glob.To[AST.All](form).GetForm() - case AST.AllType: - form = Glob.To[AST.AllType](form).GetForm() - case AST.Ex: - form = Glob.To[AST.Ex](form).GetForm() - } - } - return form -} +// import ( +// "reflect" + +// "github.com/GoelandProver/Goeland/AST" +// "github.com/GoelandProver/Goeland/Glob" +// "github.com/GoelandProver/Goeland/Lib" +// ) + +// /** +// * This file contains the functions to create a typing proof tree. +// * It defines the TypingProofTree structure and all the rules to check if a +// * system is well-typed. +// **/ + +// /* Stores the consequence of the sequent */ +// type Consequence struct { +// f AST.Form +// t AST.Term +// a AST.TypeApp +// s AST.TypeScheme +// } + +// /* A Sequent is formed of a global context, local context, and a formula or a term to type */ +// type Sequent struct { +// globalContext GlobalContext +// localContext LocalContext +// consequence Consequence +// } + +// /* Makes a typing prooftree to output. */ +// type ProofTree struct { +// sequent Sequent +// appliedRule string +// typeScheme AST.TypeScheme +// children []*ProofTree +// } + +// /* ProofTree meta-type */ +// var metaType AST.TypeHint + +// /* ProofTree methods */ + +// /* Creates and adds a child to the prooftree and returns it. */ +// func (pt *ProofTree) addChildWith(sequent Sequent) *ProofTree { +// child := ProofTree{ +// sequent: sequent, +// children: []*ProofTree{}, +// } +// pt.children = append(pt.children, &child) +// return &child +// } + +// var globalContextIsWellTyped bool = false + +// /** +// * Tries to type form. +// * If not well-typed, will return an error. +// **/ +// func WellFormedVerification(form AST.Form, dump bool) error { +// // Instanciate meta type +// metaType = AST.MkTypeHint("$tType") + +// // Second pass to type variables & to give the typevars to functions and predicates +// form = SecondPass(form) + +// globalContext, err := createGlobalContext(AST.GetGlobalContext()) +// if err != nil { +// return err +// } + +// // Sequent creation +// state := Sequent{ +// globalContext: globalContext, +// localContext: LocalContext{vars: []AST.Var{}, typeVars: []AST.TypeVar{}}, +// consequence: Consequence{f: form}, +// } + +// // Prooftree creation +// root := ProofTree{ +// sequent: state, +// children: []*ProofTree{}, +// } + +// // Launch the typing system +// _, err = launchRuleApplication(state, &root) + +// // Dump prooftree in json if it's asked & there is no error +// if dump && err == nil { +// err = root.DumpJson() +// } + +// return err +// } + +// /* Reconstructs a Form depending on what the children has returned */ +// func reconstructForm(reconstruction Reconstruct, baseForm AST.Form) Reconstruct { +// if !reconstruction.result { +// return reconstruction +// } + +// var f AST.Form +// switch form := baseForm.(type) { +// case AST.All: +// f = AST.MakeAll(form.GetIndex(), form.GetVarList(), unquantify(reconstruction.forms.At(1), form)) +// case AST.AllType: +// f = AST.MakeAllType(form.GetIndex(), form.GetVarList(), unquantify(reconstruction.forms.At(1), form)) +// case AST.Ex: +// f = AST.MakeEx(form.GetIndex(), form.GetVarList(), unquantify(reconstruction.forms.At(1), form)) +// case AST.And: +// f = AST.MakeAnd(form.GetIndex(), reconstruction.forms) +// case AST.Or: +// f = AST.MakeOr(form.GetIndex(), reconstruction.forms) +// case AST.Imp: +// f = AST.MakeImp(form.GetIndex(), reconstruction.forms.At(0), reconstruction.forms.At(1)) +// case AST.Equ: +// f = AST.MakeEqu(form.GetIndex(), reconstruction.forms.At(0), reconstruction.forms.At(1)) +// case AST.Not: +// f = AST.MakeNot(form.GetIndex(), reconstruction.forms.At(0)) +// case AST.Pred: +// // The len(form.GetTypeVars()) first children launched are children for typevars. +// // So the len(form.GetTypeVars()) first children will return +// if reconstruction.terms.Len() > len(form.GetTypeVars()) { +// terms := Lib.MkListV(reconstruction.terms.Get( +// len(form.GetTypeVars()), +// reconstruction.terms.Len(), +// )...) +// f = AST.MakePred( +// form.GetIndex(), +// form.GetID(), +// terms, +// form.GetTypeVars(), +// form.GetType(), +// ) +// } else { +// f = AST.MakePred( +// form.GetIndex(), +// form.GetID(), +// Lib.NewList[AST.Term](), +// form.GetTypeVars(), +// form.GetType(), +// ) +// } +// case AST.Top, AST.Bot: +// f = baseForm +// } + +// return Reconstruct{result: true, forms: Lib.MkListV(f), err: nil} +// } + +// /* Reconstructs a Term depending on what the children has returned */ +// func reconstructTerm(reconstruction Reconstruct, baseTerm AST.Term) Reconstruct { +// if !reconstruction.result { +// return reconstruction +// } + +// // fun: reconstruct with children terms +// if Glob.Is[AST.Fun](baseTerm) { +// termFun := Glob.To[AST.Fun](baseTerm) +// var fun AST.Fun +// // The len(form.GetTypeVars()) first children launched are children for typevars. +// // So the len(form.GetTypeVars()) first children will return +// if reconstruction.terms.Len() > len(termFun.GetTypeVars()) { +// terms := Lib.MkListV(reconstruction.terms.Get( +// len(termFun.GetTypeVars()), +// reconstruction.terms.Len(), +// )...) +// fun = AST.MakerFun( +// termFun.GetID(), +// terms, +// termFun.GetTypeVars(), +// termFun.GetTypeHint(), +// ) +// } else { +// fun = AST.MakerFun( +// termFun.GetID(), +// Lib.NewList[AST.Term](), +// termFun.GetTypeVars(), +// termFun.GetTypeHint(), +// ) +// } +// return Reconstruct{result: true, terms: Lib.MkListV[AST.Term](fun), err: nil} +// } + +// return Reconstruct{result: true, terms: Lib.MkListV(baseTerm), err: nil} +// } + +// /* Utils for reconstructions function */ + +// /* Removes all the quantifiers of form of the same type of quant. */ +// func unquantify(form AST.Form, quant AST.Form) AST.Form { +// for reflect.TypeOf(form) == reflect.TypeOf(quant) { +// switch quant.(type) { +// case AST.All: +// form = Glob.To[AST.All](form).GetForm() +// case AST.AllType: +// form = Glob.To[AST.AllType](form).GetForm() +// case AST.Ex: +// form = Glob.To[AST.Ex](form).GetForm() +// } +// } +// return form +// } diff --git a/src/Typing/term_rules.go b/src/Typing/term_rules.go index 62ae0d6c..ced4119e 100644 --- a/src/Typing/term_rules.go +++ b/src/Typing/term_rules.go @@ -32,184 +32,185 @@ package Typing -import ( - "fmt" - - "github.com/GoelandProver/Goeland/AST" - "github.com/GoelandProver/Goeland/Lib" -) - -/** - * This file contains the rules for typing terms, and also the App rule. - * The App rule is used for predicates and functions. - **/ - -/* Applies the App rule for predicates or functions */ -func applyAppRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { - var index int - var id AST.Id - var terms Lib.List[AST.Term] - var vars []AST.TypeApp - - if whatIsSet(state.consequence) == formIsSet { - index = (state.consequence.f).(AST.Pred).GetIndex() - id = (state.consequence.f).(AST.Pred).GetID() - terms = (state.consequence.f).(AST.Pred).GetArgs() - vars = (state.consequence.f).(AST.Pred).GetTypeVars() - } else { - id = (state.consequence.t).(AST.Fun).GetID() - terms = (state.consequence.t).(AST.Fun).GetArgs() - vars = (state.consequence.t).(AST.Fun).GetTypeVars() - } - - root.appliedRule = "App" - - // Search for the ID in the global context - typeScheme, err := state.globalContext.getTypeScheme(id, vars, terms) - if err != nil { - return Reconstruct{ - result: false, - err: err, - } - } - - // Affect new type scheme to the prooftree - root.typeScheme = typeScheme - primitives := typeScheme.GetPrimitives() - - // Type predicate or function - if whatIsSet(state.consequence) == formIsSet { - fTyped := AST.MakePred(index, id, terms, vars, typeScheme) - return reconstructForm(launchChildren( - createAppChildren(state, vars, terms, primitives), - root, - fatherChan, - ), fTyped) - } else { - fTyped := AST.MakerFun(id, terms, vars, typeScheme) - return reconstructTerm(launchChildren(createAppChildren(state, vars, terms, primitives), root, fatherChan), fTyped) - } -} - -/* Applies the Var rule for a term variable. */ -func applyVarRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { - // Add applied rule to the prooftree - root.appliedRule = "Var" - - // Find current variable in the local context - if _, ok := getTermFromLocalContext(state.localContext, state.consequence.t); !ok { - return Reconstruct{ - result: false, - err: fmt.Errorf("term %s not found in the local context", state.consequence.t.ToString()), - } - } - - // No consequence: next rule is the WF rule. - children := []Sequent{ - { - globalContext: state.globalContext, - localContext: state.localContext.copy(), - consequence: Consequence{}, - }, - } - - return reconstructTerm(launchChildren(children, root, fatherChan), state.consequence.t) -} - -/* Utils functions */ - -/** - * Takes all the types of the terms and makes a cross product of everything - **/ -func getArgsTypes( - context GlobalContext, - terms Lib.List[AST.Term], -) (AST.TypeApp, error) { - if terms.Len() == 0 { - return nil, nil - } - - var types []AST.TypeApp - - for _, term := range terms.GetSlice() { - switch tmpTerm := term.(type) { - case AST.Fun: - typeScheme, err := context.getTypeScheme( - tmpTerm.GetID(), - tmpTerm.GetTypeVars(), - tmpTerm.GetArgs(), - ) - if err != nil { - return nil, err - } - if typeScheme == nil { - return nil, fmt.Errorf("function %s not found in global context", tmpTerm.GetName()) - } - types = append(types, AST.GetOutType(typeScheme)) - case AST.Var: - // Variables can't be of type TypeScheme, so this line shouldn't fail. - types = append(types, tmpTerm.GetTypeApp()) - // There shouldn't be Metas yet. - case AST.Meta: - debug(Lib.MkLazy(func() string { return "Found a Meta while typing everything." })) - // ID is filtered out - } - } - - if len(types) == 1 { - return types[0], nil - } - typeCross := AST.MkTypeCross(types[0], types[1]) - for i := 2; i < len(types); i += 1 { - typeCross = AST.MkTypeCross(typeCross, types[i]) - } - return typeCross, nil -} - -/* Creates children for app rule */ -func createAppChildren( - state Sequent, - vars []AST.TypeApp, - terms Lib.List[AST.Term], - primitives []AST.TypeApp, -) []Sequent { - children := []Sequent{} - - // 1 for each type in the vars - for _, var_ := range vars { - children = append(children, Sequent{ - globalContext: state.globalContext, - localContext: state.localContext.copy(), - consequence: Consequence{a: var_}, - }) - } - - // 1 for each term - for i, term := range terms.GetSlice() { - switch t := term.(type) { - case AST.Fun: - term = AST.MakerFun(t.GetID(), t.GetArgs(), t.GetTypeVars(), primitives[i].(AST.TypeScheme)) - case AST.Meta: - term = AST.MakeMeta(t.GetIndex(), t.GetOccurence(), t.GetName(), t.GetFormula(), primitives[i]) - case AST.Var: - term = AST.MakeVar(t.GetIndex(), t.GetName(), primitives[i]) - } - children = append(children, Sequent{ - globalContext: state.globalContext, - localContext: state.localContext.copy(), - consequence: Consequence{t: term}, - }) - } - - return children -} - -/* Finds the given term in the local context, returns false if it couldn't */ -func getTermFromLocalContext(localContext LocalContext, term AST.Term) (AST.Var, bool) { - for _, var_ := range localContext.vars { - if var_.Equals(term) { - return var_, true - } - } - return AST.Var{}, false -} +// import ( +// "fmt" + +// "github.com/GoelandProver/Goeland/AST" +// "github.com/GoelandProver/Goeland/Glob" +// "github.com/GoelandProver/Goeland/Lib" +// ) + +// /** +// * This file contains the rules for typing terms, and also the App rule. +// * The App rule is used for predicates and functions. +// **/ + +// /* Applies the App rule for predicates or functions */ +// func applyAppRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { +// var index int +// var id AST.Id +// var terms Lib.List[AST.Term] +// var vars []AST.TypeApp + +// if whatIsSet(state.consequence) == formIsSet { +// index = (state.consequence.f).(AST.Pred).GetIndex() +// id = (state.consequence.f).(AST.Pred).GetID() +// terms = (state.consequence.f).(AST.Pred).GetArgs() +// vars = (state.consequence.f).(AST.Pred).GetTypeVars() +// } else { +// id = (state.consequence.t).(AST.Fun).GetID() +// terms = (state.consequence.t).(AST.Fun).GetArgs() +// vars = (state.consequence.t).(AST.Fun).GetTypeVars() +// } + +// root.appliedRule = "App" + +// // Search for the ID in the global context +// typeScheme, err := state.globalContext.getTypeScheme(id, vars, terms) +// if err != nil { +// return Reconstruct{ +// result: false, +// err: err, +// } +// } + +// // Affect new type scheme to the prooftree +// root.typeScheme = typeScheme +// primitives := typeScheme.GetPrimitives() + +// // Type predicate or function +// if whatIsSet(state.consequence) == formIsSet { +// fTyped := AST.MakePred(index, id, terms, vars, typeScheme) +// return reconstructForm(launchChildren( +// createAppChildren(state, vars, terms, primitives), +// root, +// fatherChan, +// ), fTyped) +// } else { +// fTyped := AST.MakerFun(id, terms, vars, typeScheme) +// return reconstructTerm(launchChildren(createAppChildren(state, vars, terms, primitives), root, fatherChan), fTyped) +// } +// } + +// /* Applies the Var rule for a term variable. */ +// func applyVarRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { +// // Add applied rule to the prooftree +// root.appliedRule = "Var" + +// // Find current variable in the local context +// if _, ok := getTermFromLocalContext(state.localContext, state.consequence.t); !ok { +// return Reconstruct{ +// result: false, +// err: fmt.Errorf("term %s not found in the local context", state.consequence.t.ToString()), +// } +// } + +// // No consequence: next rule is the WF rule. +// children := []Sequent{ +// { +// globalContext: state.globalContext, +// localContext: state.localContext.copy(), +// consequence: Consequence{}, +// }, +// } + +// return reconstructTerm(launchChildren(children, root, fatherChan), state.consequence.t) +// } + +// /* Utils functions */ + +// /** +// * Takes all the types of the terms and makes a cross product of everything +// **/ +// func getArgsTypes( +// context GlobalContext, +// terms Lib.List[AST.Term], +// ) (AST.TypeApp, error) { +// if terms.Len() == 0 { +// return nil, nil +// } + +// var types []AST.TypeApp + +// for _, term := range terms.GetSlice() { +// switch tmpTerm := term.(type) { +// case AST.Fun: +// typeScheme, err := context.getTypeScheme( +// tmpTerm.GetID(), +// tmpTerm.GetTypeVars(), +// tmpTerm.GetArgs(), +// ) +// if err != nil { +// return nil, err +// } +// if typeScheme == nil { +// return nil, fmt.Errorf("function %s not found in global context", tmpTerm.GetName()) +// } +// types = append(types, AST.GetOutType(typeScheme)) +// case AST.Var: +// // Variables can't be of type TypeScheme, so this line shouldn't fail. +// types = append(types, tmpTerm.GetTypeApp()) +// // There shouldn't be Metas yet. +// case AST.Meta: +// Glob.PrintDebug("GAT", Lib.MkLazy(func() string { return "Found a Meta while typing everything." })) +// // ID is filtered out +// } +// } + +// if len(types) == 1 { +// return types[0], nil +// } +// typeCross := AST.MkTypeCross(types[0], types[1]) +// for i := 2; i < len(types); i += 1 { +// typeCross = AST.MkTypeCross(typeCross, types[i]) +// } +// return typeCross, nil +// } + +// /* Creates children for app rule */ +// func createAppChildren( +// state Sequent, +// vars []AST.TypeApp, +// terms Lib.List[AST.Term], +// primitives []AST.TypeApp, +// ) []Sequent { +// children := []Sequent{} + +// // 1 for each type in the vars +// for _, var_ := range vars { +// children = append(children, Sequent{ +// globalContext: state.globalContext, +// localContext: state.localContext.copy(), +// consequence: Consequence{a: var_}, +// }) +// } + +// // 1 for each term +// for i, term := range terms.GetSlice() { +// switch t := term.(type) { +// case AST.Fun: +// term = AST.MakerFun(t.GetID(), t.GetArgs(), t.GetTypeVars(), primitives[i].(AST.TypeScheme)) +// case AST.Meta: +// term = AST.MakeMeta(t.GetIndex(), t.GetOccurence(), t.GetName(), t.GetFormula(), primitives[i]) +// case AST.Var: +// term = AST.MakeVar(t.GetIndex(), t.GetName(), primitives[i]) +// } +// children = append(children, Sequent{ +// globalContext: state.globalContext, +// localContext: state.localContext.copy(), +// consequence: Consequence{t: term}, +// }) +// } + +// return children +// } + +// /* Finds the given term in the local context, returns false if it couldn't */ +// func getTermFromLocalContext(localContext LocalContext, term AST.Term) (AST.Var, bool) { +// for _, var_ := range localContext.vars { +// if var_.Equals(term) { +// return var_, true +// } +// } +// return AST.Var{}, false +// } diff --git a/src/Typing/type.go b/src/Typing/type.go index 2d530bef..9d64162c 100644 --- a/src/Typing/type.go +++ b/src/Typing/type.go @@ -32,165 +32,159 @@ package Typing -import ( - "github.com/GoelandProver/Goeland/AST" - "github.com/GoelandProver/Goeland/Glob" - "github.com/GoelandProver/Goeland/Lib" -) - -var debug Glob.Debugger - -func InitDebugger() { - debug = Glob.CreateDebugger("typing") -} - -/** - * This file implements a second pass on the given formula to: - * - Type the variables - * - Give a type to the polymorph predicates / functions - **/ - -func SecondPass(form AST.Form) AST.Form { - after := secondPassAux(form, []AST.Var{}, []AST.TypeApp{}) - return after -} - -func secondPassAux(form AST.Form, vars []AST.Var, types []AST.TypeApp) AST.Form { - switch f := form.(type) { - case AST.Pred: - terms := nArySecondPassTerms(f.GetArgs(), vars, types) - - // Special case: defined predicate. We need to infer types. - if f.GetID().Equals(AST.Id_eq) { - return AST.MakePred( - f.GetIndex(), - f.GetID(), - terms, - []AST.TypeApp{ - AST.GetOutType( - Glob.To[AST.TypedTerm, AST.Term](terms.At(0)).GetTypeHint(), - )}) - } - - // Real case: classical predicate, it should be given - return AST.MakePred(f.GetIndex(), f.GetID(), terms, f.GetTypeVars()) - case AST.And: - return AST.MakeAnd(f.GetIndex(), nArySecondPass(f.GetChildFormulas(), vars, types)) - case AST.Or: - return AST.MakeOr(f.GetIndex(), nArySecondPass(f.GetChildFormulas(), vars, types)) - case AST.Imp: - return AST.MakeImp(f.GetIndex(), secondPassAux(f.GetF1(), vars, types), secondPassAux(f.GetF2(), vars, types)) - case AST.Equ: - return AST.MakeEqu(f.GetIndex(), secondPassAux(f.GetF1(), vars, types), secondPassAux(f.GetF2(), vars, types)) - case AST.Not: - return AST.MakeNot(f.GetIndex(), secondPassAux(f.GetForm(), vars, types)) - case AST.All: - return AST.MakeAll(f.GetIndex(), f.GetVarList(), secondPassAux(f.GetForm(), append(vars, f.GetVarList()...), types)) - case AST.Ex: - return AST.MakeEx(f.GetIndex(), f.GetVarList(), secondPassAux(f.GetForm(), append(vars, f.GetVarList()...), types)) - case AST.AllType: - return AST.MakeAllType(f.GetIndex(), f.GetVarList(), secondPassAux(f.GetForm(), vars, append(types, Glob.ConvertList[AST.TypeVar, AST.TypeApp](f.GetVarList())...))) - } - return form -} - -func secondPassTerm(term AST.Term, vars []AST.Var, types []AST.TypeApp) AST.Term { - switch t := term.(type) { - case AST.Fun: - terms := nArySecondPassTerms(t.GetArgs(), vars, types) - - // - It's a function - outType := func(term AST.Term) AST.TypeApp { - return AST.GetOutType(Glob.To[AST.TypedTerm](term).GetTypeHint()) - } - - termsType := []AST.TypeApp{} - for _, tm := range terms.GetSlice() { - termsType = append(termsType, outType(tm)) - } - - return AST.MakerFun(t.GetID(), terms, t.GetTypeVars(), - getTypeOfFunction(t.GetName(), t.GetTypeVars(), termsType)) - - case AST.Var: - return t - } - return term -} - -func nArySecondPass(forms Lib.List[AST.Form], vars []AST.Var, types []AST.TypeApp) Lib.List[AST.Form] { - res := Lib.NewList[AST.Form]() - - for _, form := range forms.GetSlice() { - res.Append(secondPassAux(form, vars, types)) - } - - return res -} - -func nArySecondPassTerms( - terms Lib.List[AST.Term], - vars []AST.Var, - types []AST.TypeApp, -) Lib.List[AST.Term] { - resTerms := Lib.NewList[AST.Term]() - - for _, term := range terms.GetSlice() { - t := secondPassTerm(term, vars, types) - - if t != nil { - resTerms.Append(t) - } - } - - return resTerms -} - -func getTypeOfFunction(name string, vars []AST.TypeApp, termsType []AST.TypeApp) AST.TypeScheme { - // Build TypeCross from termsType - var tt []AST.TypeApp - if len(termsType) >= 2 { - tc := AST.MkTypeCross(termsType[0], termsType[1]) - for i := 2; i < len(termsType); i += 1 { - tc = AST.MkTypeCross(tc, termsType[i]) - } - tt = []AST.TypeApp{tc} - } else { - tt = termsType - } - - simpleTypeScheme := AST.GetType(name, tt...) - if simpleTypeScheme != nil { - if Glob.Is[AST.QuantifiedType](simpleTypeScheme) { - return Glob.To[AST.QuantifiedType](simpleTypeScheme).Instanciate(vars) - } - return simpleTypeScheme - } - - typeScheme := AST.GetPolymorphicType(name, len(vars), len(termsType)) - - if typeScheme != nil { - // Instantiate type scheme with actual types - typeScheme = Glob.To[AST.QuantifiedType](typeScheme).Instanciate(vars) - } else { - // As only distinct objects are here, it should work with only this. - // I leave the other condition if others weirderies are found later. - if len(termsType) == 0 { - AST.SaveConstant(name, Glob.To[AST.TypeApp](AST.DefaultFunType(0))) - } - /* - else { - type_ := DefaultFunType(len(termsType)) - if len(termsType) == 1 { - SaveTypeScheme(name, GetInputType(type_)[0], GetOutType(type_)) - } else { - SaveTypeScheme(name, AST.MkTypeCross(GetInputType(type_)...), GetOutType(type_)) - } - } - */ - typeScheme = AST.DefaultFunType(0) - - } - - return typeScheme -} +// import ( +// "github.com/GoelandProver/Goeland/AST" +// "github.com/GoelandProver/Goeland/Glob" +// "github.com/GoelandProver/Goeland/Lib" +// ) + +// /** +// * This file implements a second pass on the given formula to: +// * - Type the variables +// * - Give a type to the polymorph predicates / functions +// **/ + +// func SecondPass(form AST.Form) AST.Form { +// after := secondPassAux(form, []AST.Var{}, []AST.TypeApp{}) +// return after +// } + +// func secondPassAux(form AST.Form, vars []AST.Var, types []AST.TypeApp) AST.Form { +// switch f := form.(type) { +// case AST.Pred: +// terms := nArySecondPassTerms(f.GetArgs(), vars, types) + +// // Special case: defined predicate. We need to infer types. +// if f.GetID().Equals(AST.Id_eq) { +// return AST.MakePred( +// f.GetIndex(), +// f.GetID(), +// terms, +// []AST.TypeApp{ +// AST.GetOutType( +// Glob.To[AST.TypedTerm, AST.Term](terms.At(0)).GetTypeHint(), +// )}) +// } + +// // Real case: classical predicate, it should be given +// return AST.MakePred(f.GetIndex(), f.GetID(), terms, f.GetTypeVars()) +// case AST.And: +// return AST.MakeAnd(f.GetIndex(), nArySecondPass(f.GetChildFormulas(), vars, types)) +// case AST.Or: +// return AST.MakeOr(f.GetIndex(), nArySecondPass(f.Get, vars, types)) +// case AST.Imp: +// return AST.MakeImp(f.GetIndex(), secondPassAux(f.GetF1(), vars, types), secondPassAux(f.GetF2(), vars, types)) +// case AST.Equ: +// return AST.MakeEqu(f.GetIndex(), secondPassAux(f.GetF1(), vars, types), secondPassAux(f.GetF2(), vars, types)) +// case AST.Not: +// return AST.MakeNot(f.GetIndex(), secondPassAux(f.GetForm(), vars, types)) +// case AST.All: +// return AST.MakeAll(f.GetIndex(), f.GetVarList(), secondPassAux(f.GetForm(), append(vars, f.GetVarList()...), types)) +// case AST.Ex: +// return AST.MakeEx(f.GetIndex(), f.GetVarList(), secondPassAux(f.GetForm(), append(vars, f.GetVarList()...), types)) +// case AST.AllType: +// return AST.MakeAllType(f.GetIndex(), f.GetVarList(), secondPassAux(f.GetForm(), vars, append(types, Glob.ConvertList[AST.TypeVar, AST.TypeApp](f.GetVarList())...))) +// } +// return form +// } + +// func secondPassTerm(term AST.Term, vars []AST.Var, types []AST.TypeApp) AST.Term { +// switch t := term.(type) { +// case AST.Fun: +// terms := nArySecondPassTerms(t.GetArgs(), vars, types) + +// // - It's a function +// outType := func(term AST.Term) AST.TypeApp { +// return AST.GetOutType(Glob.To[AST.TypedTerm](term).GetTypeHint()) +// } + +// termsType := []AST.TypeApp{} +// for _, tm := range terms.GetSlice() { +// termsType = append(termsType, outType(tm)) +// } + +// return AST.MakerFun(t.GetID(), terms, t.GetTypeVars(), +// getTypeOfFunction(t.GetName(), t.GetTypeVars(), termsType)) + +// case AST.Var: +// return t +// } +// return term +// } + +// func nArySecondPass(forms Lib.List[AST.Form], vars []AST.Var, types []AST.TypeApp) Lib.List[AST.Form] { +// res := Lib.NewList[AST.Form]() + +// for _, form := range forms.GetSlice() { +// res.Append(secondPassAux(form, vars, types)) +// } + +// return res +// } + +// func nArySecondPassTerms( +// terms Lib.List[AST.Term], +// vars []AST.Var, +// types []AST.TypeApp, +// ) Lib.List[AST.Term] { +// resTerms := Lib.NewList[AST.Term]() + +// for _, term := range terms.GetSlice() { +// t := secondPassTerm(term, vars, types) + +// if t != nil { +// resTerms.Append(t) +// } +// } + +// return resTerms +// } + +// func getTypeOfFunction(name string, vars []AST.TypeApp, termsType []AST.TypeApp) AST.TypeScheme { +// // Build TypeCross from termsType +// var tt []AST.TypeApp +// if len(termsType) >= 2 { +// tc := AST.MkTypeCross(termsType[0], termsType[1]) +// for i := 2; i < len(termsType); i += 1 { +// tc = AST.MkTypeCross(tc, termsType[i]) +// } +// tt = []AST.TypeApp{tc} +// } else { +// tt = termsType +// } + +// simpleTypeScheme := AST.GetType(name, tt...) +// if simpleTypeScheme != nil { +// if Glob.Is[AST.QuantifiedType](simpleTypeScheme) { +// return Glob.To[AST.QuantifiedType](simpleTypeScheme).Instanciate(vars) +// } +// return simpleTypeScheme +// } + +// typeScheme := AST.GetPolymorphicType(name, len(vars), len(termsType)) + +// if typeScheme != nil { +// // Instantiate type scheme with actual types +// typeScheme = Glob.To[AST.QuantifiedType](typeScheme).Instanciate(vars) +// } else { +// // As only distinct objects are here, it should work with only this. +// // I leave the other condition if others weirderies are found later. +// if len(termsType) == 0 { +// AST.SaveConstant(name, Glob.To[AST.TypeApp](AST.DefaultFunType(0))) +// } +// /* +// else { +// type_ := DefaultFunType(len(termsType)) +// if len(termsType) == 1 { +// SaveTypeScheme(name, GetInputType(type_)[0], GetOutType(type_)) +// } else { +// SaveTypeScheme(name, AST.MkTypeCross(GetInputType(type_)...), GetOutType(type_)) +// } +// } +// */ +// typeScheme = AST.DefaultFunType(0) + +// } + +// return typeScheme +// } diff --git a/src/Typing/type_rules.go b/src/Typing/type_rules.go index 82f03ced..f285ca85 100644 --- a/src/Typing/type_rules.go +++ b/src/Typing/type_rules.go @@ -32,189 +32,189 @@ package Typing -import ( - "fmt" - - "github.com/GoelandProver/Goeland/AST" - "github.com/GoelandProver/Goeland/Glob" - "github.com/GoelandProver/Goeland/Lib" -) - -/** - * This file contains the rules for typing terms, and also the App rule. - * The App rule is used for predicates and functions. - **/ - -/* Applies the Var rule for a type variable: erase consequence */ -func applyLocalTypeVarRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { - // Add applied rule to the prooftree - root.appliedRule = "Var" - - // Find current variable in the local context - if _, ok := getTypeFromLocalContext(state.localContext, state.consequence.a.(AST.TypeVar)); !ok { - return Reconstruct{ - result: false, - err: fmt.Errorf("TypeVar %s not found in the local context", state.consequence.a.ToString()), - } - } - - // No consequence: next rule is the WF rule. - children := []Sequent{ - { - globalContext: state.globalContext, - localContext: state.localContext.copy(), - consequence: Consequence{}, - }, - } - - return launchChildren(children, root, fatherChan) -} - -/* Applies the Var rule for a type hint: erase consequence */ -func applyGlobalTypeVarRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { - // Add applied rule to the prooftree - root.appliedRule = "Var" - - // Find current variable in the local context - if found := state.globalContext.isTypeInContext(Glob.To[AST.TypeScheme](state.consequence.a)); !found { - return Reconstruct{ - result: false, - err: fmt.Errorf("TypeVar %s not found in the global context", state.consequence.a.ToString()), - } - } - - // No consequence: next rule is the WF rule. - children := []Sequent{ - { - globalContext: state.globalContext, - localContext: state.localContext.copy(), - consequence: Consequence{}, - }, - } - - return launchChildren(children, root, fatherChan) -} - -/* Applies Type rule: erase consequence */ -func applyTypeWFRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { - // Add applied rule to the prooftree - root.appliedRule = "Type" - - // WF child - children := []Sequent{ - { - globalContext: state.globalContext, - localContext: state.localContext.copy(), - consequence: Consequence{}, - }, - } - - return launchChildren(children, root, fatherChan) -} - -/* Applies Cross rule */ -func applyCrossRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { - // Add applied rule to the prooftree - root.appliedRule = "Cross" - - if tc, ok := state.consequence.a.(AST.TypeCross); ok { - // Construct a child for every type recovered - return launchChildren(constructWithTypes(state, tc.GetAllUnderlyingTypes()), root, fatherChan) - } else { - return Reconstruct{ - result: false, - err: fmt.Errorf("CrossRule type on something that is not a TypeCross: %s", state.consequence.a.ToString()), - } - } -} - -/* Sym rule: a child for each type in the input, and one for the output if it's a function */ -func applySymRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { - root.appliedRule = "Sym" - - primitives := state.consequence.s.GetPrimitives() - out := AST.GetOutType(state.consequence.s) - - newLocalContext := state.localContext.copy() - if qt, found := state.consequence.s.(AST.QuantifiedType); found { - newLocalContext.typeVars = append(newLocalContext.typeVars, qt.QuantifiedVars()...) - } - - children := []Sequent{} - if Glob.Is[AST.TypeScheme](out) { - children = append(children, Sequent{ - globalContext: state.globalContext, - localContext: newLocalContext, - consequence: Consequence{a: out}, - }) - } - - for _, type_ := range primitives[:len(primitives)-1] { - children = append(children, Sequent{ - globalContext: state.globalContext, - localContext: newLocalContext, - consequence: Consequence{a: type_}, - }) - } - - return launchChildren(children, root, fatherChan) -} - -/* AppType rule: a child for each type in the input, and checks if the parameterized type exists. */ -func applyAppTypeRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { - root.appliedRule = "App" - - type_ := state.consequence.a.(AST.ParameterizedType) - types := type_.GetParameters() - - // Search for the ID in the global context - if !state.globalContext.parameterizedTypesContains(type_.GetName()) { - return Reconstruct{ - result: false, - err: fmt.Errorf("parameterized Type %s not in context", type_.ToString()), - } - } - - children := []Sequent{} - for _, type_ := range types { - children = append(children, Sequent{ - globalContext: state.globalContext, - localContext: state.localContext.copy(), - consequence: Consequence{a: type_}, - }) - } - - result := launchChildren(children, root, fatherChan) - - // Only one term needs to be returned because the ParameterizedType is counted as one. - return Reconstruct{ - result: result.result, - err: result.err, - terms: Lib.NewList[AST.Term](), - } -} - -/* Utils functions */ - -/* Finds the given term in the local context, returns false if it couldn't */ -func getTypeFromLocalContext(localContext LocalContext, typeApp AST.TypeVar) (AST.TypeApp, bool) { - for _, type_ := range localContext.typeVars { - if typeApp.Equals(type_) { - return type_, true - } - } - return AST.TypeVar{}, false -} - -/* Constructs all the children of a composed type */ -func constructWithTypes(state Sequent, types []AST.TypeApp) []Sequent { - children := []Sequent{} - for _, type_ := range types { - children = append(children, Sequent{ - globalContext: state.globalContext, - localContext: state.localContext.copy(), - consequence: Consequence{a: type_}, - }) - } - return children -} +// import ( +// "fmt" + +// "github.com/GoelandProver/Goeland/AST" +// "github.com/GoelandProver/Goeland/Glob" +// "github.com/GoelandProver/Goeland/Lib" +// ) + +// /** +// * This file contains the rules for typing terms, and also the App rule. +// * The App rule is used for predicates and functions. +// **/ + +// /* Applies the Var rule for a type variable: erase consequence */ +// func applyLocalTypeVarRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { +// // Add applied rule to the prooftree +// root.appliedRule = "Var" + +// // Find current variable in the local context +// if _, ok := getTypeFromLocalContext(state.localContext, state.consequence.a.(AST.TypeVar)); !ok { +// return Reconstruct{ +// result: false, +// err: fmt.Errorf("TypeVar %s not found in the local context", state.consequence.a.ToString()), +// } +// } + +// // No consequence: next rule is the WF rule. +// children := []Sequent{ +// { +// globalContext: state.globalContext, +// localContext: state.localContext.copy(), +// consequence: Consequence{}, +// }, +// } + +// return launchChildren(children, root, fatherChan) +// } + +// /* Applies the Var rule for a type hint: erase consequence */ +// func applyGlobalTypeVarRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { +// // Add applied rule to the prooftree +// root.appliedRule = "Var" + +// // Find current variable in the local context +// if found := state.globalContext.isTypeInContext(Glob.To[AST.TypeScheme](state.consequence.a)); !found { +// return Reconstruct{ +// result: false, +// err: fmt.Errorf("TypeVar %s not found in the global context", state.consequence.a.ToString()), +// } +// } + +// // No consequence: next rule is the WF rule. +// children := []Sequent{ +// { +// globalContext: state.globalContext, +// localContext: state.localContext.copy(), +// consequence: Consequence{}, +// }, +// } + +// return launchChildren(children, root, fatherChan) +// } + +// /* Applies Type rule: erase consequence */ +// func applyTypeWFRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { +// // Add applied rule to the prooftree +// root.appliedRule = "Type" + +// // WF child +// children := []Sequent{ +// { +// globalContext: state.globalContext, +// localContext: state.localContext.copy(), +// consequence: Consequence{}, +// }, +// } + +// return launchChildren(children, root, fatherChan) +// } + +// /* Applies Cross rule */ +// func applyCrossRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { +// // Add applied rule to the prooftree +// root.appliedRule = "Cross" + +// if tc, ok := state.consequence.a.(AST.TypeCross); ok { +// // Construct a child for every type recovered +// return launchChildren(constructWithTypes(state, tc.GetAllUnderlyingTypes()), root, fatherChan) +// } else { +// return Reconstruct{ +// result: false, +// err: fmt.Errorf("CrossRule type on something that is not a TypeCross: %s", state.consequence.a.ToString()), +// } +// } +// } + +// /* Sym rule: a child for each type in the input, and one for the output if it's a function */ +// func applySymRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { +// root.appliedRule = "Sym" + +// primitives := state.consequence.s.GetPrimitives() +// out := AST.GetOutType(state.consequence.s) + +// newLocalContext := state.localContext.copy() +// if qt, found := state.consequence.s.(AST.QuantifiedType); found { +// newLocalContext.typeVars = append(newLocalContext.typeVars, qt.QuantifiedVars()...) +// } + +// children := []Sequent{} +// if Glob.Is[AST.TypeScheme](out) { +// children = append(children, Sequent{ +// globalContext: state.globalContext, +// localContext: newLocalContext, +// consequence: Consequence{a: out}, +// }) +// } + +// for _, type_ := range primitives[:len(primitives)-1] { +// children = append(children, Sequent{ +// globalContext: state.globalContext, +// localContext: newLocalContext, +// consequence: Consequence{a: type_}, +// }) +// } + +// return launchChildren(children, root, fatherChan) +// } + +// /* AppType rule: a child for each type in the input, and checks if the parameterized type exists. */ +// func applyAppTypeRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { +// root.appliedRule = "App" + +// type_ := state.consequence.a.(AST.ParameterizedType) +// types := type_.GetParameters() + +// // Search for the ID in the global context +// if !state.globalContext.parameterizedTypesContains(type_.GetName()) { +// return Reconstruct{ +// result: false, +// err: fmt.Errorf("parameterized Type %s not in context", type_.ToString()), +// } +// } + +// children := []Sequent{} +// for _, type_ := range types { +// children = append(children, Sequent{ +// globalContext: state.globalContext, +// localContext: state.localContext.copy(), +// consequence: Consequence{a: type_}, +// }) +// } + +// result := launchChildren(children, root, fatherChan) + +// // Only one term needs to be returned because the ParameterizedType is counted as one. +// return Reconstruct{ +// result: result.result, +// err: result.err, +// terms: Lib.NewList[AST.Term](), +// } +// } + +// /* Utils functions */ + +// /* Finds the given term in the local context, returns false if it couldn't */ +// func getTypeFromLocalContext(localContext LocalContext, typeApp AST.TypeVar) (AST.TypeApp, bool) { +// for _, type_ := range localContext.typeVars { +// if typeApp.Equals(type_) { +// return type_, true +// } +// } +// return AST.TypeVar{}, false +// } + +// /* Constructs all the children of a composed type */ +// func constructWithTypes(state Sequent, types []AST.TypeApp) []Sequent { +// children := []Sequent{} +// for _, type_ := range types { +// children = append(children, Sequent{ +// globalContext: state.globalContext, +// localContext: state.localContext.copy(), +// consequence: Consequence{a: type_}, +// }) +// } +// return children +// } diff --git a/src/Typing/wf_rules.go b/src/Typing/wf_rules.go index 6ed30f64..186217dc 100644 --- a/src/Typing/wf_rules.go +++ b/src/Typing/wf_rules.go @@ -32,36 +32,36 @@ package Typing -/** - * This file defines the WF rules. - **/ +// /** +// * This file defines the WF rules. +// **/ -/* WF1 rule first empties the variables, and then the types. */ -func applyWF2(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { - root.appliedRule = "WF_2" +// /* WF1 rule first empties the variables, and then the types. */ +// func applyWF2(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { +// root.appliedRule = "WF_2" - // Try to empty vars first - if len(state.localContext.vars) > 0 { - // Launch child on the type of the first var - var_, newLocalContext := state.localContext.popVar() - child := []Sequent{ - { - localContext: newLocalContext, - globalContext: state.globalContext, - consequence: Consequence{a: var_.GetTypeApp()}, - }, - } - return launchChildren(child, root, fatherChan) - } +// // Try to empty vars first +// if len(state.localContext.vars) > 0 { +// // Launch child on the type of the first var +// var_, newLocalContext := state.localContext.popVar() +// child := []Sequent{ +// { +// localContext: newLocalContext, +// globalContext: state.globalContext, +// consequence: Consequence{a: var_.GetTypeApp()}, +// }, +// } +// return launchChildren(child, root, fatherChan) +// } - // Then, if vars is not empty, empty the types - _, newLocalContext := state.localContext.popTypeVar() - child := []Sequent{ - { - localContext: newLocalContext, - globalContext: state.globalContext, - consequence: Consequence{a: metaType}, - }, - } - return launchChildren(child, root, fatherChan) -} +// // Then, if vars is not empty, empty the types +// _, newLocalContext := state.localContext.popTypeVar() +// child := []Sequent{ +// { +// localContext: newLocalContext, +// globalContext: state.globalContext, +// consequence: Consequence{a: metaType}, +// }, +// } +// return launchChildren(child, root, fatherChan) +// } diff --git a/src/Unif/matching.go b/src/Unif/matching.go index c6c540bf..9003bf1a 100644 --- a/src/Unif/matching.go +++ b/src/Unif/matching.go @@ -66,23 +66,18 @@ func (m *Machine) unify(node Node, formula AST.Form) []MatchingSubstitutions { // The formula has to be a predicate. switch formula_type := formula.(type) { case AST.Pred: - terms := TypeAndTermsToTerms(formula_type.GetTypeVars(), formula_type.GetArgs()) - // Transform the predicate to a function to make the tool work properly m.terms = Lib.MkListV[AST.Term](AST.MakerFun( formula_type.GetID(), - terms, - []AST.TypeApp{}, - formula_type.GetType(), + formula_type.GetArgs(), )) result = m.unifyAux(node) if !reflect.DeepEqual(m.failure, result) { filteredResult := []MatchingSubstitutions{} - // For each substitutions, remove the [0...MetaCount(formula_type.GetTypeVars())] ones to put it in another slice (the type slice) for _, matchingSubst := range result { - actualSubsts := matchingSubst.GetSubst()[AST.CountMeta(formula_type.GetTypeVars()):] - filteredResult = append(filteredResult, MakeMatchingSubstitutions(matchingSubst.GetForm(), actualSubsts)) + filteredResult = append(filteredResult, + MakeMatchingSubstitutions(matchingSubst.GetForm(), matchingSubst.GetSubst())) } result = filteredResult } diff --git a/src/Unif/parsing.go b/src/Unif/parsing.go index 4907d8a8..e63b98da 100644 --- a/src/Unif/parsing.go +++ b/src/Unif/parsing.go @@ -34,7 +34,6 @@ package Unif import ( "github.com/GoelandProver/Goeland/AST" - "github.com/GoelandProver/Goeland/Glob" "github.com/GoelandProver/Goeland/Lib" ) @@ -56,11 +55,9 @@ func (t TermForm) GetChildrenForMappedString() []AST.MappableString { return AST.LsToMappableStringSlice(t.GetChildFormulas()) } -func (t TermForm) GetTerm() AST.Term { return t.t.Copy() } -func (t TermForm) Copy() AST.Form { return makeTermForm(t.GetIndex(), t.GetTerm()) } -func (t TermForm) GetType() AST.TypeScheme { return AST.DefaultFunType(0) } -func (t TermForm) RenameVariables() AST.Form { return t } -func (t TermForm) ReplaceTypeByMeta([]AST.TypeVar, int) AST.Form { return t } +func (t TermForm) GetTerm() AST.Term { return t.t.Copy() } +func (t TermForm) Copy() AST.Form { return makeTermForm(t.GetIndex(), t.GetTerm()) } +func (t TermForm) RenameVariables() AST.Form { return t } func (t TermForm) ReplaceTermByTerm(AST.Term, AST.Term) (AST.Form, bool) { return t, false } @@ -125,20 +122,14 @@ func ParseFormula(formula AST.Form) Sequence { // The formula has to be a predicate switch formula_type := formula.(type) { case AST.Pred: - pred := AST.MakePred(formula_type.GetIndex(), formula_type.GetID(), TypeAndTermsToTerms(formula_type.GetTypeVars(), formula_type.GetArgs()), []AST.TypeApp{}, formula_type.GetType()) - instructions := Sequence{formula: pred} + instructions := Sequence{formula: formula_type} instructions.add(Begin{}) - parsePred(pred, &instructions) + parsePred(formula_type, &instructions) instructions.add(End{}) return instructions case TermForm: - if Glob.Is[AST.Fun](formula_type.GetTerm()) { - fun := Glob.To[AST.Fun](formula_type.GetTerm()) - formula = makeTermForm(formula.GetIndex(), AST.MakerFun(fun.GetID(), TypeAndTermsToTerms(fun.GetTypeVars(), fun.GetArgs()), []AST.TypeApp{}, fun.GetTypeHint())) - } - instructions := Sequence{formula: formula} varCount := 0 postCount := 0 @@ -159,17 +150,6 @@ func ParseFormula(formula AST.Form) Sequence { } } -func TypeAndTermsToTerms( - types []AST.TypeApp, - terms Lib.List[AST.Term], -) Lib.List[AST.Term] { - tms := Lib.NewList[AST.Term]() - tms.Append(AST.TypeAppArrToTerm(types).GetSlice()...) - tms.Append(terms.GetSlice()...) - - return tms -} - /* Parses a predicate to machine instructions */ func parsePred(p AST.Pred, instructions *Sequence) { instructions.add(makeCheck(p.GetID())) diff --git a/src/Unif/substitutions_type.go b/src/Unif/substitutions_type.go index 32acc4bc..138bf430 100644 --- a/src/Unif/substitutions_type.go +++ b/src/Unif/substitutions_type.go @@ -213,7 +213,7 @@ func MakeEmptySubstitutionList() []Substitutions { /* Returns a « failed » substitution. */ func Failure() Substitutions { - fail := AST.MakeMeta(-1, -1, "FAILURE", -1, AST.MkTypeHint("i")) + fail := AST.MakeMeta(-1, -1, "FAILURE", -1) return Substitutions{Substitution{fail, fail}} } @@ -314,8 +314,6 @@ func eliminateInside(key AST.Meta, value AST.Term, s Substitutions, has_changed_ new_value := AST.MakerFun( value_2_type.GetP(), eliminateList(key, value, value_2_type.GetArgs(), &has_changed), - value_2_type.GetTypeVars(), - value_2_type.GetTypeHint(), ) if OccurCheckValid(key_2, new_value) { s_tmp.Set(key_2, new_value) @@ -361,8 +359,6 @@ func eliminateList( tempList.Append(AST.MakerFun( lt.GetP(), eliminateList(key, value, lt.GetArgs(), &hasChanged), - lt.GetTypeVars(), - lt.GetTypeHint(), )) default: tempList.Append(elementList) diff --git a/src/main.go b/src/main.go index dbe14218..b0eab71f 100644 --- a/src/main.go +++ b/src/main.go @@ -58,7 +58,7 @@ import ( "github.com/GoelandProver/Goeland/Parser" "github.com/GoelandProver/Goeland/Search" "github.com/GoelandProver/Goeland/Search/incremental" - "github.com/GoelandProver/Goeland/Typing" + _ "github.com/GoelandProver/Goeland/Typing" "github.com/GoelandProver/Goeland/Unif" ) @@ -201,7 +201,7 @@ func initDebuggers() { equality.InitDebugger() incremental.InitDebugger() Search.InitDebugger() - Typing.InitDebugger() + // Typing.InitDebugger() Unif.InitDebugger() } @@ -366,13 +366,13 @@ func checkForTypedProof(form AST.Form) AST.Form { isTypedProof := !AST.EmptyGlobalContext() && !Glob.NoTypeCheck() if isTypedProof { - err := Typing.WellFormedVerification(form.Copy(), Glob.GetTypeProof()) + // err := Typing.WellFormedVerification(form.Copy(), Glob.GetTypeProof()) - if err != nil { - Glob.Fatal("typechecker", fmt.Sprintf("Typing error: %v", err)) - } else { - Glob.PrintInfo("typechecker", fmt.Sprintf("The problem %s is well typed.", Glob.GetProblemName())) - } + // if err != nil { + // Glob.Fatal(main_label, fmt.Sprintf("Typing error: %v", err)) + // } else { + // Glob.PrintInfo(main_label, "Well typed.") + // } } return form From 6c5dbacc2d1011473cd3ceec85d26ab0bd44f756 Mon Sep 17 00:00:00 2001 From: Johann Rosain Date: Tue, 22 Jul 2025 22:42:02 +0200 Subject: [PATCH 05/30] Updated syntax of types and reintroduced them in the internals --- src/AST/formsDef.go | 42 ++- src/AST/formula.go | 19 +- src/AST/maker.go | 20 +- src/AST/manage_apps_types.go | 297 --------------- src/AST/parameterizedtype.go | 163 --------- src/AST/polytypes.go | 177 --------- src/AST/quantifiedtype.go | 159 -------- src/AST/quantifiers.go | 28 +- src/AST/{term_list.go => term-list.go} | 12 - src/AST/term.go | 8 +- src/AST/termsDef.go | 26 +- src/AST/tptp-native-types.go | 167 +++++++++ src/AST/tptp_native.go | 154 -------- src/AST/ty-syntax.go | 334 +++++++++++++++++ src/AST/typearrow.go | 159 -------- src/AST/typecross.go | 129 ------- src/AST/typed-vars.go | 129 +++++++ src/AST/typehint.go | 120 ------ src/AST/typevar.go | 126 ------- src/AST/typing_utils.go | 118 ------ src/Core/Sko/inner-skolemization.go | 11 +- src/Core/Sko/interface.go | 5 +- src/Core/Sko/outer-skolemization.go | 11 +- src/Core/Sko/preinner-skolemization.go | 29 +- src/Core/instanciation.go | 14 +- src/Core/skolemisation.go | 16 +- src/Core/statement.go | 4 +- src/Core/substitutions_search.go | 11 +- src/Engine/pretyper.go | 29 +- src/Engine/syntax-translation.go | 304 ++++++++-------- src/Lib/list.go | 18 +- src/Lib/opt.go | 4 +- src/Lib/sets.go | 18 +- .../equality/bse/equality_problem_list.go | 19 +- src/Mods/equality/bse/equality_types.go | 21 +- src/Mods/equality/sateq/subsgatherer.go | 2 +- src/Mods/equality/sateq/termrep.go | 2 + src/Mods/gs3/dependency.go | 30 +- src/Mods/gs3/proof.go | 8 +- src/Mods/lambdapi/context.go | 113 +++--- src/Mods/lambdapi/formDecorator.go | 9 +- src/Mods/lambdapi/proof.go | 44 ++- src/Mods/rocq/context.go | 42 +-- src/Search/incremental/rules.go | 8 +- src/Typing/apply_rules.go | 189 ---------- src/Typing/contexts.go | 341 ------------------ src/Typing/env-and-context.go | 136 +++++++ src/Typing/form_rules.go | 234 ------------ src/Typing/{wf_rules.go => init.go} | 43 +-- src/Typing/launch_rules.go | 177 --------- src/Typing/prooftree_dump.go | 151 -------- src/Typing/rules.go | 212 +---------- src/Typing/term_rules.go | 216 ----------- src/Typing/type.go | 190 ---------- src/Typing/type_rules.go | 220 ----------- src/Unif/matching.go | 2 + src/Unif/substitutions_type.go | 4 +- src/main.go | 77 ++-- 58 files changed, 1298 insertions(+), 4053 deletions(-) delete mode 100644 src/AST/manage_apps_types.go delete mode 100644 src/AST/parameterizedtype.go delete mode 100644 src/AST/polytypes.go delete mode 100644 src/AST/quantifiedtype.go rename src/AST/{term_list.go => term-list.go} (93%) create mode 100644 src/AST/tptp-native-types.go delete mode 100644 src/AST/tptp_native.go create mode 100644 src/AST/ty-syntax.go delete mode 100644 src/AST/typearrow.go delete mode 100644 src/AST/typecross.go create mode 100644 src/AST/typed-vars.go delete mode 100644 src/AST/typehint.go delete mode 100644 src/AST/typevar.go delete mode 100644 src/AST/typing_utils.go delete mode 100644 src/Typing/apply_rules.go delete mode 100644 src/Typing/contexts.go create mode 100644 src/Typing/env-and-context.go delete mode 100644 src/Typing/form_rules.go rename src/Typing/{wf_rules.go => init.go} (61%) delete mode 100644 src/Typing/launch_rules.go delete mode 100644 src/Typing/prooftree_dump.go delete mode 100644 src/Typing/term_rules.go delete mode 100644 src/Typing/type.go delete mode 100644 src/Typing/type_rules.go diff --git a/src/AST/formsDef.go b/src/AST/formsDef.go index 55ff9ba5..bf1922c3 100644 --- a/src/AST/formsDef.go +++ b/src/AST/formsDef.go @@ -87,24 +87,20 @@ type All struct { quantifier } -func MakeAllSimple(i int, vars []Var, forms Form, metas Lib.Set[Meta]) All { +func MakeAllSimple(i int, vars Lib.List[TypedVar], forms Form, metas Lib.Set[Meta]) All { return All{makeQuantifier(i, vars, forms, metas, AllQuant)} } -func MakeAll(i int, vars []Var, forms Form) All { +func MakeAll(i int, vars Lib.List[TypedVar], forms Form) All { return MakeAllSimple(i, vars, forms, Lib.EmptySet[Meta]()) } -func MakerAll(vars []Var, forms Form) All { +func MakerAll(vars Lib.List[TypedVar], forms Form) All { return MakeAll(MakerIndexFormula(), vars, forms) } func (a All) Equals(other any) bool { - if typed, ok := other.(All); ok { - return AreEqualsVarList(a.GetVarList(), typed.GetVarList()) && a.GetForm().Equals(typed.GetForm()) - } - - return false + return a.quantifier.Equals(other) } func (a All) GetSubFormulasRecur() Lib.List[Form] { @@ -139,24 +135,20 @@ type Ex struct { quantifier } -func MakeExSimple(i int, vars []Var, forms Form, metas Lib.Set[Meta]) Ex { +func MakeExSimple(i int, vars Lib.List[TypedVar], forms Form, metas Lib.Set[Meta]) Ex { return Ex{makeQuantifier(i, vars, forms, metas, ExQuant)} } -func MakeEx(i int, vars []Var, forms Form) Ex { +func MakeEx(i int, vars Lib.List[TypedVar], forms Form) Ex { return MakeExSimple(i, vars, forms, Lib.EmptySet[Meta]()) } -func MakerEx(vars []Var, forms Form) Ex { +func MakerEx(vars Lib.List[TypedVar], forms Form) Ex { return MakeEx(MakerIndexFormula(), vars, forms) } func (e Ex) Equals(other any) bool { - if typed, ok := other.(Ex); ok { - return AreEqualsVarList(e.GetVarList(), typed.GetVarList()) && e.GetForm().Equals(typed.GetForm()) - } - - return false + return e.quantifier.Equals(other) } func (e Ex) GetSubFormulasRecur() Lib.List[Form] { @@ -826,6 +818,7 @@ type Pred struct { *MappedString index int id Id + tys Lib.List[Ty] args Lib.List[Term] metas Lib.Cache[Lib.Set[Meta], Pred] } @@ -833,6 +826,7 @@ type Pred struct { func MakePredSimple( index int, id Id, + tys Lib.List[Ty], terms Lib.List[Term], metas Lib.Set[Meta], ) Pred { @@ -841,6 +835,7 @@ func MakePredSimple( fms, index, id, + tys, terms, Lib.MkCache(metas, Pred.forceGetMetas), } @@ -851,11 +846,13 @@ func MakePredSimple( func MakePred( index int, id Id, + tys Lib.List[Ty], terms Lib.List[Term], ) Pred { return MakePredSimple( index, id, + tys, terms, Lib.EmptySet[Meta](), ) @@ -863,15 +860,17 @@ func MakePred( func MakerPred( id Id, + tys Lib.List[Ty], terms Lib.List[Term], ) Pred { - return MakePred(MakerIndexFormula(), id, terms) + return MakePred(MakerIndexFormula(), id, tys, terms) } /* Pred attributes getters */ func (p Pred) GetIndex() int { return p.index } func (p Pred) GetID() Id { return p.id.Copy().(Id) } +func (p Pred) GetTyArgs() Lib.List[Ty] { return p.tys } func (p Pred) GetArgs() Lib.List[Term] { return p.args } /* Formula methods */ @@ -914,6 +913,7 @@ func (p Pred) Copy() Form { np := MakePredSimple( p.index, p.id, + p.GetTyArgs(), p.GetArgs(), p.metas.Raw().Copy(), ) @@ -927,7 +927,9 @@ func (p Pred) Copy() Form { func (p Pred) Equals(other any) bool { if typed, ok := other.(Pred); ok { - return typed.id.Equals(p.id) && Lib.ListEquals(typed.args, p.args) + return typed.id.Equals(p.id) && + Lib.ListEquals(typed.tys, p.tys) && + Lib.ListEquals(typed.args, p.args) } return false @@ -968,6 +970,7 @@ func (p Pred) ReplaceTermByTerm(old Term, new Term) (Form, bool) { np := MakePredSimple( p.GetIndex(), p.GetID(), + p.GetTyArgs(), termList, p.metas.Raw(), ) @@ -999,6 +1002,7 @@ func (p Pred) SubstituteVarByMeta(old Var, new Meta) Form { return MakePredSimple( nf.index, nf.id, + nf.tys, nf.args, nf.metas.Raw(), ) @@ -1031,7 +1035,7 @@ func (p Pred) ReplaceMetaByTerm(meta Meta, term Term) Form { } } - return MakePred(p.GetIndex(), p.id, newTerms) + return MakePred(p.GetIndex(), p.id, p.tys, newTerms) } // ----------------------------------------------------------------------------- diff --git a/src/AST/formula.go b/src/AST/formula.go index 0a1b37d5..18532b5c 100644 --- a/src/AST/formula.go +++ b/src/AST/formula.go @@ -89,6 +89,7 @@ func replaceTermInTermList( ) newTermList.Upd(i, MakerFun( nf.GetP(), + nf.GetTyArgs(), termList, )) res = res || r @@ -110,24 +111,6 @@ func replaceTermInTermList( /* Utils */ -func instanciateTypeAppList(typeApps []TypeApp, vars []TypeVar, index int) []TypeApp { - // For each typeVar € nf.GetTypeVars(), if typeVar € varList, instanciate typeVar - typeVars := []TypeApp{} - for _, typeVar := range typeApps { - if Glob.Is[TypeVar](typeVar) { - tv := Glob.To[TypeVar](typeVar) - if Lib.ComparableList[TypeVar](vars).Contains(tv) { - tv.ShouldBeMeta(index) - } - typeVars = append(typeVars, tv) - } else { - typeVars = append(typeVars, typeVar) - } - } - - return typeVars -} - func metasUnion(forms Lib.List[Form]) Lib.Set[Meta] { res := Lib.EmptySet[Meta]() diff --git a/src/AST/maker.go b/src/AST/maker.go index a514c277..3b509884 100644 --- a/src/AST/maker.go +++ b/src/AST/maker.go @@ -66,13 +66,9 @@ var EmptyPredEq Pred /* Initialization */ func Init() { Reset() - initTypes() + initTPTPNativeTypes() Id_eq = MakerId("=") - EmptyPredEq = MakerPred(Id_eq, Lib.NewList[Term]()) - - // Eq/Neq types - // FIXME: Register the type of equality in the global context - // --- (call an internal function like SaveEqType()) + EmptyPredEq = MakerPred(Id_eq, Lib.NewList[Ty](), Lib.NewList[Term]()) initDefaultMap() } @@ -133,7 +129,7 @@ func MakerNewVar(s string) Var { } /* Meta maker */ -func MakerMeta(s string, formula int) Meta { +func MakerMeta(s string, formula int, ty Ty) Meta { lock_term.Lock() i, ok := occurenceMeta[s] lock_term.Unlock() @@ -143,25 +139,25 @@ func MakerMeta(s string, formula int) Meta { new_index := cpt_term cpt_term += 1 lock_term.Unlock() - return MakeMeta(new_index, i, s, formula) + return MakeMeta(new_index, i, s, formula, ty) } else { lock_term.Lock() occurenceMeta[s] = 1 new_index := cpt_term cpt_term += 1 lock_term.Unlock() - return MakeMeta(new_index, 0, s, formula) + return MakeMeta(new_index, 0, s, formula, ty) } } /* Const maker (given a id, create a fun without args) */ func MakerConst(id Id) Fun { - return MakeFun(id, Lib.NewList[Term](), Lib.EmptySet[Meta]()) + return MakeFun(id, Lib.NewList[Ty](), Lib.NewList[Term](), Lib.EmptySet[Meta]()) } /* Fun maker, with given id and args */ -func MakerFun(id Id, terms Lib.List[Term]) Fun { - return MakeFun(id, terms, Lib.EmptySet[Meta]()) +func MakerFun(id Id, ty_args Lib.List[Ty], terms Lib.List[Term]) Fun { + return MakeFun(id, ty_args, terms, Lib.EmptySet[Meta]()) } /* Index make for formula */ diff --git a/src/AST/manage_apps_types.go b/src/AST/manage_apps_types.go deleted file mode 100644 index 06b6bbb9..00000000 --- a/src/AST/manage_apps_types.go +++ /dev/null @@ -1,297 +0,0 @@ -/** -* Copyright 2022 by the authors (see AUTHORS). -* -* Goéland is an automated theorem prover for first order logic. -* -* This software is governed by the CeCILL license under French law and -* abiding by the rules of distribution of free software. You can use, -* modify and/ or redistribute the software under the terms of the CeCILL -* license as circulated by CEA, CNRS and INRIA at the following URL -* "http://www.cecill.info". -* -* As a counterpart to the access to the source code and rights to copy, -* modify and redistribute granted by the license, users are provided only -* with a limited warranty and the software's author, the holder of the -* economic rights, and the successive licensors have only limited -* liability. -* -* In this respect, the user's attention is drawn to the risks associated -* with loading, using, modifying and/or developing or reproducing the -* software by the user in light of its specific status of free software, -* that may mean that it is complicated to manipulate, and that also -* therefore means that it is reserved for developers and experienced -* professionals having in-depth computer knowledge. Users are therefore -* encouraged to load and test the software's suitability as regards their -* requirements in conditions enabling the security of their systems and/or -* data to be ensured and, more generally, to use and operate it in the -* same conditions as regards security. -* -* The fact that you are presently reading this means that you have had -* knowledge of the CeCILL license and that you accept its terms. -**/ - -package AST - -import ( - "fmt" - "sync" - - "github.com/GoelandProver/Goeland/Glob" -) - -/** - * This file contains the logic behind the Type Schemes of polymorphic functions - * or predicates. - * A function can have different types of arguments, for example : - * sum: int * int > int - * sum: rat * rat > rat - * but both type schemes should be valid, and kept in memory. - **/ - -/* Maps an application: input type scheme and output type scheme. */ -type App struct { - in TypeApp - out TypeApp - App TypeScheme -} - -/* Map of Type Schemes for a function or a predicate. */ -var typeSchemesMap struct { - tsMap map[string][]App - lock sync.Mutex -} - -var pMap struct { - parametersMap map[string][]TypeApp - lock sync.Mutex -} - -const ( - IsFun = iota - IsProp = iota -) - -/* Saves a TypeScheme in the map of schemes. */ -func SaveTypeScheme(name string, in TypeApp, out TypeApp) error { - tArrow := MkTypeArrow(in, out) - - // If the map contains the name of the function/predicate, a type scheme has already been - // defined for it. It means that the out types shouldn't clash, otherwise, the new type - // scheme is wrong. - tScheme, found := getSchemeFromArgs(name, in) - if tScheme != nil { - if tScheme.Equals(tArrow) { - return nil - } - return fmt.Errorf("trying to save a known type scheme with different return types for the function %s", name) - } - - // It's not in the map, it should be added - typeSchemesMap.lock.Lock() - if found { - typeSchemesMap.tsMap[name] = append(typeSchemesMap.tsMap[name], App{in: in, out: out, App: tArrow}) - } else { - typeSchemesMap.tsMap[name] = []App{{in: in, out: out, App: tArrow}} - } - typeSchemesMap.lock.Unlock() - - return nil -} - -func SavePolymorphScheme(name string, scheme TypeScheme) error { - tScheme, found := getPolymorphSchemeFromArgs(name, scheme) - if tScheme != nil { - if !GetOutType(tScheme).Equals(GetOutType(scheme)) { - return fmt.Errorf("trying to save a known type scheme with different return types for the function %s", name) - } - return nil - } - - // It's not in the map, it should be added - typeSchemesMap.lock.Lock() - if found { - typeSchemesMap.tsMap[name] = append(typeSchemesMap.tsMap[name], App{App: scheme}) - } else { - typeSchemesMap.tsMap[name] = []App{{App: scheme}} - } - typeSchemesMap.lock.Unlock() - - return nil -} - -/* Saves the TypeScheme of a constant function */ -func SaveConstant(name string, out TypeApp) error { - // Check if the constant is already saved in the context - typeSchemesMap.lock.Lock() - if arr, found := typeSchemesMap.tsMap[name]; found { - var err error - if !arr[0].out.Equals(out) { - err = fmt.Errorf("trying to save a known type scheme with different return types for the function %s", name) - } - typeSchemesMap.lock.Unlock() - return err - } - - // Save the constant in the context. - // The line out.(TypeScheme) shouldn't fail : it's never a TypeVar. - typeSchemesMap.tsMap[name] = []App{ - {out: out, App: Glob.To[TypeScheme](out)}, - } - - typeSchemesMap.lock.Unlock() - return nil -} - -/* Checks if the given name is a constant (TypeHint) */ -func IsConstant(name string) bool { - typeSchemesMap.lock.Lock() - _, res := typeSchemesMap.tsMap[name] - typeSchemesMap.lock.Unlock() - return res -} - -/* Gets the TypeScheme from the global context. Returns default type if it doesn't exists. */ -func GetTypeOrDefault(name string, outDefault int, inArgs ...TypeApp) TypeScheme { - typeScheme := GetType(name, inArgs...) - if typeScheme == nil { - var size int - if len(inArgs) == 0 { - size = 0 - } else { - size = inArgs[0].Size() - } - - switch outDefault { - case IsFun: - return DefaultFunType(size) - case IsProp: - return DefaultPropType(size) - } - } - return typeScheme -} - -/* Gets a TypeScheme from the map of schemes with the name. Nil if it doesn't exists in the global context. */ -func GetType(name string, inArgs ...TypeApp) TypeScheme { - if len(inArgs) == 0 { - return getConstantTypeScheme(name) - } - args := inArgs[0] - - if tScheme, _ := getSchemeFromArgs(name, args); tScheme != nil { - return tScheme - } else { - return nil - } -} - -/* Gets a TypeScheme from the map of schemes with the name. Nil if it doesn't exists in the global context. */ -func GetPolymorphicType(name string, lenVars, lenTerms int) TypeScheme { - typeSchemesMap.lock.Lock() - if arr, found := typeSchemesMap.tsMap[name]; found { - for _, fun := range arr { - if fun.App.Size()-1 == lenTerms && (Glob.Is[QuantifiedType](fun.App) && len(fun.App.(QuantifiedType).vars) == lenVars) { - typeSchemesMap.lock.Unlock() - return fun.App - } - } - } - typeSchemesMap.lock.Unlock() - return nil -} - -/* Saves a parameterized type. A TypeApp should be nil if it's unknown */ -func SaveParamereterizedType(name string, types []TypeApp) { - pMap.lock.Lock() - if _, found := pMap.parametersMap[name]; !found { - pMap.parametersMap[name] = types - } - pMap.lock.Unlock() -} - -/* Gets the constants saved in the context */ -func getConstantTypeScheme(name string) TypeScheme { - var tScheme TypeScheme - typeSchemesMap.lock.Lock() - if typeSchemes, found := typeSchemesMap.tsMap[name]; found { - tScheme = typeSchemes[0].App - } else { - // If it's not found, the type is inferred with $i - tScheme = nil - } - typeSchemesMap.lock.Unlock() - return tScheme -} - -/* Returns the TypeScheme from the name & inArgs if it exists in the map. Else, nil. true means fun name is in the map. */ -func getSchemeFromArgs(name string, inArgs TypeApp) (TypeScheme, bool) { - typeSchemesMap.lock.Lock() - if arr, found := typeSchemesMap.tsMap[name]; found { - for _, fun := range arr { - // Polymorphic schemes don't have any of them. - if fun.in == nil || !Glob.Is[TypeScheme](inArgs) { - continue - } - if fun.in.Equals(inArgs) { - typeSchemesMap.lock.Unlock() - return fun.App, true - } - } - typeSchemesMap.lock.Unlock() - return nil, true - } - typeSchemesMap.lock.Unlock() - return nil, false -} - -/* Returns the TypeScheme from the name & inArgs if it exists in the map. Else, nil. true means fun name is in the map. */ -func getPolymorphSchemeFromArgs(name string, scheme TypeScheme) (TypeScheme, bool) { - typeSchemesMap.lock.Lock() - if arr, found := typeSchemesMap.tsMap[name]; found { - for _, fun := range arr { - if GetInputType(fun.App).Equals(GetInputType(scheme)) { - typeSchemesMap.lock.Unlock() - return fun.App, true - } - } - typeSchemesMap.lock.Unlock() - return nil, true - } - typeSchemesMap.lock.Unlock() - return nil, false -} - -/* Returns the global context. Use this only in polyrules. */ -func GetGlobalContext() map[string][]App { - // Get type schemes - typeSchemesMap.lock.Lock() - globalContext := make(map[string][]App) - - for name, app := range typeSchemesMap.tsMap { - globalContext[name] = make([]App, len(app)) - copy(globalContext[name], app) - } - - typeSchemesMap.lock.Unlock() - // Add TypeHints - tMap.lock.Lock() - for name, type_ := range tMap.uidsMap { - globalContext[name] = []App{{App: type_}} - } - tMap.lock.Unlock() - - // Add parameterized types - pMap.lock.Lock() - for name := range pMap.parametersMap { - globalContext[name] = []App{} - } - pMap.lock.Unlock() - return globalContext -} - -func IsPrimitive(name string) bool { - tMap.lock.Lock() - _, found := tMap.uidsMap[name] - tMap.lock.Unlock() - return found -} diff --git a/src/AST/parameterizedtype.go b/src/AST/parameterizedtype.go deleted file mode 100644 index 5b2d4a42..00000000 --- a/src/AST/parameterizedtype.go +++ /dev/null @@ -1,163 +0,0 @@ -/** -* Copyright 2022 by the authors (see AUTHORS). -* -* Goéland is an automated theorem prover for first order logic. -* -* This software is governed by the CeCILL license under French law and -* abiding by the rules of distribution of free software. You can use, -* modify and/ or redistribute the software under the terms of the CeCILL -* license as circulated by CEA, CNRS and INRIA at the following URL -* "http://www.cecill.info". -* -* As a counterpart to the access to the source code and rights to copy, -* modify and redistribute granted by the license, users are provided only -* with a limited warranty and the software's author, the holder of the -* economic rights, and the successive licensors have only limited -* liability. -* -* In this respect, the user's attention is drawn to the risks associated -* with loading, using, modifying and/or developing or reproducing the -* software by the user in light of its specific status of free software, -* that may mean that it is complicated to manipulate, and that also -* therefore means that it is reserved for developers and experienced -* professionals having in-depth computer knowledge. Users are therefore -* encouraged to load and test the software's suitability as regards their -* requirements in conditions enabling the security of their systems and/or -* data to be ensured and, more generally, to use and operate it in the -* same conditions as regards security. -* -* The fact that you are presently reading this means that you have had -* knowledge of the CeCILL license and that you accept its terms. -**/ - -/** - * This file declares one of the basic types used for typing the prover : - * ParameterizedType, a type which is parameterized with other types. - **/ - -package AST - -import ( - "strings" - - "fmt" - "github.com/GoelandProver/Goeland/Glob" - "github.com/GoelandProver/Goeland/Lib" -) - -/** - * Parameterized Type (TypeApp + TypeScheme) - * A Type which is parameterized with type apps to compose types. - * Example: map(int, int) - **/ -type ParameterizedType struct { - name string - parameters Lib.ComparableList[TypeApp] -} - -/* TypeScheme interface */ -func (pt ParameterizedType) isScheme() {} -func (pt ParameterizedType) toMappedString(subst map[string]string) string { - mappedString := []string{} - for _, typeScheme := range convert(pt.parameters, typeAppToTypeScheme) { - mappedString = append(mappedString, typeScheme.toMappedString(subst)) - } - return pt.name + "(" + strings.Join(mappedString, ", ") + ")" -} - -/* TypeApp interface */ -func (pt ParameterizedType) isTypeApp() {} -func (pt ParameterizedType) substitute(mapSubst map[TypeVar]string) TypeScheme { - newPt := ParameterizedType{pt.name, Lib.ComparableList[TypeApp]{}} - for _, param := range pt.parameters { - newPt.parameters = append(newPt.parameters, param.substitute(mapSubst).(TypeApp)) - } - return newPt -} -func (pt ParameterizedType) instanciate(substMap map[TypeVar]TypeApp) TypeApp { - newPt := ParameterizedType{pt.name, Lib.ComparableList[TypeApp]{}} - for _, param := range pt.parameters { - newPt.parameters = append(newPt.parameters, param.instanciate(substMap)) - } - return newPt -} - -// Exported methods - -func (pt ParameterizedType) ToString() string { return pt.toMappedString(make(map[string]string)) } -func (pt ParameterizedType) Equals(oth interface{}) bool { - if !Glob.Is[ParameterizedType](oth) { - return false - } - othPT := Glob.To[ParameterizedType](oth) - return pt.name == othPT.name && pt.parameters.Equals(othPT.parameters) -} -func (pt ParameterizedType) Size() int { return 1 } -func (pt ParameterizedType) GetPrimitives() []TypeApp { return []TypeApp{pt} } -func (pt ParameterizedType) GetParameters() []TypeApp { - res := []TypeApp{} - for _, param := range pt.parameters { - if Glob.Is[ParameterizedType](param) { - res = append(res, Glob.To[ParameterizedType](param).GetParameters()...) - } else { - res = append(res, param) - } - } - return res -} - -func (pt ParameterizedType) Copy() TypeApp { - newPT := ParameterizedType{name: pt.name, parameters: make(Lib.ComparableList[TypeApp], len(pt.parameters))} - copy(newPT.parameters, pt.parameters) - return newPT -} - -func (pt ParameterizedType) GetName() string { - return pt.name -} - -/* Makes a Parameterized Type from name and parameters */ -func MkParameterizedType(name string, types []TypeApp) ParameterizedType { - pMap.lock.Lock() - if parameters, found := pMap.parametersMap[name]; found { - k := 0 - nextTypes := make([]TypeApp, len(parameters)) - copy(nextTypes, parameters) - for i, param := range nextTypes { - if param == nil { - nextTypes[i] = types[k] - k++ - } - } - if k != len(types) { - pMap.lock.Unlock() - Glob.PrintInfo("PRMTR_TYPE", fmt.Sprintf("Name of the type: %s, length of the args: %d", name, len(types))) - Glob.PrintError("PRMTR_TYPE", "Parameterized type can not be instanciated with this number of arguments.") - return ParameterizedType{} - } - types = nextTypes - } else { - pMap.lock.Unlock() - Glob.PrintError("PRMTR_TYPE", "Parameterized type not found.") - return ParameterizedType{} - } - pMap.lock.Unlock() - - parameterizedType := ParameterizedType{name, types} - - vars := []TypeVar{} - for _, type_ := range types { - if var_, ok := type_.(TypeVar); ok { - vars = append(vars, var_) - } - } - - return parameterizedType -} - -func IsParameterizedType(name string) bool { - pMap.lock.Lock() - _, found := pMap.parametersMap[name] - pMap.lock.Unlock() - return found -} diff --git a/src/AST/polytypes.go b/src/AST/polytypes.go deleted file mode 100644 index a15a1267..00000000 --- a/src/AST/polytypes.go +++ /dev/null @@ -1,177 +0,0 @@ -/** -* Copyright 2022 by the authors (see AUTHORS). -* -* Goéland is an automated theorem prover for first order logic. -* -* This software is governed by the CeCILL license under French law and -* abiding by the rules of distribution of free software. You can use, -* modify and/ or redistribute the software under the terms of the CeCILL -* license as circulated by CEA, CNRS and INRIA at the following URL -* "http://www.cecill.info". -* -* As a counterpart to the access to the source code and rights to copy, -* modify and redistribute granted by the license, users are provided only -* with a limited warranty and the software's author, the holder of the -* economic rights, and the successive licensors have only limited -* liability. -* -* In this respect, the user's attention is drawn to the risks associated -* with loading, using, modifying and/or developing or reproducing the -* software by the user in light of its specific status of free software, -* that may mean that it is complicated to manipulate, and that also -* therefore means that it is reserved for developers and experienced -* professionals having in-depth computer knowledge. Users are therefore -* encouraged to load and test the software's suitability as regards their -* requirements in conditions enabling the security of their systems and/or -* data to be ensured and, more generally, to use and operate it in the -* same conditions as regards security. -* -* The fact that you are presently reading this means that you have had -* knowledge of the CeCILL license and that you accept its terms. -**/ - -/** - * This file declares the basic interfaces used for typing the prover. - **/ - -package AST - -import ( - "fmt" - "sync" - - "github.com/GoelandProver/Goeland/Glob" -) - -/** - * Polymorphic type, used either as a TypeHint, TypeCross or a TypeArrow to allow the inductive - * composition of either of the 3 to give a TypeScheme. - **/ -type TypeScheme interface { - /* Non-exported methods */ - isScheme() - toMappedString(map[string]string) string - - /* Exported methods */ - ToString() string - Size() int - GetPrimitives() []TypeApp - Equals(oth interface{}) bool -} - -/** - * Used for types which can be put inside a function or a predicate as arguments - * for a polymorphic scheme. - * It includes : TypeVar, TypeHint and TypeCross. - * In TFF, TypeArrow can not be the type of a variable. - * Furthermore, a TypeApp is not a quantified type scheme. - **/ -type TypeApp interface { - /* Non-exported methods */ - isTypeApp() - substitute(map[TypeVar]string) TypeScheme - instanciate(map[TypeVar]TypeApp) TypeApp - - /* Exported methods */ - ToString() string - Copy() TypeApp - Size() int - Equals(oth interface{}) bool -} - -/** - * Makers. - * As each type is unique, and stored in a Glob map (in shared memory), a lock should - * be defined. - **/ - -/* Call the init function before any type is created with MkType. */ -func initTypes() { - // Instantiate tCounter - tCounter.count = 1 - tCounter.lock = sync.Mutex{} - - // Instantiate tMap - tMap.uidsMap = make(map[string]TypeHint) - tMap.lock = sync.Mutex{} - - // Instantiate typeSchemesMap - typeSchemesMap.tsMap = make(map[string][]App) - typeSchemesMap.lock = sync.Mutex{} - - // Instanciate parameters map - pMap.parametersMap = make(map[string][]TypeApp) - pMap.lock = sync.Mutex{} - - // Default types - defaultType = MkTypeHint("$i") - defaultProp = MkTypeHint("$o") - - if Glob.GetArithModule() { - InitTPTPArithmetic() - } -} - -func EmptyTAArray() []TypeApp { - return []TypeApp{} -} - -/* Utils */ - -func utilMapCreation(vars []TypeVar) map[TypeVar]string { - metaTypeMap := make(map[TypeVar]string) - for i, var_ := range vars { - metaTypeMap[var_] = fmt.Sprintf("*_%d", i) - } - return metaTypeMap -} - -func utilMapReverseCreation(vars []TypeVar) map[string]string { - metaTypeMap := make(map[string]string) - for i, var_ := range vars { - metaTypeMap[fmt.Sprintf("*_%d", i)] = var_.ToString() - } - return metaTypeMap -} - -func substTypeAppList(mapSubst map[TypeVar]string, typeApp []TypeApp) []TypeApp { - newTypeApp := []TypeApp{} - for _, type_ := range typeApp { - newTypeApp = append(newTypeApp, type_.substitute(mapSubst).(TypeApp)) - } - return newTypeApp -} - -func instanciateList(mapSubst map[TypeVar]TypeApp, typeApp []TypeApp) []TypeApp { - newTypeApp := []TypeApp{} - for _, type_ := range typeApp { - newTypeApp = append(newTypeApp, type_.instanciate(mapSubst)) - } - return newTypeApp -} - -func EmptyGlobalContext() bool { - typeSchemesMap.lock.Lock() - schemeLen := len(typeSchemesMap.tsMap) - typeSchemesMap.lock.Unlock() - return schemeLen == 1 -} - -func CountMeta(types []TypeApp) int { - metas := 0 - for _, type_ := range types { - if tv, isTv := type_.(TypeVar); isTv && tv.Instantiated() { - metas += 1 - } - } - return metas -} - -/* Copies a list of TypeApp */ -func CopyTypeAppList(ta []TypeApp) []TypeApp { - res := make([]TypeApp, len(ta)) - for i := range ta { - res[i] = ta[i].Copy() - } - return res -} diff --git a/src/AST/quantifiedtype.go b/src/AST/quantifiedtype.go deleted file mode 100644 index 2394c58e..00000000 --- a/src/AST/quantifiedtype.go +++ /dev/null @@ -1,159 +0,0 @@ -/** -* Copyright 2022 by the authors (see AUTHORS). -* -* Goéland is an automated theorem prover for first order logic. -* -* This software is governed by the CeCILL license under French law and -* abiding by the rules of distribution of free software. You can use, -* modify and/ or redistribute the software under the terms of the CeCILL -* license as circulated by CEA, CNRS and INRIA at the following URL -* "http://www.cecill.info". -* -* As a counterpart to the access to the source code and rights to copy, -* modify and redistribute granted by the license, users are provided only -* with a limited warranty and the software's author, the holder of the -* economic rights, and the successive licensors have only limited -* liability. -* -* In this respect, the user's attention is drawn to the risks associated -* with loading, using, modifying and/or developing or reproducing the -* software by the user in light of its specific status of free software, -* that may mean that it is complicated to manipulate, and that also -* therefore means that it is reserved for developers and experienced -* professionals having in-depth computer knowledge. Users are therefore -* encouraged to load and test the software's suitability as regards their -* requirements in conditions enabling the security of their systems and/or -* data to be ensured and, more generally, to use and operate it in the -* same conditions as regards security. -* -* The fact that you are presently reading this means that you have had -* knowledge of the CeCILL license and that you accept its terms. -**/ - -/** - * This file declares one of the basic types used for typing the prover : - * QuantifiedType, the Pi operator. - **/ - -package AST - -import ( - "fmt" - "strings" - - "github.com/GoelandProver/Goeland/Glob" - "github.com/GoelandProver/Goeland/Lib" -) - -/** - * Quantified TypeScheme. - * It has a list of type vars and an associated scheme. - **/ -type QuantifiedType struct { - vars Lib.ComparableList[TypeVar] - scheme TypeScheme -} - -/* TypeScheme interface */ -func (qt QuantifiedType) isScheme() {} -func (qt QuantifiedType) toMappedString(subst map[string]string) string { - return "Π " + strings.Join(convert(qt.vars, typeTToString[TypeVar]), ", ") + ": Type. " + qt.scheme.toMappedString(subst) -} - -func (qt QuantifiedType) Equals(oth interface{}) bool { - return Glob.Is[QuantifiedType](oth) && qt.scheme.Equals(Glob.To[QuantifiedType](oth).scheme) -} - -func (qt QuantifiedType) QuantifiedVarsLen() int { return len(qt.vars) } -func (qt QuantifiedType) QuantifiedVars() Lib.ComparableList[TypeVar] { return qt.vars } -func (qt QuantifiedType) Size() int { return qt.scheme.Size() } - -func (qt QuantifiedType) ToString() string { - return qt.toMappedString(utilMapReverseCreation(qt.vars)) -} - -func (qt QuantifiedType) GetPrimitives() []TypeApp { - vars := make(map[TypeVar]TypeApp) - for i, var_ := range qt.vars { - vars[MkTypeVar(fmt.Sprintf("*_%d", i))] = var_ - } - primitives := []TypeApp{} - for _, th := range qt.scheme.GetPrimitives() { - if Glob.Is[TypeVar](th) { - if var_, found := vars[th.(TypeVar)]; found { - primitives = append(primitives, var_) - } - } else if Glob.Is[ParameterizedType](th) { - primitives = append(primitives, th.instanciate(vars)) - } else { - primitives = append(primitives, th) - } - } - return primitives -} - -func (qt QuantifiedType) Instanciate(types []TypeApp) TypeScheme { - substMap := make(map[TypeVar]TypeApp) - for i := range qt.vars { - substMap[MkTypeVar(fmt.Sprintf("*_%d", i))] = types[i] - } - - tv := []TypeVar{} - for _, var_ := range types { - if Glob.Is[TypeVar](var_) { - tv = append(tv, Glob.To[TypeVar](var_)) - } else if Glob.Is[ParameterizedType](var_) { - prim := Glob.To[ParameterizedType](var_).GetParameters() - for _, p := range prim { - if Glob.Is[TypeVar](p) { - tv = append(tv, Glob.To[TypeVar](p)) - } - } - } else if Glob.Is[TypeScheme](var_) { - prim := Glob.To[TypeScheme](var_).GetPrimitives() - for _, p := range prim { - if Glob.Is[TypeVar](p) { - tv = append(tv, Glob.To[TypeVar](p)) - } - } - } - } - - if Glob.Is[TypeApp](qt.scheme) { - if len(tv) > 0 { - return MkQuantifiedType(tv, Glob.To[TypeScheme](Glob.To[TypeApp](qt.scheme).instanciate(substMap))) - } - return Glob.To[TypeScheme](Glob.To[TypeApp](qt.scheme).instanciate(substMap)) - } else if Glob.Is[TypeArrow](qt.scheme) { - if len(tv) > 0 { - return MkQuantifiedType(tv, Glob.To[TypeArrow](qt.scheme).instanciate(substMap)) - } - return Glob.To[TypeArrow](qt.scheme).instanciate(substMap) - } else { - if len(tv) > 0 { - return MkQuantifiedType(tv, Glob.To[TypeScheme](Glob.To[ParameterizedType](qt.scheme).instanciate(substMap))) - } - return Glob.To[TypeScheme](Glob.To[ParameterizedType](qt.scheme).instanciate(substMap)) - } -} - -/* Makes a QuantifiedType from TypeVars and a TypeScheme. */ -func MkQuantifiedType(vars []TypeVar, typeScheme TypeScheme) QuantifiedType { - // Modify the typeScheme to make it modulo alpha-conversion - - // 1 - Corresponding map creation - metaTypeMap := utilMapCreation(vars) - - // 2 - Substitute all TypeVar with the meta type - switch ts := typeScheme.(type) { - case TypeApp: - typeScheme = ts.substitute(metaTypeMap) - case TypeArrow: - typeScheme = ts.substitute(metaTypeMap) - default: - //Paradoxal - Glob.Anomaly("MkQuantifiedType", "Reached an unreachable case.") - } - - return QuantifiedType{vars: vars, scheme: typeScheme} -} diff --git a/src/AST/quantifiers.go b/src/AST/quantifiers.go index e6d3e009..75b770dc 100644 --- a/src/AST/quantifiers.go +++ b/src/AST/quantifiers.go @@ -47,12 +47,12 @@ type quantifier struct { *MappedString metas Lib.Cache[Lib.Set[Meta], quantifier] index int - varList []Var + varList Lib.List[TypedVar] subForm Form symbol FormulaType } -func makeQuantifier(i int, vars []Var, subForm Form, metas Lib.Set[Meta], symbol FormulaType) quantifier { +func makeQuantifier(i int, vars Lib.List[TypedVar], subForm Form, metas Lib.Set[Meta], symbol FormulaType) quantifier { fms := &MappedString{} qua := quantifier{ fms, @@ -71,18 +71,14 @@ func (q quantifier) GetIndex() int { return q.index } -func (q quantifier) GetVarList() []Var { - return copyVarList(q.varList) +func (q quantifier) GetVarList() Lib.List[TypedVar] { + return Lib.ListCpy(q.varList) } func (q quantifier) GetForm() Form { return q.subForm.Copy() } -func (q quantifier) GetType() TypeScheme { - return DefaultPropType(0) -} - func (q quantifier) forceGetMetas() Lib.Set[Meta] { return q.subForm.GetMetas() } @@ -110,9 +106,9 @@ func ChangeVarSeparator(sep string) string { func (q quantifier) ToMappedStringSurround(mapping MapString, displayTypes bool) string { varStrings := []string{} - for _ = range q.GetVarList() { + for _ = range q.GetVarList().GetSlice() { str := mapping[QuantVarOpen] - str += ListToMappedString(q.GetVarList(), varSeparator, "", mapping, false) + str += ListToMappedString(q.GetVarList().GetSlice(), varSeparator, "", mapping, false) varStrings = append(varStrings, str+mapping[QuantVarClose]) } @@ -129,7 +125,7 @@ func (q quantifier) GetChildFormulas() Lib.List[Form] { func (q quantifier) Equals(other any) bool { if typed, ok := other.(quantifier); ok { - return AreEqualsVarList(q.varList, typed.varList) && q.subForm.Equals(typed.subForm) + return Lib.ListEquals(q.varList, typed.varList) && q.subForm.Equals(typed.subForm) } return false @@ -142,7 +138,7 @@ func (q quantifier) GetSubTerms() Lib.List[Term] { func (q quantifier) copy() quantifier { nq := makeQuantifier( q.GetIndex(), - copyVarList(q.GetVarList()), + Lib.ListCpy(q.varList), q.GetForm(), q.metas.Raw().Copy(), q.symbol, @@ -167,14 +163,14 @@ func (q quantifier) replaceTermByTerm(old Term, new Term) (quantifier, bool) { } func (q quantifier) renameVariables() quantifier { - newVarList := []Var{} + newVarList := Lib.NewList[TypedVar]() newForm := q.GetForm() - for _, v := range q.GetVarList() { + for _, v := range q.GetVarList().GetSlice() { newVar := MakerNewVar(v.GetName()) newVar = MakerVar(fmt.Sprintf("%s%d", newVar.GetName(), newVar.GetIndex())) - newVarList = append(newVarList, newVar) - newForm, _ = newForm.RenameVariables().ReplaceTermByTerm(v, newVar) + newVarList.Append(MkTypedVar(newVar.name, newVar.index, v.ty)) + newForm, _ = newForm.RenameVariables().ReplaceTermByTerm(v.ToBoundVar(), newVar) } return makeQuantifier( diff --git a/src/AST/term_list.go b/src/AST/term-list.go similarity index 93% rename from src/AST/term_list.go rename to src/AST/term-list.go index 98d73cf1..ab4d8823 100644 --- a/src/AST/term_list.go +++ b/src/AST/term-list.go @@ -117,10 +117,6 @@ func EqualsWithoutOrder(tl, other Lib.List[Term]) bool { return Lib.ListEquals(tlSorted.List(), otherSorted.List()) } -func AreEqualsTypeVarList(tv1, tv2 []TypeVar) bool { - return Lib.ComparableList[TypeVar](tv1).Equals(tv2) -} - /* check if two lists of var are equals */ func AreEqualsVarList(tl1, tl2 []Var) bool { if len(tl1) != len(tl2) { @@ -142,11 +138,3 @@ func copyVarList(tl []Var) []Var { } return res } - -func copyTypeVarList(tv []TypeVar) []TypeVar { - res := []TypeVar{} - for _, t := range tv { - res = append(res, t.Copy().(TypeVar)) - } - return res -} diff --git a/src/AST/term.go b/src/AST/term.go index 6b4160d6..23adba38 100644 --- a/src/AST/term.go +++ b/src/AST/term.go @@ -78,16 +78,16 @@ func MakeVar(i int, s string) Var { return newVar } -func MakeMeta(index, occurence int, s string, f int) Meta { +func MakeMeta(index, occurence int, s string, f int, ty Ty) Meta { fms := &MappedString{} - meta := Meta{fms, index, occurence, s, f} + meta := Meta{fms, index, occurence, s, f, ty} fms.MappableString = &meta return meta } -func MakeFun(p Id, args Lib.List[Term], metas Lib.Set[Meta]) Fun { +func MakeFun(p Id, ty_args Lib.List[Ty], args Lib.List[Term], metas Lib.Set[Meta]) Fun { fms := &MappedString{} - fun := Fun{fms, p, args, Lib.MkCache(metas, Fun.forceGetMetas)} + fun := Fun{fms, p, ty_args, args, Lib.MkCache(metas, Fun.forceGetMetas)} fms.MappableString = fun return fun } diff --git a/src/AST/termsDef.go b/src/AST/termsDef.go index 544c2aff..49e2bb6f 100644 --- a/src/AST/termsDef.go +++ b/src/AST/termsDef.go @@ -147,6 +147,7 @@ func (i Id) Less(u any) bool { type Fun struct { *MappedString p Id + tys Lib.List[Ty] args Lib.List[Term] metas Lib.Cache[Lib.Set[Meta], Fun] } @@ -190,6 +191,7 @@ func (f Fun) GetChildrenForMappedString() []MappableString { func (f Fun) GetID() Id { return f.p.Copy().(Id) } func (f Fun) GetP() Id { return f.p.Copy().(Id) } +func (f Fun) GetTyArgs() Lib.List[Ty] { return f.tys } func (f Fun) GetArgs() Lib.List[Term] { return f.args } func (f *Fun) SetArgs(tl Lib.List[Term]) { f.args = tl } @@ -204,9 +206,11 @@ func (f Fun) Equals(t any) bool { switch typed := t.(type) { case Fun: return typed.GetID().Equals(f.GetID()) && + Lib.ListEquals(typed.GetTyArgs(), f.GetTyArgs()) && Lib.ListEquals(typed.GetArgs(), f.GetArgs()) case *Fun: return typed.GetID().Equals(f.GetID()) && + Lib.ListEquals(typed.GetTyArgs(), f.GetTyArgs()) && Lib.ListEquals(typed.GetArgs(), f.GetArgs()) default: return false @@ -214,11 +218,11 @@ func (f Fun) Equals(t any) bool { } func (f Fun) Copy() Term { - return MakeFun(f.GetP(), f.GetArgs(), f.metas.Raw()) + return MakeFun(f.GetP(), Lib.ListCpy(f.GetTyArgs()), Lib.ListCpy(f.GetArgs()), f.metas.Raw()) } func (f Fun) PointerCopy() *Fun { - nf := MakeFun(f.GetP(), f.GetArgs(), f.metas.Raw()) + nf := MakeFun(f.GetP(), f.GetTyArgs(), f.GetArgs(), f.metas.Raw()) return &nf } @@ -256,7 +260,7 @@ func (f Fun) ReplaceSubTermBy(oldTerm, newTerm Term) Term { return newTerm.Copy() } else { tl, res := replaceFirstOccurrenceTermList(f.GetArgs(), oldTerm, newTerm) - nf := MakeFun(f.GetID(), tl, f.metas.Raw()) + nf := MakeFun(f.GetID(), f.GetTyArgs(), tl, f.metas.Raw()) if !res && !f.metas.NeedsUpd() { nf.metas.AvoidUpd() } @@ -269,7 +273,7 @@ func (f Fun) ReplaceAllSubTerm(oldTerm, newTerm Term) Term { return newTerm.Copy() } else { tl, res := ReplaceOccurrence(f.GetArgs(), oldTerm, newTerm) - nf := MakeFun(f.GetID(), tl, f.metas.Raw()) + nf := MakeFun(f.GetID(), f.GetTyArgs(), tl, f.metas.Raw()) if !res && !f.metas.NeedsUpd() { nf.metas.AvoidUpd() } @@ -336,7 +340,7 @@ func (v Var) ReplaceSubTermBy(original_term, new_term Term) Term { func (v Var) ToMappedString(map_ MapString, type_ bool) string { if type_ { - return fmt.Sprintf("%s_%d : %s", v.GetName(), v.GetIndex()) + return fmt.Sprintf("%s_%d", v.GetName(), v.GetIndex()) } return v.GetName() } @@ -347,7 +351,7 @@ func (v Var) ToMappedStringSurround(mapping MapString, displayTypes bool) string func (v Var) ToMappedStringChild(mapping MapString, displayTypes bool) (separator, emptyValue string) { if displayTypes { - return "", fmt.Sprintf("%s_%d : %s", v.GetName(), v.GetIndex()) + return "", fmt.Sprintf("%s_%d", v.GetName(), v.GetIndex()) } else { return "", v.GetName() } @@ -376,7 +380,7 @@ type Meta struct { occurence int name string formula int - // FIXME: remember the type of a Meta + ty Ty } func (m Meta) GetFormula() int { return m.formula } @@ -389,6 +393,7 @@ func (m Meta) IsFun() bool { return false } func (m Meta) ToMeta() Meta { return m } func (m Meta) GetMetas() Lib.Set[Meta] { return Lib.Singleton(m) } func (m Meta) GetMetaList() Lib.List[Meta] { return Lib.MkListV(m) } +func (m Meta) GetTy() Ty { return m.ty } func (m Meta) ToMappedStringSurround(mapping MapString, displayTypes bool) string { return "%s" @@ -396,7 +401,7 @@ func (m Meta) ToMappedStringSurround(mapping MapString, displayTypes bool) strin func (m Meta) ToMappedStringChild(mapping MapString, displayTypes bool) (separator, emptyValue string) { if displayTypes { - return "", fmt.Sprintf("%s_%d : %s", m.GetName(), m.GetIndex()) + return "", fmt.Sprintf("%s_%d : %s", m.GetName(), m.GetIndex(), m.ty.ToString()) } else { return "", fmt.Sprintf("%s_%d", m.GetName(), m.GetIndex()) } @@ -414,7 +419,7 @@ func (m Meta) Equals(t any) bool { } func (m Meta) Copy() Term { - return MakeMeta(m.GetIndex(), m.GetOccurence(), m.GetName(), m.GetFormula()) + return MakeMeta(m.GetIndex(), m.GetOccurence(), m.GetName(), m.GetFormula(), m.GetTy()) } func (m Meta) ReplaceSubTermBy(original_term, new_term Term) Term { @@ -439,7 +444,8 @@ func (m Meta) Less(u any) bool { } func MakeEmptyMeta() Meta { - return MakeMeta(-1, -1, "-1", -1) + // FIXME: nil are bad + return MakeMeta(-1, -1, "-1", -1, nil) } func MetaEquals(x, y Meta) bool { diff --git a/src/AST/tptp-native-types.go b/src/AST/tptp-native-types.go new file mode 100644 index 00000000..7bc401e1 --- /dev/null +++ b/src/AST/tptp-native-types.go @@ -0,0 +1,167 @@ +/** +* Copyright 2022 by the authors (see AUTHORS). +* +* Goéland is an automated theorem prover for first order logic. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +**/ + +/** + * This file declares TPTP native types and types scheme : + * - int, rat, real for primitives + * - a bunch of type schemes + **/ + +package AST + +// FIXME: update this file with the new type system + +// var tInt TypeHint +// var tRat TypeHint +// var tReal TypeHint +// var defaultType TypeHint +// var defaultProp TypeHint + +// var intCrossInt TypeApp +// var ratCrossRat TypeApp +// var realCrossReal TypeApp + +var tType Ty + +func initTPTPNativeTypes() { + tType = MkTyConst("$tType") + // FIXME: always register the equality type in the context. +} + +func TType() Ty { + return tType +} + +func IsTType(ty Ty) bool { + return ty.Equals(tType) +} + +// func InitTPTPArithmetic() { +// // Types +// tInt = MkTypeHint("$int") +// tRat = MkTypeHint("$rat") +// tReal = MkTypeHint("$real") + +// intCrossInt = MkTypeCross(tInt, tInt) +// ratCrossRat = MkTypeCross(tRat, tRat) +// realCrossReal = MkTypeCross(tReal, tReal) + +// // Schemes +// // 1 - Binary predicates +// recordBinaryProp("$less") +// recordBinaryProp("$lesseq") +// recordBinaryProp("$greater") +// recordBinaryProp("$greatereq") + +// // 2 - Binary input arguments +// recordBinaryInArgs("$sum") +// recordBinaryInArgs("$difference") +// recordBinaryInArgs("$product") +// recordBinaryInArgs("$quotient_e") +// recordBinaryInArgs("$quotient_t") +// recordBinaryInArgs("$quotient_f") +// recordBinaryInArgs("$remainder_e") +// recordBinaryInArgs("$remainder_t") +// recordBinaryInArgs("$remainder_f") + +// // 3 - $quotient +// SaveTypeScheme("$quotient", ratCrossRat, tRat) +// SaveTypeScheme("$quotient", realCrossReal, tReal) + +// // 4 - Unary input arguments +// recordUnaryInArgs("$uminus") +// recordUnaryInArgs("$floor") +// recordUnaryInArgs("$ceiling") +// recordUnaryInArgs("$truncate") +// recordUnaryInArgs("$round") + +// // 5 - Unary predicates +// recordUnaryProp("$is_int") +// recordUnaryProp("$is_rat") + +// // 6 - Conversion +// recordConversion("$to_int", tInt) +// recordConversion("$to_rat", tRat) +// recordConversion("$to_real", tReal) +// } + +// func recordBinaryProp(name string) { +// SaveTypeScheme(name, intCrossInt, defaultProp) +// SaveTypeScheme(name, ratCrossRat, defaultProp) +// SaveTypeScheme(name, realCrossReal, defaultProp) +// } + +// func recordBinaryInArgs(name string) { +// SaveTypeScheme(name, intCrossInt, tInt) +// SaveTypeScheme(name, ratCrossRat, tRat) +// SaveTypeScheme(name, realCrossReal, tReal) +// } + +// func recordUnaryInArgs(name string) { +// SaveTypeScheme(name, tInt, tInt) +// SaveTypeScheme(name, tRat, tRat) +// SaveTypeScheme(name, tReal, tReal) +// } + +// func recordUnaryProp(name string) { +// SaveTypeScheme(name, tInt, defaultProp) +// SaveTypeScheme(name, tRat, defaultProp) +// SaveTypeScheme(name, tReal, defaultProp) +// } + +// func recordConversion(name string, out TypeApp) { +// SaveTypeScheme(name, tInt, out) +// SaveTypeScheme(name, tRat, out) +// SaveTypeScheme(name, tReal, out) +// } + +// func IsInt(tType TypeScheme) bool { return tType.Equals(tInt) } +// func IsRat(tType TypeScheme) bool { return tType.Equals(tRat) } +// func IsReal(tType TypeScheme) bool { return tType.Equals(tReal) } +// func DefaultType() TypeApp { return defaultType } +// func DefaultProp() TypeApp { return defaultProp } +// func DefaultFunType(len int) TypeScheme { return defaultAppType(len, defaultType) } +// func DefaultPropType(len int) TypeScheme { return defaultAppType(len, defaultProp) } + +// func defaultAppType(len int, out TypeApp) TypeScheme { +// if len == 0 { +// return Glob.To[TypeScheme](out) +// } else if len == 1 { +// return MkTypeArrow(defaultType, out) +// } else { +// ts := []TypeApp{} +// for i := 0; i < len; i++ { +// ts = append(ts, defaultType) +// } +// return MkTypeArrow(MkTypeCross(ts...), out) +// } +// } diff --git a/src/AST/tptp_native.go b/src/AST/tptp_native.go deleted file mode 100644 index bb3b1d04..00000000 --- a/src/AST/tptp_native.go +++ /dev/null @@ -1,154 +0,0 @@ -/** -* Copyright 2022 by the authors (see AUTHORS). -* -* Goéland is an automated theorem prover for first order logic. -* -* This software is governed by the CeCILL license under French law and -* abiding by the rules of distribution of free software. You can use, -* modify and/ or redistribute the software under the terms of the CeCILL -* license as circulated by CEA, CNRS and INRIA at the following URL -* "http://www.cecill.info". -* -* As a counterpart to the access to the source code and rights to copy, -* modify and redistribute granted by the license, users are provided only -* with a limited warranty and the software's author, the holder of the -* economic rights, and the successive licensors have only limited -* liability. -* -* In this respect, the user's attention is drawn to the risks associated -* with loading, using, modifying and/or developing or reproducing the -* software by the user in light of its specific status of free software, -* that may mean that it is complicated to manipulate, and that also -* therefore means that it is reserved for developers and experienced -* professionals having in-depth computer knowledge. Users are therefore -* encouraged to load and test the software's suitability as regards their -* requirements in conditions enabling the security of their systems and/or -* data to be ensured and, more generally, to use and operate it in the -* same conditions as regards security. -* -* The fact that you are presently reading this means that you have had -* knowledge of the CeCILL license and that you accept its terms. -**/ - -/** - * This file declares TPTP native types and types scheme : - * - int, rat, real for primitives - * - a bunch of type schemes - **/ - -package AST - -import ( - "github.com/GoelandProver/Goeland/Glob" -) - -var tInt TypeHint -var tRat TypeHint -var tReal TypeHint -var defaultType TypeHint -var defaultProp TypeHint - -var intCrossInt TypeApp -var ratCrossRat TypeApp -var realCrossReal TypeApp - -func InitTPTPArithmetic() { - // Types - tInt = MkTypeHint("$int") - tRat = MkTypeHint("$rat") - tReal = MkTypeHint("$real") - - intCrossInt = MkTypeCross(tInt, tInt) - ratCrossRat = MkTypeCross(tRat, tRat) - realCrossReal = MkTypeCross(tReal, tReal) - - // Schemes - // 1 - Binary predicates - recordBinaryProp("$less") - recordBinaryProp("$lesseq") - recordBinaryProp("$greater") - recordBinaryProp("$greatereq") - - // 2 - Binary input arguments - recordBinaryInArgs("$sum") - recordBinaryInArgs("$difference") - recordBinaryInArgs("$product") - recordBinaryInArgs("$quotient_e") - recordBinaryInArgs("$quotient_t") - recordBinaryInArgs("$quotient_f") - recordBinaryInArgs("$remainder_e") - recordBinaryInArgs("$remainder_t") - recordBinaryInArgs("$remainder_f") - - // 3 - $quotient - SaveTypeScheme("$quotient", ratCrossRat, tRat) - SaveTypeScheme("$quotient", realCrossReal, tReal) - - // 4 - Unary input arguments - recordUnaryInArgs("$uminus") - recordUnaryInArgs("$floor") - recordUnaryInArgs("$ceiling") - recordUnaryInArgs("$truncate") - recordUnaryInArgs("$round") - - // 5 - Unary predicates - recordUnaryProp("$is_int") - recordUnaryProp("$is_rat") - - // 6 - Conversion - recordConversion("$to_int", tInt) - recordConversion("$to_rat", tRat) - recordConversion("$to_real", tReal) -} - -func recordBinaryProp(name string) { - SaveTypeScheme(name, intCrossInt, defaultProp) - SaveTypeScheme(name, ratCrossRat, defaultProp) - SaveTypeScheme(name, realCrossReal, defaultProp) -} - -func recordBinaryInArgs(name string) { - SaveTypeScheme(name, intCrossInt, tInt) - SaveTypeScheme(name, ratCrossRat, tRat) - SaveTypeScheme(name, realCrossReal, tReal) -} - -func recordUnaryInArgs(name string) { - SaveTypeScheme(name, tInt, tInt) - SaveTypeScheme(name, tRat, tRat) - SaveTypeScheme(name, tReal, tReal) -} - -func recordUnaryProp(name string) { - SaveTypeScheme(name, tInt, defaultProp) - SaveTypeScheme(name, tRat, defaultProp) - SaveTypeScheme(name, tReal, defaultProp) -} - -func recordConversion(name string, out TypeApp) { - SaveTypeScheme(name, tInt, out) - SaveTypeScheme(name, tRat, out) - SaveTypeScheme(name, tReal, out) -} - -func IsInt(tType TypeScheme) bool { return tType.Equals(tInt) } -func IsRat(tType TypeScheme) bool { return tType.Equals(tRat) } -func IsReal(tType TypeScheme) bool { return tType.Equals(tReal) } -func DefaultType() TypeApp { return defaultType } -func DefaultProp() TypeApp { return defaultProp } -func DefaultFunType(len int) TypeScheme { return defaultAppType(len, defaultType) } -func DefaultPropType(len int) TypeScheme { return defaultAppType(len, defaultProp) } - -func defaultAppType(len int, out TypeApp) TypeScheme { - if len == 0 { - return Glob.To[TypeScheme](out) - } else if len == 1 { - return MkTypeArrow(defaultType, out) - } else { - ts := []TypeApp{} - for i := 0; i < len; i++ { - ts = append(ts, defaultType) - } - return MkTypeArrow(MkTypeCross(ts...), out) - } -} diff --git a/src/AST/ty-syntax.go b/src/AST/ty-syntax.go new file mode 100644 index 00000000..950d4847 --- /dev/null +++ b/src/AST/ty-syntax.go @@ -0,0 +1,334 @@ +/** +* Copyright 2022 by the authors (see AUTHORS). +* +* Goéland is an automated theorem prover for first order logic. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +**/ + +/** + * This file declares the syntax of the TFF1 type system. + * Variables are internal to polymorphic schemes and are treated with pseudo De Bruijn indices. + **/ + +package AST + +import ( + "fmt" + "github.com/GoelandProver/Goeland/Glob" + "github.com/GoelandProver/Goeland/Lib" +) + +type Ty interface { + isTy() + ToString() string + Equals(any) bool + Copy() Ty +} + +// Internal, shouldn't get out so no upper case +type tyVar struct { + repr string +} + +func (tyVar) isTy() {} +func (v tyVar) ToString() string { return v.repr } +func (v tyVar) Equals(oth any) bool { + if ov, ok := oth.(tyVar); ok { + return v.repr == ov.repr + } + return false +} +func (v tyVar) Copy() Ty { return tyVar{v.repr} } + +type TyBound struct { + name string + index int +} + +func (TyBound) isTy() {} +func (b TyBound) ToString() string { return b.name } +func (b TyBound) Equals(oth any) bool { + if bv, ok := oth.(TyBound); ok { + return b.name == bv.name + } + return false +} +func (b TyBound) Copy() Ty { return TyBound{b.name, b.index} } + +type TyMeta struct { + name string +} + +func (TyMeta) isTy() {} +func (m TyMeta) ToString() string { return m.name } +func (m TyMeta) Equals(oth any) bool { + if om, ok := oth.(TyMeta); ok { + return m.name == om.name + } + return false +} +func (m TyMeta) Copy() Ty { return TyMeta{m.name} } + +// Type constructors, e.g., list, option, ... +// Include constants, e.g., $i, $o, ... +type TyConstr struct { + symbol string + args Lib.List[Ty] +} + +func (TyConstr) isTy() {} + +func (c TyConstr) ToString() string { + if c.args.Len() == 0 { + return c.symbol + } + return c.symbol + "(" + Lib.ListToString(c.args, ", ", "") + ")" +} + +func (c TyConstr) Equals(oth any) bool { + if oc, ok := oth.(TyConstr); ok { + return c.symbol == oc.symbol && + Lib.ListEquals(c.args, oc.args) + } + return false +} + +func (c TyConstr) Copy() Ty { + return TyConstr{c.symbol, Lib.ListCpy(c.args)} +} + +type TyProd struct { + args Lib.List[Ty] +} + +func (TyProd) isTy() {} + +func (p TyProd) ToString() string { + return "(" + Lib.ListToString(p.args, " * ", "") + ")" +} + +func (p TyProd) GetTys() Lib.List[Ty] { + return p.args +} + +func (p TyProd) Equals(oth any) bool { + if op, ok := oth.(TyProd); ok { + return Lib.ListEquals(p.args, op.args) + } + return false +} + +func (p TyProd) Copy() Ty { + return TyProd{Lib.ListCpy(p.args)} +} + +type TyFunc struct { + in, out Ty +} + +func (TyFunc) isTy() {} +func (f TyFunc) ToString() string { + return f.in.ToString() + " > " + f.out.ToString() +} +func (f TyFunc) Equals(oth any) bool { + if of, ok := oth.(TyFunc); ok { + return f.in.Equals(of.in) && f.out.Equals(of.out) + } + return false +} + +func (f TyFunc) Copy() Ty { + return TyFunc{f.in.Copy(), f.out.Copy()} +} + +type TyPi struct { + vars Lib.List[string] + ty Ty +} + +func (TyPi) isTy() {} +func (p TyPi) ToString() string { + return "!> [" + p.vars.ToString(func(s string) string { return s }, ", ", "") + "] : (" + p.ty.ToString() + ")" +} +func (p TyPi) Equals(oth any) bool { + if op, ok := oth.(TyPi); ok { + cmp := func(x, y string) bool { return x == y } + return p.vars.Equals(cmp, p.vars, op.vars) && + p.ty.Equals(op.ty) + } + return false +} + +func (p TyPi) Copy() Ty { + return TyPi{p.vars.Copy(func(x string) string { return x }), p.ty.Copy()} +} + +// Makers + +func MkTyVar(repr string) Ty { + return tyVar{repr} +} + +func MkTyBV(name string, index int) Ty { + return TyBound{name, index} +} + +func MkTyMeta(name string) Ty { + return TyMeta{name} +} + +func MkTyConstr(symbol string, args Lib.List[Ty]) Ty { + return TyConstr{symbol, args} +} + +func MkTyConst(symbol string) Ty { + return TyConstr{symbol, Lib.NewList[Ty]()} +} + +func MkTyProd(args Lib.List[Ty]) Ty { + return TyProd{args} +} + +func MkTyFunc(in, out Ty) Ty { + return TyFunc{in, out} +} + +func MkTyPi(vars Lib.List[string], ty Ty) Ty { + return TyPi{vars, ty} +} + +// FIXME: the Maker logic should be factorized somewhere +func MakerTyBV(name string) Ty { + lock_term.Lock() + i, ok := idVar[name] + lock_term.Unlock() + if ok { + return MkTyBV(name, i) + } else { + lock_term.Lock() + idVar[name] = cpt_term + vr := MkTyBV(name, cpt_term) + cpt_term += 1 + lock_term.Unlock() + return vr + } +} + +func InstantiateTy(ty Ty, instance Lib.List[Ty]) Ty { + switch rty := ty.(type) { + case TyFunc: + if !instance.Empty() { + Glob.Anomaly( + "Ty.Instantiate", + fmt.Sprintf( + "On instantiation of %s: given instance %s has arguments when it shouldn't", + ty.ToString(), + Lib.ListToString(instance, ", ", "(empty instance)"), + ), + ) + } + return ty + case TyPi: + if instance.Len() != rty.vars.Len() { + Glob.Anomaly( + "Ty.Instantiate", + fmt.Sprintf( + "On instantiation of %s: given instance %s does not have the right number of arguments", + ty.ToString(), + Lib.ListToString(instance, ", ", "(empty instance)"), + ), + ) + } + + instanceMap := make(map[string]Ty) + for i, ity := range instance.GetSlice() { + instanceMap[rty.vars.At(i)] = ity + } + return instantiateTyRec(rty.ty, ty, instanceMap) + } + Glob.Anomaly( + "Ty.Instantiate", + fmt.Sprintf("Tried to instantiate %s which is not a Pi-type", ty.ToString()), + ) + return nil +} + +// source type is here for logging +func instantiateTyRec(ty, source Ty, instance map[string]Ty) Ty { + aux := func(ty Ty) Ty { + return instantiateTyRec(ty, source, instance) + } + + switch rty := ty.(type) { + case tyVar: + if val, ok := instance[rty.repr]; ok { + return val + } + Glob.Anomaly( + "Ty.Instantiate", + fmt.Sprintf("Under type %s: type variable %s has no instance", source.ToString(), rty.repr), + ) + + case TyConstr: + return MkTyConstr( + rty.symbol, + Lib.ListMap(rty.args, aux), + ) + + case TyProd: + return MkTyProd(Lib.ListMap(rty.args, aux)) + + case TyFunc: + return MkTyFunc(aux(rty.in), aux(rty.out)) + } + + Glob.Anomaly( + "Ty.Instantiate", + fmt.Sprintf( + "In %s, trying to instantiate %s which is illegal", + source.ToString(), + ty.ToString(), + ), + ) + return nil +} + +func GetArgsTy(ty Ty) Lib.List[Ty] { + switch rty := ty.(type) { + case TyFunc: + switch nty := rty.in.(type) { + case TyProd: + return nty.args + } + } + Glob.Anomaly( + "Ty.GetArgs", + fmt.Sprintf("Tried to extract types of arguments of a non-functional type %s", ty.ToString()), + ) + return Lib.NewList[Ty]() +} diff --git a/src/AST/typearrow.go b/src/AST/typearrow.go deleted file mode 100644 index 6690f424..00000000 --- a/src/AST/typearrow.go +++ /dev/null @@ -1,159 +0,0 @@ -/** -* Copyright 2022 by the authors (see AUTHORS). -* -* Goéland is an automated theorem prover for first order logic. -* -* This software is governed by the CeCILL license under French law and -* abiding by the rules of distribution of free software. You can use, -* modify and/ or redistribute the software under the terms of the CeCILL -* license as circulated by CEA, CNRS and INRIA at the following URL -* "http://www.cecill.info". -* -* As a counterpart to the access to the source code and rights to copy, -* modify and redistribute granted by the license, users are provided only -* with a limited warranty and the software's author, the holder of the -* economic rights, and the successive licensors have only limited -* liability. -* -* In this respect, the user's attention is drawn to the risks associated -* with loading, using, modifying and/or developing or reproducing the -* software by the user in light of its specific status of free software, -* that may mean that it is complicated to manipulate, and that also -* therefore means that it is reserved for developers and experienced -* professionals having in-depth computer knowledge. Users are therefore -* encouraged to load and test the software's suitability as regards their -* requirements in conditions enabling the security of their systems and/or -* data to be ensured and, more generally, to use and operate it in the -* same conditions as regards security. -* -* The fact that you are presently reading this means that you have had -* knowledge of the CeCILL license and that you accept its terms. -**/ - -/** - * This file declares one of the basic types used for typing the prover : - * TypeArrow, the -> operator. It's implemented as an input scheme (TypeApp) - * and output arguments (array of TypeScheme). - **/ - -package AST - -import ( - "fmt" - "strings" - - "github.com/GoelandProver/Goeland/Glob" - "github.com/GoelandProver/Goeland/Lib" -) - -/** - * Type consisting of two TypeSchemes : the in-arguments parameter(s) and the out parameter. - * For example, if a function f takes to parameters of type int, and returns an int, it - * will be typed as f : (int * int) -> int - * TypeCross has higher precedence than TypeArrow. - **/ -type TypeArrow struct { - left TypeApp - right Lib.ComparableList[TypeApp] -} - -/* TypeScheme interface */ -// Unexported methods. -func (ta TypeArrow) isScheme() {} -func (ta TypeArrow) toMappedString(subst map[string]string) string { - mappedString := []string{Glob.To[TypeScheme](ta.left).toMappedString(subst)} - for _, typeScheme := range convert(ta.right, typeAppToTypeScheme) { - mappedString = append(mappedString, typeScheme.toMappedString(subst)) - } - return "(" + strings.Join(mappedString, " > ") + ")" -} - -/* TypeArrow methods */ -func (ta TypeArrow) substitute(mapSubst map[TypeVar]string) TypeScheme { - return MkTypeArrow(ta.left.substitute(mapSubst).(TypeApp), substTypeAppList(mapSubst, ta.right)...) -} -func (ta TypeArrow) instanciate(mapSubst map[TypeVar]TypeApp) TypeScheme { - return MkTypeArrow(ta.left.instanciate(mapSubst), instanciateList(mapSubst, ta.right)...) -} - -// Exported methods. -/** - * Returns a string of a TypeArrow: (type1 > type2 > ... > typeN). - **/ -func (ta TypeArrow) ToString() string { - list := []string{ta.left.ToString()} - list = append(list, convert(ta.right, typeTToString[TypeApp])...) - return "(" + strings.Join(list, " > ") + ")" -} - -func (ta TypeArrow) Equals(oth interface{}) bool { - if !Glob.Is[TypeArrow](oth) { - return false - } - - othTA := Glob.To[TypeArrow](oth) - return ((ta.left == nil && othTA.left == nil) || ta.left.Equals(othTA.left)) && ta.right.Equals(othTA.right) -} - -func (ta TypeArrow) Size() int { - return ta.left.Size() + sum(convert(ta.right, typeTToSize[TypeApp])) -} - -func (ta TypeArrow) GetPrimitives() []TypeApp { - typeApp := []TypeApp{} - typeApp = typeAppToUnderlyingType(typeApp, ta.left) - return append(typeApp, convert(ta.right, typeAppToUnderlyingType)...) -} - -/* Makes a TypeArrow from two TypeSchemes */ -func MkTypeArrow(left TypeApp, typeApps ...TypeApp) TypeArrow { - if len(typeApps) < 1 { - debug(Lib.MkLazy(func() string { return "There should be at least one out type in a TypeArrow." })) - return TypeArrow{} - } - ta := TypeArrow{left: left, right: make(Lib.ComparableList[TypeApp], len(typeApps))} - copy(ta.right, typeApps) - return ta -} - -/* Gets the out type of an arrow type scheme */ -func GetOutType(typeScheme TypeScheme) TypeApp { - switch t := typeScheme.(type) { - case TypeArrow: - // Returns the out type of the last arrow. - return GetOutType(Glob.To[TypeScheme](t.right[len(t.right)-1])) - case QuantifiedType: - vars := make(map[TypeVar]string) - for i, var_ := range t.vars { - vars[MkTypeVar(fmt.Sprintf("*_%d", i))] = var_.ToString() - } - - if Glob.Is[TypeArrow](t.scheme) { - return GetOutType(Glob.To[TypeArrow](t.scheme).substitute(vars)) - } else { - return GetOutType(Glob.To[TypeApp](t.scheme).substitute(vars)) - } - // typeScheme may be a TypeHint if it comes from a constant. - case TypeHint: - return t - // Everything else is a TypeApp anyways - default: - return t.(TypeApp) - } -} - -/* Gets the input type of an arrow type scheme */ -func GetInputType(typeScheme TypeScheme) Lib.ComparableList[TypeApp] { - switch t := typeScheme.(type) { - case QuantifiedType: - return GetInputType(t.scheme) - case TypeArrow: - typeArrow := Glob.To[TypeArrow](typeScheme) - list := Lib.ComparableList[TypeApp]{typeArrow.left} - list = append(list, typeArrow.right[:len(typeArrow.right)-1]...) - return list - case TypeApp: - return []TypeApp{t} - } - return nil -} diff --git a/src/AST/typecross.go b/src/AST/typecross.go deleted file mode 100644 index 73466cb1..00000000 --- a/src/AST/typecross.go +++ /dev/null @@ -1,129 +0,0 @@ -/** -* Copyright 2022 by the authors (see AUTHORS). -* -* Goéland is an automated theorem prover for first order logic. -* -* This software is governed by the CeCILL license under French law and -* abiding by the rules of distribution of free software. You can use, -* modify and/ or redistribute the software under the terms of the CeCILL -* license as circulated by CEA, CNRS and INRIA at the following URL -* "http://www.cecill.info". -* -* As a counterpart to the access to the source code and rights to copy, -* modify and redistribute granted by the license, users are provided only -* with a limited warranty and the software's author, the holder of the -* economic rights, and the successive licensors have only limited -* liability. -* -* In this respect, the user's attention is drawn to the risks associated -* with loading, using, modifying and/or developing or reproducing the -* software by the user in light of its specific status of free software, -* that may mean that it is complicated to manipulate, and that also -* therefore means that it is reserved for developers and experienced -* professionals having in-depth computer knowledge. Users are therefore -* encouraged to load and test the software's suitability as regards their -* requirements in conditions enabling the security of their systems and/or -* data to be ensured and, more generally, to use and operate it in the -* same conditions as regards security. -* -* The fact that you are presently reading this means that you have had -* knowledge of the CeCILL license and that you accept its terms. -**/ - -/** - * This file declares one of the basic types used for typing the prover : - * TypeCross, a conjonction of types. It's a list of TypeApp. - * A TypeArrow can not be a child of a conjonction in first order (no currification occurs). - * Otherwise, the children would be of type TypeScheme. - **/ - -package AST - -import ( - "strings" - - "github.com/GoelandProver/Goeland/Glob" - "github.com/GoelandProver/Goeland/Lib" -) - -/** - * A conjonction of types. - * The UID is calculated on creation. - * Please, use MkTypeCross() to make a new TypeCross. - * It's used, for example, for function or predicate arguments. - * For example, take the function + on natural numbers. It takes 2 integers as arguments : - * +: int*int > int - * This notation is the same as +: int > int > int (as > is an imply, - * not(int) v not(int) v int is equivalent to not(int ^ int) v int = int * int > int). - **/ -type TypeCross struct { - types Lib.ComparableList[TypeApp] -} - -/* TypeScheme interface */ -// Non-exported methods. -func (tc TypeCross) isScheme() {} -func (tc TypeCross) toMappedString(subst map[string]string) string { - mappedString := []string{} - for _, typeScheme := range convert(tc.types, typeAppToTypeScheme) { - mappedString = append(mappedString, typeScheme.toMappedString(subst)) - } - if Glob.IsLambdapiOutput() { - return strings.Join(mappedString, " → ") - } - return "(" + strings.Join(mappedString, " * ") + ")" -} - -// Exported methods. -func (tc TypeCross) ToString() string { - if Glob.IsLambdapiOutput() { - return strings.Join(convert(tc.types, typeTToString[TypeApp]), " → ") - } - return "(" + strings.Join(convert(tc.types, typeTToString[TypeApp]), " * ") + ")" -} -func (tc TypeCross) Size() int { return sum(convert(tc.types, typeTToSize[TypeApp])) } - -// GetAllUnderlyingTypes ? Or just tc.types ? I'm thinking the 2nd is better cause the first looses associativity ? Is it fine ? -func (tc TypeCross) GetPrimitives() []TypeApp { return tc.GetAllUnderlyingTypes() } - -func (tc TypeCross) Equals(oth interface{}) bool { - return Glob.Is[TypeCross](oth) && tc.types.Equals(Glob.To[TypeCross](oth).types) -} - -/* TypeApp interface */ -// Non-exported methods. -func (tc TypeCross) isTypeApp() {} -func (tc TypeCross) substitute(mapSubst map[TypeVar]string) TypeScheme { - return MkTypeCross(substTypeAppList(mapSubst, tc.types)...) -} -func (tc TypeCross) instanciate(mapSubst map[TypeVar]TypeApp) TypeApp { - return MkTypeCross(instanciateList(mapSubst, tc.types)...) -} - -// Exported methods. -/** - * Copies the TypeApp slice to avoid wrong modifications. - **/ -func (tc TypeCross) Copy() TypeApp { - return MkTypeCross(convert(tc.types, copyTypeApp)...) -} - -/** - * Returns all primitive types composing this cross type. - **/ -func (tc TypeCross) GetAllUnderlyingTypes() []TypeApp { - return convert(tc.types, typeAppToUnderlyingType) -} - -/** - * Makes a TypeCross from any number of TypeApp. - **/ -func MkTypeCross(typeSchemes ...TypeApp) TypeCross { - if len(typeSchemes) < 2 { - debug(Lib.MkLazy(func() string { return "There should be at least two underlying types in a TypeCross." })) - return TypeCross{} - } - tc := TypeCross{types: make([]TypeApp, len(typeSchemes))} - copy(tc.types, typeSchemes) - return tc -} diff --git a/src/AST/typed-vars.go b/src/AST/typed-vars.go new file mode 100644 index 00000000..f9514fb4 --- /dev/null +++ b/src/AST/typed-vars.go @@ -0,0 +1,129 @@ +/** +* Copyright 2022 by the authors (see AUTHORS). +* +* Goéland is an automated theorem prover for first order logic. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +**/ + +/** +* This file implements an interface for bound variables. +**/ + +package AST + +import ( + "fmt" +) + +type TypedVar struct { + name string + index int + ty Ty +} + +func (v TypedVar) Copy() TypedVar { + return TypedVar{v.name, v.index, v.ty.Copy()} +} + +func (v TypedVar) Equals(oth any) bool { + if ov, ok := oth.(TypedVar); ok { + return v.name == ov.name && v.index == ov.index && + v.ty.Equals(ov.ty) + } + return false +} + +func (v TypedVar) ToString() string { + return fmt.Sprintf("%s_%d : %s", v.name, v.index, v.ty.ToString()) +} + +func (v TypedVar) GetName() string { + return v.name +} + +func (v TypedVar) GetIndex() int { + return v.index +} + +func (v TypedVar) GetTy() Ty { + return v.ty +} + +func (v TypedVar) ToBoundVar() Var { + return MakeVar(v.index, v.name) +} + +func (v TypedVar) ToTyBoundVar() TyBound { + return MkTyBV(v.name, v.index).(TyBound) +} + +func MkTypedVar(name string, index int, ty Ty) TypedVar { + return TypedVar{name, index, ty} +} + +func MakerTypedVar(name string, ty Ty) TypedVar { + lock_term.Lock() + i, ok := idVar[name] + lock_term.Unlock() + if ok { + return MkTypedVar(name, i, ty) + } else { + lock_term.Lock() + idVar[name] = cpt_term + vr := MkTypedVar(name, cpt_term, ty) + cpt_term += 1 + lock_term.Unlock() + return vr + } +} + +// ----------------------------------------------------------------------------- +// Mappable string interface + +func (v TypedVar) GetChildrenForMappedString() []MappableString { + return []MappableString{} +} + +func (v TypedVar) ToMappedString(map_ MapString, type_ bool) string { + if type_ { + return fmt.Sprintf("%s : %s", v.name, v.ty.ToString()) + } + return v.name +} + +func (v TypedVar) ToMappedStringChild(mapping MapString, displayTypes bool) (separator, emptyValue string) { + if displayTypes { + return "", fmt.Sprintf("%s : %s", v.name, v.ty.ToString()) + } else { + return "", v.name + } +} + +func (TypedVar) ToMappedStringSurround(_ MapString, _ bool) string { + return "%s" +} diff --git a/src/AST/typehint.go b/src/AST/typehint.go deleted file mode 100644 index 9732181f..00000000 --- a/src/AST/typehint.go +++ /dev/null @@ -1,120 +0,0 @@ -/** -* Copyright 2022 by the authors (see AUTHORS). -* -* Goéland is an automated theorem prover for first order logic. -* -* This software is governed by the CeCILL license under French law and -* abiding by the rules of distribution of free software. You can use, -* modify and/ or redistribute the software under the terms of the CeCILL -* license as circulated by CEA, CNRS and INRIA at the following URL -* "http://www.cecill.info". -* -* As a counterpart to the access to the source code and rights to copy, -* modify and redistribute granted by the license, users are provided only -* with a limited warranty and the software's author, the holder of the -* economic rights, and the successive licensors have only limited -* liability. -* -* In this respect, the user's attention is drawn to the risks associated -* with loading, using, modifying and/or developing or reproducing the -* software by the user in light of its specific status of free software, -* that may mean that it is complicated to manipulate, and that also -* therefore means that it is reserved for developers and experienced -* professionals having in-depth computer knowledge. Users are therefore -* encouraged to load and test the software's suitability as regards their -* requirements in conditions enabling the security of their systems and/or -* data to be ensured and, more generally, to use and operate it in the -* same conditions as regards security. -* -* The fact that you are presently reading this means that you have had -* knowledge of the CeCILL license and that you accept its terms. -**/ - -/** - * This file declares the basic types used for typing the prover : - * TypeHint, a primitive type that is used as the basis of the inductive relation - **/ - -package AST - -import ( - "sync" - - "github.com/GoelandProver/Goeland/Glob" -) - -/** - * Primitive type composed of an unique identifier, used to identify it from - * other types, and a name, used for printing options. - **/ -type TypeHint struct { - uid uint64 /* Real ID */ - name string /* Name */ -} - -/* TypeScheme interface */ -// Non-exported methods -func (th TypeHint) isScheme() {} -func (th TypeHint) toMappedString(subst map[string]string) string { return th.ToString() } - -// Exported methods -func (th TypeHint) ToString() string { return th.name } -func (th TypeHint) Size() int { return 1 } -func (th TypeHint) GetPrimitives() []TypeApp { return []TypeApp{th} } - -func (th TypeHint) Equals(oth interface{}) bool { - return Glob.Is[TypeHint](oth) && Glob.To[TypeHint](oth).uid == th.uid -} - -/* TypeApp interface */ -// Non-exported methods -func (th TypeHint) isTypeApp() {} -func (th TypeHint) substitute(mapSubst map[TypeVar]string) TypeScheme { return th } -func (th TypeHint) instanciate(map[TypeVar]TypeApp) TypeApp { return th } - -// Exported methods -func (th TypeHint) Copy() TypeApp { return MkTypeHint(th.name) } - -/* Current unused unique identifier. Comes with a lock. */ -var tCounter struct { - count uint64 - lock sync.Mutex -} - -/* Map of all the unique identifiers of the different types based on their name. */ -var tMap struct { - uidsMap map[string]TypeHint - lock sync.Mutex -} - -/** - * Makes a TypeHint. - * If the name of the type already exists in the map, returns it. - * Else, creates a new TypeHint with a new unique identifier and updates the map recording - * the types. - **/ -func MkTypeHint(typeName string) TypeHint { - // 1 - search if the type is already declared. Returns it if it's found. - tMap.lock.Lock() - if tHint, found := tMap.uidsMap[typeName]; found { - tMap.lock.Unlock() - return tHint - } - tMap.lock.Unlock() - - // 2 - creation of a new type. - tCounter.lock.Lock() - tHint := TypeHint{ - uid: tCounter.count, - name: typeName, - } - tCounter.count += 1 - tCounter.lock.Unlock() - - // 3 - update of the map. - tMap.lock.Lock() - tMap.uidsMap[typeName] = tHint - tMap.lock.Unlock() - - return tHint -} diff --git a/src/AST/typevar.go b/src/AST/typevar.go deleted file mode 100644 index 3051df64..00000000 --- a/src/AST/typevar.go +++ /dev/null @@ -1,126 +0,0 @@ -/** -* Copyright 2022 by the authors (see AUTHORS). -* -* Goéland is an automated theorem prover for first order logic. -* -* This software is governed by the CeCILL license under French law and -* abiding by the rules of distribution of free software. You can use, -* modify and/ or redistribute the software under the terms of the CeCILL -* license as circulated by CEA, CNRS and INRIA at the following URL -* "http://www.cecill.info". -* -* As a counterpart to the access to the source code and rights to copy, -* modify and redistribute granted by the license, users are provided only -* with a limited warranty and the software's author, the holder of the -* economic rights, and the successive licensors have only limited -* liability. -* -* In this respect, the user's attention is drawn to the risks associated -* with loading, using, modifying and/or developing or reproducing the -* software by the user in light of its specific status of free software, -* that may mean that it is complicated to manipulate, and that also -* therefore means that it is reserved for developers and experienced -* professionals having in-depth computer knowledge. Users are therefore -* encouraged to load and test the software's suitability as regards their -* requirements in conditions enabling the security of their systems and/or -* data to be ensured and, more generally, to use and operate it in the -* same conditions as regards security. -* -* The fact that you are presently reading this means that you have had -* knowledge of the CeCILL license and that you accept its terms. -**/ - -/** - * This file declares one of the basic types used for typing the prover : - * TypeVar, a variable of type. - **/ - -package AST - -import ( - "github.com/GoelandProver/Goeland/Glob" -) - -const ( - BAD_INDEX = -1 -) - -/** - * A quantified variable of type. - * It can serve in arguments of a function or predicate. - **/ -type TypeVar struct { - name string - metaInfo struct { - formulaIndex int - index int - occurence int - } -} - -/* TypeScheme interface */ -// Non-exported methods. -func (tv TypeVar) isScheme() {} -func (tv TypeVar) toMappedString(subst map[string]string) string { - if substString, inMap := subst[tv.name]; inMap { - return substString - } - return tv.name -} - -// Exported methods. -func (tv TypeVar) ToString() string { return tv.name } -func (tv TypeVar) Size() int { return 1 } -func (tv TypeVar) GetPrimitives() []TypeApp { return []TypeApp{tv} } - -func (tv TypeVar) Equals(oth interface{}) bool { - if tv.metaInfo.formulaIndex != BAD_INDEX && tv.metaInfo.index != BAD_INDEX { - return true - } - if !Glob.Is[TypeVar](oth) { - return false - } - typeVar := Glob.To[TypeVar](oth) - return typeVar.name == tv.name && typeVar.metaInfo == tv.metaInfo -} - -/* TypeApp interface */ -func (tv TypeVar) isTypeApp() {} - -func (tv TypeVar) substitute(mapSubst map[TypeVar]string) TypeScheme { - newTv := tv.Copy().(TypeVar) - newTv.name = mapSubst[tv] - return newTv -} - -func (tv TypeVar) instanciate(mapSubst map[TypeVar]TypeApp) TypeApp { - if typeApp, found := mapSubst[tv]; found { - return typeApp - } else { - return tv - } -} - -func (tv TypeVar) Copy() TypeApp { - newTv := MkTypeVar(tv.name) - newTv.metaInfo = tv.metaInfo - return newTv -} - -/* TypeVar should be converted to Meta when becoming a term */ -func (tv *TypeVar) ShouldBeMeta(formula int) { tv.metaInfo.formulaIndex = formula } -func (tv *TypeVar) Instantiate(index int) { tv.metaInfo.index = index } -func (tv TypeVar) IsMeta() bool { return tv.metaInfo.formulaIndex != BAD_INDEX } -func (tv TypeVar) Instantiated() bool { return tv.metaInfo.index != BAD_INDEX } -func (tv TypeVar) MetaInfos() (int, int, int) { - return tv.metaInfo.formulaIndex, tv.metaInfo.index, tv.metaInfo.occurence -} - -/* Makes a TypeVar from a name */ -func MkTypeVar(name string) TypeVar { - return TypeVar{name, struct { - formulaIndex int - index int - occurence int - }{BAD_INDEX, BAD_INDEX, BAD_INDEX}} -} diff --git a/src/AST/typing_utils.go b/src/AST/typing_utils.go deleted file mode 100644 index 14b00541..00000000 --- a/src/AST/typing_utils.go +++ /dev/null @@ -1,118 +0,0 @@ -/** -* Copyright 2022 by the authors (see AUTHORS). -* -* Goéland is an automated theorem prover for first order logic. -* -* This software is governed by the CeCILL license under French law and -* abiding by the rules of distribution of free software. You can use, -* modify and/ or redistribute the software under the terms of the CeCILL -* license as circulated by CEA, CNRS and INRIA at the following URL -* "http://www.cecill.info". -* -* As a counterpart to the access to the source code and rights to copy, -* modify and redistribute granted by the license, users are provided only -* with a limited warranty and the software's author, the holder of the -* economic rights, and the successive licensors have only limited -* liability. -* -* In this respect, the user's attention is drawn to the risks associated -* with loading, using, modifying and/or developing or reproducing the -* software by the user in light of its specific status of free software, -* that may mean that it is complicated to manipulate, and that also -* therefore means that it is reserved for developers and experienced -* professionals having in-depth computer knowledge. Users are therefore -* encouraged to load and test the software's suitability as regards their -* requirements in conditions enabling the security of their systems and/or -* data to be ensured and, more generally, to use and operate it in the -* same conditions as regards security. -* -* The fact that you are presently reading this means that you have had -* knowledge of the CeCILL license and that you accept its terms. -**/ - -/** - * This file stores various utils functions for typing. - **/ - -package AST - -import ( - "github.com/GoelandProver/Goeland/Glob" -) - -type Type interface { - Size() int - ToString() string -} - -/** - * Converts a TypeApp to a TypeScheme. - * If the TypeApp is not a TypeScheme, it doesn't do anything. - **/ -func typeAppToTypeScheme(ls []TypeScheme, in TypeApp) []TypeScheme { - if typeScheme := Glob.To[TypeScheme](in); Glob.Is[TypeScheme](in) { - return append(ls, typeScheme) - } - return ls -} - -/** - * Adds input TypeScheme argument String to the list. - * Should be used on call to convert function. - **/ -func typeTToString[T Type](ls []string, in T) []string { - return append(ls, in.ToString()) -} - -/** - * Adds the size of the TypeScheme argument to the list. - * Should be used on call to convert function. - **/ -func typeTToSize[T Type](ls []int, in T) []int { - return append(ls, in.Size()) -} - -/** - * Copies in to the list. - * Use in convert function as a lambda. - **/ -func copyTypeApp(ls []TypeApp, in TypeApp) []TypeApp { - return append(ls, in.Copy()) -} - -/** - * Adds underlying types of the TypeApp argument to the list. - * Should be used on call to convert function. - **/ -func typeAppToUnderlyingType(ls []TypeApp, in TypeApp) []TypeApp { - if tc, isTc := in.(TypeCross); isTc { - return append(ls, tc.GetAllUnderlyingTypes()...) - } else { - return append(ls, in) - } -} - -/** - * Factorizes the loop needed to populate a list of elements with a new type. - * It needs : - * - the original list - * - a transformation function, taking as input the transformed list and the current element. - * If the current element doesn't fit the model of the transformation, you can just return - * the list. Else, append the transformed element to the list and return it. - **/ -func convert[T any, U any](list []T, transform func([]U, T) []U) []U { - transformedList := []U{} - for _, element := range list { - transformedList = transform(transformedList, element) - } - return transformedList -} - -/** Sums a list. **/ -func sum(list []int) int { - s := 0 - for _, element := range list { - s += element - } - return s -} diff --git a/src/Core/Sko/inner-skolemization.go b/src/Core/Sko/inner-skolemization.go index 93abe49d..3db9f882 100644 --- a/src/Core/Sko/inner-skolemization.go +++ b/src/Core/Sko/inner-skolemization.go @@ -47,34 +47,35 @@ import ( type InnerSkolemization struct { existingSymbols Lib.Set[AST.Id] - mu sync.Mutex + mu *sync.Mutex } func MkInnerSkolemization() InnerSkolemization { return InnerSkolemization{ existingSymbols: Lib.EmptySet[AST.Id](), - mu: sync.Mutex{}, + mu: &sync.Mutex{}, } } func (sko InnerSkolemization) Skolemize( _, form AST.Form, - x AST.Var, + x AST.TypedVar, _ Lib.Set[AST.Meta], ) (Skolemization, AST.Form) { sko.mu.Lock() - symbol := genFreshSymbol(&sko.existingSymbols, &sko.mu, x) + symbol := genFreshSymbol(&sko.existingSymbols, x) sko.mu.Unlock() internalMetas := form.GetMetas().Elements() skolemFunc := AST.MakerFun( symbol, + Lib.NewList[AST.Ty](), Lib.ListMap(internalMetas, Glob.To[AST.Term]), ) skolemizedForm, _ := form.ReplaceTermByTerm( - Glob.To[AST.Term](x), + x.ToBoundVar(), Glob.To[AST.Term](skolemFunc), ) diff --git a/src/Core/Sko/interface.go b/src/Core/Sko/interface.go index 984e345f..647a24e8 100644 --- a/src/Core/Sko/interface.go +++ b/src/Core/Sko/interface.go @@ -34,7 +34,6 @@ package Sko import ( "fmt" - "sync" "github.com/GoelandProver/Goeland/AST" "github.com/GoelandProver/Goeland/Lib" @@ -53,7 +52,7 @@ type Skolemization interface { Skolemize( AST.Form, AST.Form, - AST.Var, + AST.TypedVar, Lib.Set[AST.Meta], ) (Skolemization, AST.Form) } @@ -61,7 +60,7 @@ type Skolemization interface { /* If every Skolem symbol is created using this function, then it will generate * a fresh symbol for sure. Otherwise, nothing is guaranteed. */ -func genFreshSymbol(existingSymbols *Lib.Set[AST.Id], mu *sync.Mutex, x AST.Var) AST.Id { +func genFreshSymbol(existingSymbols *Lib.Set[AST.Id], x AST.TypedVar) AST.Id { symbol := AST.MakerNewId( fmt.Sprintf("skolem@%v", x.GetName()), ) diff --git a/src/Core/Sko/outer-skolemization.go b/src/Core/Sko/outer-skolemization.go index 1e199fe4..1cfa7fa8 100644 --- a/src/Core/Sko/outer-skolemization.go +++ b/src/Core/Sko/outer-skolemization.go @@ -47,34 +47,35 @@ import ( type OuterSkolemization struct { existingSymbols Lib.Set[AST.Id] - mu sync.Mutex + mu *sync.Mutex } func MkOuterSkolemization() OuterSkolemization { return OuterSkolemization{ existingSymbols: Lib.EmptySet[AST.Id](), - mu: sync.Mutex{}, + mu: &sync.Mutex{}, } } func (sko OuterSkolemization) Skolemize( _, form AST.Form, - x AST.Var, + x AST.TypedVar, fvs Lib.Set[AST.Meta], ) (Skolemization, AST.Form) { sko.mu.Lock() - symbol := genFreshSymbol(&sko.existingSymbols, &sko.mu, x) + symbol := genFreshSymbol(&sko.existingSymbols, x) sko.mu.Unlock() metas := fvs.Elements() skolemFunc := AST.MakerFun( symbol, + Lib.NewList[AST.Ty](), Lib.ListMap(metas, Glob.To[AST.Term]), ) skolemizedForm, _ := form.ReplaceTermByTerm( - Glob.To[AST.Term](x), + x.ToBoundVar(), Glob.To[AST.Term](skolemFunc), ) diff --git a/src/Core/Sko/preinner-skolemization.go b/src/Core/Sko/preinner-skolemization.go index 84e36676..b81cd965 100644 --- a/src/Core/Sko/preinner-skolemization.go +++ b/src/Core/Sko/preinner-skolemization.go @@ -49,20 +49,20 @@ import ( type PreInnerSkolemization struct { existingSymbols Lib.Set[AST.Id] linkedSymbols Lib.List[Glob.Pair[AST.Form, AST.Id]] - mu sync.Mutex + mu *sync.Mutex } func MkPreInnerSkolemization() PreInnerSkolemization { return PreInnerSkolemization{ existingSymbols: Lib.EmptySet[AST.Id](), linkedSymbols: Lib.NewList[Glob.Pair[AST.Form, AST.Id]](), - mu: sync.Mutex{}, + mu: &sync.Mutex{}, } } func (sko PreInnerSkolemization) Skolemize( delta, form AST.Form, - x AST.Var, + x AST.TypedVar, _ Lib.Set[AST.Meta], ) (Skolemization, AST.Form) { realDelta := alphaConvert(delta, 0, make(map[int]AST.Var)) @@ -75,7 +75,7 @@ func (sko PreInnerSkolemization) Skolemize( ); ok { symbol = val.Snd } else { - symbol = genFreshSymbol(&sko.existingSymbols, &sko.mu, x) + symbol = genFreshSymbol(&sko.existingSymbols, x) sko.linkedSymbols.Append(Glob.MakePair(realDelta, symbol)) } sko.mu.Unlock() @@ -84,11 +84,12 @@ func (sko PreInnerSkolemization) Skolemize( skolemFunc := AST.MakerFun( symbol, + Lib.NewList[AST.Ty](), Lib.ListMap(internalMetas, Glob.To[AST.Term]), ) skolemizedForm, _ := form.ReplaceTermByTerm( - Glob.To[AST.Term](x), + x.ToBoundVar(), Glob.To[AST.Term](skolemFunc), ) @@ -115,6 +116,7 @@ func alphaConvert( return AST.MakePred( f.GetIndex(), f.GetID(), + f.GetTyArgs(), mappedTerms, ) case AST.Not: @@ -170,15 +172,15 @@ func alphaConvert( func makeConvertedVarList( k int, substitution map[int]AST.Var, - vl []AST.Var, -) (int, map[int]AST.Var, []AST.Var) { - newVarList := []AST.Var{} - for i, v := range vl { - nv := AST.MakeVar(k+i, fresh(k+i)) - newVarList = append(newVarList, nv) - substitution[v.GetIndex()] = nv + vl Lib.List[AST.TypedVar], +) (int, map[int]AST.Var, Lib.List[AST.TypedVar]) { + newVarList := Lib.MkList[AST.TypedVar](vl.Len()) + for i, v := range vl.GetSlice() { + nv := AST.MkTypedVar(fresh(k+i), k+i, v.GetTy()) + newVarList.Upd(i, nv) + substitution[v.GetIndex()] = nv.ToBoundVar() } - return k + len(vl), substitution, newVarList + return k + vl.Len(), substitution, newVarList } func alphaConvertTerm(t AST.Term, substitution map[int]AST.Var) AST.Term { @@ -196,6 +198,7 @@ func alphaConvertTerm(t AST.Term, substitution map[int]AST.Var) AST.Term { }) return AST.MakerFun( nt.GetID(), + nt.GetTyArgs(), mappedTerms, ) } diff --git a/src/Core/instanciation.go b/src/Core/instanciation.go index 5df870d8..58a517b0 100644 --- a/src/Core/instanciation.go +++ b/src/Core/instanciation.go @@ -65,14 +65,14 @@ func Instantiate(fnt FormAndTerms, index int) (FormAndTerms, Lib.Set[AST.Meta]) } func RealInstantiate( - varList []AST.Var, + varList Lib.List[AST.TypedVar], index, status int, subForm AST.Form, terms Lib.List[AST.Term], ) (FormAndTerms, AST.Meta) { - v := varList[0] - meta := AST.MakerMeta(strings.ToUpper(v.GetName()), index) - subForm = subForm.SubstituteVarByMeta(v, meta) + v := varList.At(0) + meta := AST.MakerMeta(strings.ToUpper(v.GetName()), index, v.GetTy()) + subForm = subForm.SubstituteVarByMeta(v.ToBoundVar(), meta) terms = terms.Copy(AST.Term.Copy) terms.Add( @@ -80,12 +80,12 @@ func RealInstantiate( Glob.To[AST.Term](meta), ) - if len(varList) > 1 { + if varList.Len() > 1 { if status == is_exists { - ex := AST.MakerEx(varList[1:], subForm) + ex := AST.MakerEx(varList.Slice(1, varList.Len()), subForm) subForm = AST.MakerNot(ex) } else { - subForm = AST.MakerAll(varList[1:], subForm) + subForm = AST.MakerAll(varList.Slice(1, varList.Len()), subForm) } } else { if status == is_exists { diff --git a/src/Core/skolemisation.go b/src/Core/skolemisation.go index b18593a4..aade0643 100644 --- a/src/Core/skolemisation.go +++ b/src/Core/skolemisation.go @@ -93,7 +93,7 @@ func Skolemize(form AST.Form, branchMetas Lib.Set[AST.Meta]) AST.Form { return realSkolemize( form, f.GetForm(), - f.GetVarList()[0], + f.GetVarList().At(0), f.GetVarList(), branchMetas, isNegAll, @@ -105,7 +105,7 @@ func Skolemize(form AST.Form, branchMetas Lib.Set[AST.Meta]) AST.Form { return realSkolemize( form, nf.GetForm(), - nf.GetVarList()[0], + nf.GetVarList().At(0), nf.GetVarList(), branchMetas, isExists, @@ -119,8 +119,8 @@ func Skolemize(form AST.Form, branchMetas Lib.Set[AST.Meta]) AST.Form { func realSkolemize( initialForm, deltaForm AST.Form, - x AST.Var, - allVars []AST.Var, + x AST.TypedVar, + allVars Lib.List[AST.TypedVar], metas Lib.Set[AST.Meta], typ int, ) AST.Form { @@ -133,13 +133,13 @@ func realSkolemize( selectedSkolemization = sko switch typ { case isNegAll: - if len(allVars) > 1 { - res = AST.MakerAll(allVars[1:], res) + if allVars.Len() > 1 { + res = AST.MakerAll(allVars.Slice(1, allVars.Len()), res) } res = AST.MakerNot(res) case isExists: - if len(allVars) > 1 { - res = AST.MakerEx(allVars[1:], res) + if allVars.Len() > 1 { + res = AST.MakerEx(allVars.Slice(1, allVars.Len()), res) } default: Glob.Anomaly("Skolemization", "impossible reconstruction case") diff --git a/src/Core/statement.go b/src/Core/statement.go index 29fcb21f..5598b747 100644 --- a/src/Core/statement.go +++ b/src/Core/statement.go @@ -50,7 +50,7 @@ func InitDebugger() { type TFFAtomTyping struct { Literal AST.Id - Ts AST.TypeScheme + Ty AST.Ty } // TPTP inputs are a list of statements @@ -137,7 +137,7 @@ func (statement Statement) ToString() string { str := statement.role.ToString() + " " + statement.name + " " switch ty := statement.atomTyping.(type) { case Lib.Some[TFFAtomTyping]: - return str + ty.Val.Literal.GetName() + ": " + ty.Val.Ts.ToString() + return str + ty.Val.Literal.GetName() + ": " + ty.Val.Ty.ToString() case Lib.None[TFFAtomTyping]: return str + "[None]" } diff --git a/src/Core/substitutions_search.go b/src/Core/substitutions_search.go index 2a2169b5..2b17a874 100644 --- a/src/Core/substitutions_search.go +++ b/src/Core/substitutions_search.go @@ -209,21 +209,13 @@ func ApplySubstitutionOnTerm(old_symbol AST.Meta, new_symbol, t AST.Term) AST.Te case AST.Fun: res = AST.MakerFun( nf.GetP(), + nf.GetTyArgs(), ApplySubstitutionOnTermList(old_symbol, new_symbol, nf.GetArgs()), ) } return res } -func applySubstitutionOnType(old_type, new_type, t AST.TypeApp) AST.TypeApp { - if tv, isTv := t.(AST.TypeVar); isTv { - if tv.Instantiated() && tv.Equals(old_type) { - return new_type - } - } - return t -} - /* Apply substitutions on a list of terms */ func ApplySubstitutionsOnTermList( s Unif.Substitutions, @@ -276,6 +268,7 @@ func ApplySubstitutionOnFormula(old_symbol AST.Meta, new_symbol AST.Term, f AST. res = AST.MakePred( nf.GetIndex(), nf.GetID(), + nf.GetTyArgs(), ApplySubstitutionOnTermList(old_symbol, new_symbol, nf.GetArgs()), ) case AST.Not: diff --git a/src/Engine/pretyper.go b/src/Engine/pretyper.go index 86c8d69e..1a1b82c6 100644 --- a/src/Engine/pretyper.go +++ b/src/Engine/pretyper.go @@ -82,10 +82,17 @@ func lookupInContext(con Context, name string) Lib.Option[Parser.PType] { return Lib.MkNone[Parser.PType]() } -func isTType(pty Parser.PType) bool { +func isTyConstr(pty Parser.PType) bool { switch ty := pty.(type) { case Parser.PTypeFun: return ty.Symbol() == "$tType" + case Parser.PTypeBin: + switch ty.Operator() { + case Parser.PTypeMap: + return isTyConstr(ty.Right()) + } + case Parser.PTypeQuant: + return isTyConstr(ty.Ty()) } return false } @@ -96,7 +103,7 @@ func splitTypes( actualTys := Lib.NewList[Parser.PType]() others := Lib.NewList[Parser.PTerm]() for _, ty := range tys { - if isTType(ty.Snd) { + if isTyConstr(ty.Snd) { actualTys.Append(parserTermToType(ty.Fst)) } else { others.Append(ty.Fst) @@ -136,17 +143,11 @@ func parserTermToType(pterm Parser.PTerm) Parser.PType { return nil } -func splitTypeVars( - tys []Lib.Pair[string, Parser.PAtomicType], -) ([]AST.TypeVar, []AST.Var) { - tyvars := []AST.TypeVar{} - others := []AST.Var{} - for _, ty := range tys { - if isTType(ty.Snd.(Parser.PType)) { - tyvars = append(tyvars, AST.MkTypeVar(ty.Fst)) - } else { - others = append(others, AST.MakerVar(ty.Fst)) - } +func pretypeVars(vars []Lib.Pair[string, Parser.PAtomicType]) Lib.List[AST.TypedVar] { + res := Lib.MkList[AST.TypedVar](len(vars)) + for i, v := range vars { + ty := elaborateType(v.Snd.(Parser.PType), v.Snd.(Parser.PType), false) + res.Upd(i, AST.MakerTypedVar(v.Fst, ty)) } - return tyvars, others + return res } diff --git a/src/Engine/syntax-translation.go b/src/Engine/syntax-translation.go index 9ad5a737..92b258d8 100644 --- a/src/Engine/syntax-translation.go +++ b/src/Engine/syntax-translation.go @@ -38,11 +38,13 @@ package Engine import ( "fmt" + "github.com/GoelandProver/Goeland/AST" "github.com/GoelandProver/Goeland/Core" "github.com/GoelandProver/Goeland/Glob" "github.com/GoelandProver/Goeland/Lib" "github.com/GoelandProver/Goeland/Parser" + "github.com/GoelandProver/Goeland/Typing" ) type Context []Lib.Pair[string, Parser.PType] @@ -50,31 +52,35 @@ type Context []Lib.Pair[string, Parser.PType] var elab_label string = "Elab" var parsing_label string = "Parsing" -func ToInternalSyntax(parser_statements []Parser.PStatement) []Core.Statement { - statements := []Core.Statement{} +func ToInternalSyntax(parser_statements []Parser.PStatement) (statements []Core.Statement, is_typed bool) { + is_typed = false con := Context{} for _, statement := range parser_statements { - newCon, stmt := elaborateParsingStatement(con, statement) + new_con, stmt, is_typed_stmt := elaborateParsingStatement(con, statement) statements = append(statements, stmt) - con = newCon + con = new_con + is_typed = is_typed || is_typed_stmt } - return statements + return statements, is_typed } func elaborateParsingStatement( con Context, statement Parser.PStatement, -) (Context, Core.Statement) { +) (Context, Core.Statement, bool) { statement_role := elaborateRole(statement.Role(), statement) + is_typed := false var core_statement Core.Statement switch f := statement.Form().(type) { case Lib.Some[Parser.PForm]: + form, is_typed_form := elaborateParsingForm(con, f.Val) core_statement = Core.MakeFormStatement( statement.Name(), statement_role, - elaborateParsingForm(con, f.Val), + form, ) + is_typed = is_typed || is_typed_form case Lib.None[Parser.PForm]: switch ty := statement.TypedConst().(type) { @@ -86,6 +92,7 @@ func elaborateParsingStatement( statement_role, elaborateParsingType(ty.Val), ) + is_typed = true case Lib.None[Lib.Pair[string, Parser.PType]]: if statement.Role() != Parser.Include { @@ -96,7 +103,7 @@ func elaborateParsingStatement( } } } - return con, core_statement + return con, core_statement, is_typed } func elaborateRole(parsing_role Parser.PFormulaRole, stmt Parser.PStatement) Core.FormulaRole { @@ -123,13 +130,13 @@ func elaborateRole(parsing_role Parser.PFormulaRole, stmt Parser.PStatement) Cor return Core.Unknown } -func elaborateParsingForm(con Context, f Parser.PForm) AST.Form { +func elaborateParsingForm(con Context, f Parser.PForm) (AST.Form, bool) { return elaborateForm(con, f, f) } // The [source_form] argument is here for error printing purposes. -func elaborateForm(con Context, f, source_form Parser.PForm) AST.Form { - aux := func(t Parser.PTerm) AST.Term { +func elaborateForm(con Context, f, source_form Parser.PForm) (AST.Form, bool) { + aux := func(t Parser.PTerm) (AST.Term, bool) { return elaborateParsingTerm(con, t) } @@ -138,23 +145,38 @@ func elaborateForm(con Context, f, source_form Parser.PForm) AST.Form { case Parser.PConst: switch pform.PConstant { case Parser.PTop: - return AST.MakerTop() + return AST.MakerTop(), false case Parser.PBot: - return AST.MakerBot() + return AST.MakerBot(), false } case Parser.PPred: typed_arguments := pretype(con, pform.Args()) - _, real_args := splitTypes(typed_arguments) + typed_args, term_args := splitTypes(typed_arguments) + args := Lib.MkList[AST.Term](term_args.Len()) + is_typed := false + + for i, trm := range term_args.GetSlice() { + arg, b := aux(trm) + is_typed = is_typed || b + args.Upd(i, arg) + } + return AST.MakerPred( AST.MakerId(pform.Symbol()), - Lib.ListMap(real_args, aux), - ) + Lib.ListMap( + typed_args, + func(pty Parser.PType) AST.Ty { + return elaborateType(pty, pty, false) + }), + args, + ), is_typed || !typed_args.Empty() case Parser.PUnary: switch pform.PUnaryOp { case Parser.PUnaryNeg: - return AST.MakerNot(elaborateForm(con, pform.PForm, source_form)) + nf, b := elaborateForm(con, pform.PForm, source_form) + return AST.MakerNot(nf), b } case Parser.PBin: @@ -164,19 +186,17 @@ func elaborateForm(con Context, f, source_form Parser.PForm) AST.Form { case Parser.PBinaryAnd: return maybeFlattenAnd(con, pform, source_form) case Parser.PBinaryImp: - return AST.MakerImp( - elaborateForm(con, pform.Left(), source_form), - elaborateForm(con, pform.Right(), source_form), - ) + lft, b1 := elaborateForm(con, pform.Left(), source_form) + rgt, b2 := elaborateForm(con, pform.Right(), source_form) + return AST.MakerImp(lft, rgt), b1 || b2 case Parser.PBinaryEqu: - return AST.MakerEqu( - elaborateForm(con, pform.Left(), source_form), - elaborateForm(con, pform.Right(), source_form), - ) + lft, b1 := elaborateForm(con, pform.Left(), source_form) + rgt, b2 := elaborateForm(con, pform.Right(), source_form) + return AST.MakerEqu(lft, rgt), b1 || b2 } case Parser.PQuant: - type_vars, vars := splitTypeVars(pform.Vars()) + vars := pretypeVars(pform.Vars()) switch pform.PQuantifier { case Parser.PQuantAll: actualVars := Lib.ListMap( @@ -185,13 +205,13 @@ func elaborateForm(con Context, f, source_form Parser.PForm) AST.Form { return Lib.MkPair(p.Fst, p.Snd.(Parser.PType)) }, ) - form := elaborateForm(append(con, actualVars.GetSlice()...), pform.PForm, source_form) - if len(vars) != 0 { + form, b := elaborateForm(append(con, actualVars.GetSlice()...), pform.PForm, source_form) + if !vars.Empty() { form = AST.MakerAll(vars, form) } - return form + return form, b case Parser.PQuantEx: - if len(type_vars) != 0 { + if vars.Any(func(v AST.TypedVar) bool { return AST.IsTType(v.GetTy()) }) { Glob.Anomaly( elab_label, "Found existentially quantified types when parsing "+source_form.ToString(), @@ -203,21 +223,21 @@ func elaborateForm(con Context, f, source_form Parser.PForm) AST.Form { return Lib.MkPair(p.Fst, p.Snd.(Parser.PType)) }, ) - form := elaborateForm(append(con, actualVars.GetSlice()...), pform.PForm, source_form) - if len(vars) != 0 { - return AST.MakerEx(vars, form) + form, b := elaborateForm(append(con, actualVars.GetSlice()...), pform.PForm, source_form) + if !vars.Empty() { + form = AST.MakerEx(vars, form) } - return form + return form, b } } Glob.Anomaly( elab_label, "Parsed formula "+source_form.ToString()+" does not correspond to any internal formula", ) - return nil + return nil, false } -func maybeFlattenOr(con Context, f Parser.PBin, source_form Parser.PForm) AST.Form { +func maybeFlattenOr(con Context, f Parser.PBin, source_form Parser.PForm) (AST.Form, bool) { return maybeFlattenBin( con, f, source_form, func(ls Lib.List[AST.Form]) AST.Form { return AST.MakerOr(ls) }, @@ -225,7 +245,7 @@ func maybeFlattenOr(con Context, f Parser.PBin, source_form Parser.PForm) AST.Fo ) } -func maybeFlattenAnd(con Context, f Parser.PBin, source_form Parser.PForm) AST.Form { +func maybeFlattenAnd(con Context, f Parser.PBin, source_form Parser.PForm) (AST.Form, bool) { return maybeFlattenBin( con, f, source_form, func(ls Lib.List[AST.Form]) AST.Form { return AST.MakerAnd(ls) }, @@ -239,23 +259,22 @@ func maybeFlattenBin( source_form Parser.PForm, maker Lib.Func[Lib.List[AST.Form], AST.Form], op Parser.PBinOp, -) AST.Form { +) (AST.Form, bool) { if !Glob.Flatten() { - return maker( - Lib.MkListV( - elaborateForm(con, f.Left(), source_form), - elaborateForm(con, f.Right(), source_form), - )) + lft, b1 := elaborateForm(con, f.Left(), source_form) + rgt, b2 := elaborateForm(con, f.Right(), source_form) + return maker(Lib.MkListV(lft, rgt)), b1 || b2 } subforms := flatten(f, op) - forms := Lib.MkListV( - Lib.ListMap( - subforms, - func(f Parser.PForm) AST.Form { return elaborateForm(con, f, source_form) }, - ).GetSlice()..., - ) - return maker(forms) + is_typed := false + real_subforms := Lib.MkList[AST.Form](subforms.Len()) + for i, subform := range subforms.GetSlice() { + real_subform, b := elaborateForm(con, subform, source_form) + real_subforms.Upd(i, real_subform) + is_typed = is_typed || b + } + return maker(real_subforms), is_typed } func flatten(f Parser.PForm, op Parser.PBinOp) Lib.List[Parser.PForm] { @@ -270,171 +289,132 @@ func flatten(f Parser.PForm, op Parser.PBinOp) Lib.List[Parser.PForm] { return Lib.MkListV(f) } -func elaborateParsingTerm(con Context, t Parser.PTerm) AST.Term { +func elaborateParsingTerm(con Context, t Parser.PTerm) (AST.Term, bool) { return elaborateTerm(con, t, t) } // The argument [source_term] is here for error printing purposes. -func elaborateTerm(con Context, t, source_term Parser.PTerm) AST.Term { - aux := func(t Parser.PTerm) AST.Term { +func elaborateTerm(con Context, t, source_term Parser.PTerm) (AST.Term, bool) { + aux := func(t Parser.PTerm) (AST.Term, bool) { return elaborateTerm(con, t, source_term) } - fail := func(ty AST.TypeScheme) { - Glob.Fatal( - parsing_label, - fmt.Sprintf( - "Non-atomic type found when pretyping %s: got %s", - t.ToString(), - ty.ToString(), - ), - ) - } - switch pterm := t.(type) { case Parser.PVar: - ty := lookupInContext(con, pterm.Name()) - switch t := ty.(type) { - case Lib.Some[Parser.PType]: - if isTType(t.Val) { - Glob.Anomaly( - elab_label, - fmt.Sprintf( - "Trying to transform the type variable %s into an internal term in %s", - pterm.Name(), - source_term.ToString(), - ), - ) - } - - ty := elaborateType(t.Val, t.Val) - if _, ok := ty.(AST.TypeApp); !ok { - fail(ty) - } - // FIXME: get some error function over here - return AST.MakerVar(pterm.Name()) - } + return AST.MakerVar(pterm.Name()), false case Parser.PFun: typed_arguments := pretype(con, pterm.Args()) - _, real_args := splitTypes(typed_arguments) + ty_args, trm_args := splitTypes(typed_arguments) + args := Lib.MkList[AST.Term](trm_args.Len()) + is_typed := false + + for i, trm := range trm_args.GetSlice() { + arg, b := aux(trm) + is_typed = is_typed || b + args.Upd(i, arg) + } + fun := AST.MakerFun( AST.MakerId(pterm.Symbol()), - Lib.ListMap(real_args, aux), + Lib.ListMap( + ty_args, + func(pty Parser.PType) AST.Ty { + return elaborateType(pty, pty, false) + }), + args, ) switch oty := pterm.DefinedType().(type) { case Lib.Some[Parser.PTypeFun]: - ty := elaborateType(oty.Val, oty.Val).(AST.TypeApp) - AST.SaveConstant(pterm.Symbol(), ty) + ty := elaborateType(oty.Val, oty.Val, false) + Typing.AddToGlobalEnv(pterm.Symbol(), ty) } - return fun + return fun, is_typed || !ty_args.Empty() } Glob.Anomaly( elab_label, "Parsed term "+source_term.ToString()+" does not correspond to any internal term", ) - return nil + return nil, false } func elaborateParsingType(pty Lib.Pair[string, Parser.PType]) Core.TFFAtomTyping { return Core.TFFAtomTyping{ Literal: AST.MakerId(pty.Fst), - Ts: elaborateType(pty.Snd, pty.Snd), + Ty: elaborateType(pty.Snd, pty.Snd, true), } } // The [source_type] argument is here for error printing. -func elaborateType(pty, source_type Parser.PType) AST.TypeScheme { - aux := func(pty Parser.PType) AST.TypeScheme { - return elaborateType(pty, source_type) +func elaborateType(pty, source_type Parser.PType, from_top_level bool) AST.Ty { + aux := func(pty Parser.PType) AST.Ty { + return elaborateType(pty, source_type, from_top_level) } switch ty := pty.(type) { case Parser.PTypeVar: - return AST.MkTypeVar(ty.Name()) - - case Parser.PTypeFun: - if len(ty.Args()) == 0 { - return AST.MkTypeHint(ty.Symbol()) + if from_top_level { + return AST.MkTyVar(ty.Name()) } else { - args := Lib.MkListV(ty.Args()...) - actualArgs := Lib.ListMap( - args, - func(atom Parser.PAtomicType) Parser.PType { return atom.(Parser.PType) }, - ) - elaboratedArgs := Lib.ListMap(actualArgs, aux) - convertedArgs := Lib.ListMap( - elaboratedArgs, - func(ty AST.TypeScheme) AST.TypeApp { return ty.(AST.TypeApp) }, - ) - // FIXME: this is __bad__ - params := []AST.TypeApp{} - for range convertedArgs.GetSlice() { - params = append(params, nil) - } - // FIXME: shouldn't this be internalized when making a new parameterized type - // instead of having to save it before? - AST.SaveParamereterizedType(ty.Symbol(), params) - return AST.MkParameterizedType( - ty.Symbol(), - convertedArgs.GetSlice(), - ) + return AST.MakerTyBV(ty.Name()) } + case Parser.PTypeFun: + args := Lib.MkListV(ty.Args()...) + actualArgs := Lib.ListMap( + args, + func(atom Parser.PAtomicType) Parser.PType { return atom.(Parser.PType) }, + ) + elaboratedArgs := Lib.ListMap(actualArgs, aux) + return AST.MkTyConstr(ty.Symbol(), elaboratedArgs) case Parser.PTypeBin: - new_left := elaborateType(ty.Left(), source_type) - new_right := elaborateType(ty.Right(), source_type) - - fail := func(cse string) { + fail_if_forbidden := func(ty Parser.PType) { Glob.Fatal( parsing_label, fmt.Sprintf( - "Non-atomic type found under the %s type %s in %s", - cse, + "Non-atomic type (%s) found under the type %s", ty.ToString(), source_type.ToString(), ), ) } + fail_if_forbidden(ty.Left()) + fail_if_forbidden(ty.Right()) + + new_left := elaborateType(ty.Left(), source_type, from_top_level) + new_right := elaborateType(ty.Right(), source_type, from_top_level) + switch ty.Operator() { case Parser.PTypeProd: - if !Glob.Is[AST.TypeApp](new_left) { - fail("map") - } - if !Glob.Is[AST.TypeApp](new_right) { - fail("map") - } - left_list := flattenProd(new_left.(AST.TypeApp)) - right_list := flattenProd(new_right.(AST.TypeApp)) - return AST.MkTypeCross(append(left_list, right_list...)...) + left_list := flattenProd(new_left) + right_list := flattenProd(new_right) + return AST.MkTyProd(Lib.MkListV(append(left_list, right_list...)...)) case Parser.PTypeMap: - if !Glob.Is[AST.TypeApp](new_left) { - fail("map") - } - if !Glob.Is[AST.TypeApp](new_right) { - fail("map") - } - return AST.MkTypeArrow( - elaborateType(ty.Left(), source_type).(AST.TypeApp), - elaborateType(ty.Right(), source_type).(AST.TypeApp), + return AST.MkTyFunc( + elaborateType(ty.Left(), source_type, from_top_level), + elaborateType(ty.Right(), source_type, from_top_level), ) } case Parser.PTypeQuant: switch ty.Quant() { case Parser.PTypeAll: - vars := Lib.MkListV(ty.Vars()...) - actualVars := Lib.ListMap( - vars, - func(p Lib.Pair[string, Parser.PAtomicType]) AST.TypeVar { - return AST.MkTypeVar(p.Fst) - }, - ) - return AST.MkQuantifiedType( - actualVars.GetSlice(), - elaborateType(ty.Ty(), source_type), - ) + var_names := Lib.MkList[string](len(ty.Vars())) + for i, v := range ty.Vars() { + var_names.Upd(i, v.Fst) + } + + underlying_type := elaborateType(ty.Ty(), source_type, from_top_level) + + if Glob.Is[AST.TyPi](underlying_type) { + Glob.Anomaly( + elab_label, + fmt.Sprintf("Found nested Pi-type in %s", source_type.ToString()), + ) + } + + return AST.MkTyPi(var_names, underlying_type) } } @@ -445,14 +425,14 @@ func elaborateType(pty, source_type Parser.PType) AST.TypeScheme { return nil } -func flattenProd(ty AST.TypeApp) []AST.TypeApp { +func flattenProd(ty AST.Ty) []AST.Ty { switch nty := ty.(type) { - case AST.TypeCross: - res := []AST.TypeApp{} - for _, uty := range nty.GetAllUnderlyingTypes() { + case AST.TyProd: + res := []AST.Ty{} + for _, uty := range nty.GetTys().GetSlice() { res = append(res, flattenProd(uty)...) } return res } - return []AST.TypeApp{ty} + return []AST.Ty{ty} } diff --git a/src/Lib/list.go b/src/Lib/list.go index f8460371..8aa9a881 100644 --- a/src/Lib/list.go +++ b/src/Lib/list.go @@ -92,13 +92,13 @@ func (l List[T]) Slice(st, ed int) List[T] { return List[T]{values: l.values[st:ed]} } -func ListEquals[T Comparable](ls0, ls1 List[T]) bool { +func (l List[T]) Equals(cmp Func2[T, T, bool], ls0, ls1 List[T]) bool { if ls0.Len() != ls1.Len() { return false } for i := range ls0.values { - if !ls0.At(i).Equals(ls1.At(i)) { + if !cmp(ls0.At(i), ls1.At(i)) { return false } } @@ -106,6 +106,11 @@ func ListEquals[T Comparable](ls0, ls1 List[T]) bool { return true } +func ListEquals[T Comparable](ls0, ls1 List[T]) bool { + cmp := func(x, y T) bool { return x.Equals(y) } + return ls0.Equals(cmp, ls0, ls1) +} + func (l List[T]) ToString( strFunc Func[T, string], sep, emptyValue string, @@ -216,6 +221,15 @@ func (l List[T]) Clear() { l.values = nil } +func (l List[T]) Any(pred Func[T, bool]) bool { + for _, el := range l.values { + if pred(el) { + return true + } + } + return false +} + func ToStrictlyOrderedList[T StrictlyOrdered](l List[T]) StrictlyOrderedList[T] { return StrictlyOrderedList[T]{values: l} } diff --git a/src/Lib/opt.go b/src/Lib/opt.go index e85b2a80..f78c6124 100644 --- a/src/Lib/opt.go +++ b/src/Lib/opt.go @@ -47,10 +47,10 @@ type None[A any] struct{} func (Some[A]) isOpt() {} func (None[A]) isOpt() {} -func OptBind[A, B any](u Option[A], f Func[A, B]) Option[B] { +func OptBind[A, B any](u Option[A], f Func[A, Option[B]]) Option[B] { switch x := u.(type) { case Some[A]: - return Some[B]{f(x.Val)} + return f(x.Val) case None[A]: return None[B]{} } diff --git a/src/Lib/sets.go b/src/Lib/sets.go index 3be6ea17..be86e7d4 100644 --- a/src/Lib/sets.go +++ b/src/Lib/sets.go @@ -47,6 +47,7 @@ package Lib import ( _ "fmt" + "slices" ) // ----------------------------------------------------------------------------- @@ -302,12 +303,7 @@ func (s0 Set[T]) Diff(s1 Set[T]) Set[T] { } func (s0 Set[T]) Disjoint(s1 Set[T]) bool { - for _, x := range s1.Elements().GetSlice() { - if s0.Contains(x) { - return false - } - } - return true + return !slices.ContainsFunc(s1.Elements().GetSlice(), s0.Contains) } func (s Set[T]) Cardinal() int { @@ -322,6 +318,16 @@ func (s Set[T]) Copy() Set[T] { return mkSet(nodeCpy(s.root)) } +func (s Set[T]) Filter(pred Func[T, bool]) Set[T] { + res := EmptySet[T]() + for _, x := range s.Elements().GetSlice() { + if pred(x) { + res.Add(x) + } + } + return res +} + // ----------------------------------------------------------------------------- // Internal; do not call. diff --git a/src/Mods/equality/bse/equality_problem_list.go b/src/Mods/equality/bse/equality_problem_list.go index 689b3ad8..a6b6479d 100644 --- a/src/Mods/equality/bse/equality_problem_list.go +++ b/src/Mods/equality/bse/equality_problem_list.go @@ -45,7 +45,9 @@ import ( "strings" "github.com/GoelandProver/Goeland/AST" + "github.com/GoelandProver/Goeland/Glob" "github.com/GoelandProver/Goeland/Lib" + "github.com/GoelandProver/Goeland/Typing" "github.com/GoelandProver/Goeland/Unif" ) @@ -208,12 +210,25 @@ func buildEqualityProblemMultiListFromPredList(pred AST.Pred, tn Unif.DataStruct predId := pred.GetID() metas := Lib.NewList[AST.Meta]() - for _, arg := range pred.GetArgs().GetSlice() { - metas = Lib.ListAdd(metas, AST.MakerMeta("METAEQ_"+arg.ToString(), -1)) + var ty AST.Ty + switch rty := Typing.QueryEnvInstance(predId.GetName(), pred.GetTyArgs()).(type) { + case Lib.Some[AST.Ty]: + ty = rty.Val + case Lib.None[AST.Ty]: + Glob.Anomaly( + "Equality.Build", + fmt.Sprintf("Type of predicate %s not found", pred.ToString()), + ) + } + tys := AST.GetArgsTy(ty) + + for i, arg := range pred.GetArgs().GetSlice() { + metas = Lib.ListAdd(metas, AST.MakerMeta("METAEQ_"+arg.ToString(), -1, tys.At(i))) } newTerm := AST.MakerPred( predId.Copy().(AST.Id), + pred.GetTyArgs(), AST.MetaListToTermList(metas), ) found, complementaryPredList := tn.Unify(newTerm) diff --git a/src/Mods/equality/bse/equality_types.go b/src/Mods/equality/bse/equality_types.go index 2c1deb91..775b1fae 100644 --- a/src/Mods/equality/bse/equality_types.go +++ b/src/Mods/equality/bse/equality_types.go @@ -120,16 +120,15 @@ func (equs Equalities) removeHalf() Equalities { /* Retrieve equalities from a datastructure */ func retrieveEqualities(dt Unif.DataStructure) Equalities { res := Equalities{} - MetaEQ1 := AST.MakerMeta("METAEQ1", -1) - MetaEQ2 := AST.MakerMeta("METAEQ2", -1) - // TODO: type this - tv := AST.MkTypeVar("EQ") - eq_pred := AST.MakerPred(AST.Id_eq, Lib.NewList[AST.Term]()) - tv.ShouldBeMeta(eq_pred.GetIndex()) - tv.Instantiate(1) + meta_ty := AST.MkTyMeta("META_TY_EQ") + MetaEQ1 := AST.MakerMeta("METAEQ1", -1, meta_ty) + MetaEQ2 := AST.MakerMeta("METAEQ2", -1, meta_ty) + + eq_pred := AST.MakerPred(AST.Id_eq, Lib.NewList[AST.Ty](), Lib.NewList[AST.Term]()) eq_pred = AST.MakePred( eq_pred.GetIndex(), AST.Id_eq, + Lib.MkListV[AST.Ty](meta_ty), Lib.MkListV[AST.Term](MetaEQ1, MetaEQ2), ) _, eq_list := dt.Unify(eq_pred) @@ -152,13 +151,15 @@ func retrieveEqualities(dt Unif.DataStructure) Equalities { /* Retrieve inequalities from a datastructure */ func retrieveInequalities(dt Unif.DataStructure) Inequalities { res := Inequalities{} - MetaNEQ1 := AST.MakerMeta("META_NEQ_1", -1) - MetaNEQ2 := AST.MakerMeta("META_NEQ_2", -1) + meta_ty := AST.MkTyMeta("META_TY_NEQ") + MetaNEQ1 := AST.MakerMeta("META_NEQ_1", -1, meta_ty) + MetaNEQ2 := AST.MakerMeta("META_NEQ_2", -1, meta_ty) - neq_pred := AST.MakerPred(AST.Id_eq, Lib.NewList[AST.Term]()) + neq_pred := AST.MakerPred(AST.Id_eq, Lib.NewList[AST.Ty](), Lib.NewList[AST.Term]()) neq_pred = AST.MakePred( neq_pred.GetIndex(), AST.Id_eq, + Lib.MkListV(meta_ty), Lib.MkListV[AST.Term](MetaNEQ1, MetaNEQ2), ) _, neq_list := dt.Unify(neq_pred) diff --git a/src/Mods/equality/sateq/subsgatherer.go b/src/Mods/equality/sateq/subsgatherer.go index 995193a4..41b30cff 100644 --- a/src/Mods/equality/sateq/subsgatherer.go +++ b/src/Mods/equality/sateq/subsgatherer.go @@ -83,7 +83,7 @@ func translate(toTranslate *eqClass, correspondence map[*eqClass]*termRecord) AS for i, s := range tr.args { args.Upd(i, translate(s, correspondence)) } - return AST.MakerFun(tr.symbolId, args) + return AST.MakerFun(tr.symbolId, tr.tyArgs, args) } } diff --git a/src/Mods/equality/sateq/termrep.go b/src/Mods/equality/sateq/termrep.go index 36c8a42a..244a5777 100644 --- a/src/Mods/equality/sateq/termrep.go +++ b/src/Mods/equality/sateq/termrep.go @@ -36,6 +36,7 @@ import ( "fmt" "github.com/GoelandProver/Goeland/AST" + "github.com/GoelandProver/Goeland/Lib" ) type Ordered[T any] interface { @@ -138,6 +139,7 @@ type termRecord struct { eqClass *eqClass meta *AST.Meta symbolId AST.Id + tyArgs Lib.List[AST.Ty] args []*eqClass } diff --git a/src/Mods/gs3/dependency.go b/src/Mods/gs3/dependency.go index 06a865d1..80209233 100644 --- a/src/Mods/gs3/dependency.go +++ b/src/Mods/gs3/dependency.go @@ -55,10 +55,10 @@ func manageGammasInstantiations(initialForm, resultForm AST.Form) AST.Term { //PrintInfo("FORMS", fmt.Sprintf("init: %s, result: %s", initialForm.ToString(), resultForm.ToString())) switch initialGamma := initialForm.(type) { case AST.All: - term = getResultTerm(initialGamma.GetVarList()[0], normalisedInitialForm, resultForm) + term = getResultTerm(initialGamma.GetVarList().At(0), normalisedInitialForm, resultForm) case AST.Not: if ex, ok := initialGamma.GetForm().(AST.Ex); ok { - term = getResultTerm(ex.GetVarList()[0], normalisedInitialForm, resultForm) + term = getResultTerm(ex.GetVarList().At(0), normalisedInitialForm, resultForm) } } //PrintInfo("TERM", fmt.Sprintf("Term: %s ; Result: %s", term.ToString(), resultForm.ToString())) @@ -74,10 +74,10 @@ func manageDeltasSkolemisations(initialForm, resultForm AST.Form) AST.Term { normalisedInitialForm := getNextFormula(initialForm.Copy()) switch initialDelta := initialForm.(type) { case AST.Ex: - term = getResultTerm(initialDelta.GetVarList()[0], normalisedInitialForm, resultForm) + term = getResultTerm(initialDelta.GetVarList().At(0), normalisedInitialForm, resultForm) case AST.Not: if all, ok := initialDelta.GetForm().(AST.All); ok { - term = getResultTerm(all.GetVarList()[0], normalisedInitialForm, resultForm) + term = getResultTerm(all.GetVarList().At(0), normalisedInitialForm, resultForm) } } return term @@ -91,14 +91,14 @@ func getNextFormula(form AST.Form) AST.Form { switch f := form.(type) { case AST.All: varList := f.GetVarList() - if len(varList) > 1 { - return AST.MakerAll(varList[1:], f.GetForm()) + if varList.Len() > 1 { + return AST.MakerAll(varList.Slice(1, varList.Len()), f.GetForm()) } return f.GetForm() case AST.Ex: varList := f.GetVarList() - if len(varList) > 1 { - return AST.MakerEx(varList[1:], f.GetForm()) + if varList.Len() > 1 { + return AST.MakerEx(varList.Slice(1, varList.Len()), f.GetForm()) } return f.GetForm() case AST.Not: @@ -107,17 +107,17 @@ func getNextFormula(form AST.Form) AST.Form { return form } -func getResultTerm(v AST.Var, bareForm, endForm AST.Form) AST.Term { +func getResultTerm(v AST.TypedVar, bareForm, endForm AST.Form) AST.Term { variablesOccurrences := getAllVariableOccurrences(v, bareForm) return getTermAt(endForm, variablesOccurrences) } // Explores the form and if a variable in the varlist is found, returns its occurrence. -func getAllVariableOccurrences(v AST.Var, form AST.Form) occurrences { +func getAllVariableOccurrences(v AST.TypedVar, form AST.Form) occurrences { return getVariableOccurrencesForm(v, form, occurrences{}, occurrence{}) } -func getVariableOccurrencesForm(v AST.Var, form AST.Form, currentOcc occurrences, path occurrence) occurrences { +func getVariableOccurrencesForm(v AST.TypedVar, form AST.Form, currentOcc occurrences, path occurrence) occurrences { workingPath := make(occurrence, len(path)) copy(workingPath, path) switch f := form.(type) { @@ -143,23 +143,23 @@ func getVariableOccurrencesForm(v AST.Var, form AST.Form, currentOcc occurrences return currentOcc } -func getUnaryOcc(v AST.Var, form AST.Form, currentOcc occurrences, path occurrence) occurrences { +func getUnaryOcc(v AST.TypedVar, form AST.Form, currentOcc occurrences, path occurrence) occurrences { return getVariableOccurrencesForm(v, form, currentOcc, append(path, 0)) } -func getNAryOcc(v AST.Var, currentOcc occurrences, path occurrence, fl Lib.List[AST.Form]) occurrences { +func getNAryOcc(v AST.TypedVar, currentOcc occurrences, path occurrence, fl Lib.List[AST.Form]) occurrences { for i, nf := range fl.GetSlice() { currentOcc = getVariableOccurrencesForm(v, nf, currentOcc, appcp(path, i)) } return currentOcc } -func getVariableOccurrencesTerm(v AST.Var, term AST.Term, currentOcc occurrences, path occurrence) occurrences { +func getVariableOccurrencesTerm(v AST.TypedVar, term AST.Term, currentOcc occurrences, path occurrence) occurrences { workingPath := make(occurrence, len(path)) copy(workingPath, path) switch t := term.(type) { case AST.Var: - if t.Equals(v) { + if t.Equals(v.ToBoundVar()) { currentOcc = append(currentOcc, workingPath) } case AST.Fun: diff --git a/src/Mods/gs3/proof.go b/src/Mods/gs3/proof.go index 551ff2c7..eebe9c80 100644 --- a/src/Mods/gs3/proof.go +++ b/src/Mods/gs3/proof.go @@ -647,20 +647,20 @@ func (gs GS3Proof) findInBetaHist(id int) int { func getAllFormulasDependantOn(term AST.Term, form AST.Form) Lib.List[AST.Form] { switch f := form.(type) { case AST.All: - return getSubformulas(term, f.GetVarList()[0], f.GetForm()) + return getSubformulas(term, f.GetVarList().At(0), f.GetForm()) case AST.Not: if ex, isEx := f.GetForm().(AST.Ex); isEx { - return getSubformulas(term, ex.GetVarList()[0], AST.MakerNot(f.GetForm())) + return getSubformulas(term, ex.GetVarList().At(0), AST.MakerNot(f.GetForm())) } } return Lib.NewList[AST.Form]() } -func getSubformulas(term AST.Term, v AST.Var, form AST.Form) Lib.List[AST.Form] { +func getSubformulas(term AST.Term, v AST.TypedVar, form AST.Form) Lib.List[AST.Form] { subforms := form.GetSubFormulasRecur() dependantSubforms := Lib.NewList[AST.Form]() for _, f := range subforms.GetSlice() { - f, res := f.ReplaceTermByTerm(v, term) + f, res := f.ReplaceTermByTerm(v.ToBoundVar(), term) if res { dependantSubforms.Append(f) } diff --git a/src/Mods/lambdapi/context.go b/src/Mods/lambdapi/context.go index ca42bd43..953fb17f 100644 --- a/src/Mods/lambdapi/context.go +++ b/src/Mods/lambdapi/context.go @@ -50,19 +50,19 @@ func makeContextIfNeeded(root AST.Form, metaList Lib.List[AST.Meta]) string { root = AST.MakerAnd(registeredAxioms) } - if AST.EmptyGlobalContext() { - resultString += strings.Join(getContextFromFormula(root), "\n") + "\n" + // if AST.EmptyGlobalContext() { + resultString += strings.Join(getContextFromFormula(root), "\n") + "\n" - if metaList.Len() > 0 { - resultString += contextualizeMetas(metaList) - } - } else { - resultString += getContextAsString(root) - - if metaList.Len() > 0 { - resultString += contextualizeMetas(metaList) - } + if metaList.Len() > 0 { + resultString += contextualizeMetas(metaList) } + // } else { + // resultString += getContextAsString(root) + + // if metaList.Len() > 0 { + // resultString += contextualizeMetas(metaList) + // } + // } return resultString } @@ -116,54 +116,55 @@ func getContextAsString(root AST.Form) string { } func GlobContextPairs() (types, arrows, others []Glob.Pair[string, string]) { - context := AST.GetGlobalContext() - for k, v := range context { - if k != "=" && k[0] != '$' { - switch typed := v[0].App.(type) { - case AST.TypeArrow: - primitives := typed.GetPrimitives() - typesStr := "" + return []Glob.Pair[string, string]{}, []Glob.Pair[string, string]{}, []Glob.Pair[string, string]{} + // context := AST.GetGlobalContext() + // for k, v := range context { + // if k != "=" && k[0] != '$' { + // switch typed := v[0].App.(type) { + // case AST.TypeArrow: + // primitives := typed.GetPrimitives() + // typesStr := "" - for i, prim := range primitives { - if i != len(primitives)-1 { - typesStr += "τ (" + prim.ToString() + ") → " - } else { - typesStr += prim.ToString() - } - } - arrows = append(arrows, Glob.MakePair(k, typesStr)) - case AST.QuantifiedType: - primitives := typed.GetPrimitives() - typesStr := "" - contextualized := []string{} + // for i, prim := range primitives { + // if i != len(primitives)-1 { + // typesStr += "τ (" + prim.ToString() + ") → " + // } else { + // typesStr += prim.ToString() + // } + // } + // arrows = append(arrows, Glob.MakePair(k, typesStr)) + // case AST.QuantifiedType: + // primitives := typed.GetPrimitives() + // typesStr := "" + // contextualized := []string{} - for i, prim := range primitives { - if i != len(primitives)-1 { - switch typedPrim := prim.(type) { - case AST.TypeVar: - str := AST.SimpleStringMappable(typedPrim.ToString()) - symbol := addToContext(&str) - typesStr += "τ (" + symbol + ") → " - contextualized = append(contextualized, symbol) - case AST.TypeHint: - typesStr += "τ (" + prim.ToString() + ") → " - } - } else { - typesStr += prim.ToString() - } - } - arrows = append(arrows, Glob.MakePair(k, fmt.Sprintf("Π (%s : Type), %s", strings.Join(contextualized, " : Type), ("), typesStr))) - case AST.TypeHint: - if k == typed.ToString() { - types = append(types, Glob.MakePair(k, "Type")) - } else { - others = append(others, Glob.MakePair(k, fmt.Sprintf("τ (%s)", typed.ToString()))) - } - } - } - } + // for i, prim := range primitives { + // if i != len(primitives)-1 { + // switch typedPrim := prim.(type) { + // case AST.TypeVar: + // str := AST.SimpleStringMappable(typedPrim.ToString()) + // symbol := addToContext(&str) + // typesStr += "τ (" + symbol + ") → " + // contextualized = append(contextualized, symbol) + // case AST.TypeHint: + // typesStr += "τ (" + prim.ToString() + ") → " + // } + // } else { + // typesStr += prim.ToString() + // } + // } + // arrows = append(arrows, Glob.MakePair(k, fmt.Sprintf("Π (%s : Type), %s", strings.Join(contextualized, " : Type), ("), typesStr))) + // case AST.TypeHint: + // if k == typed.ToString() { + // types = append(types, Glob.MakePair(k, "Type")) + // } else { + // others = append(others, Glob.MakePair(k, fmt.Sprintf("τ (%s)", typed.ToString()))) + // } + // } + // } + // } - return types, arrows, others + // return types, arrows, others } func contextPreamble() string { diff --git a/src/Mods/lambdapi/formDecorator.go b/src/Mods/lambdapi/formDecorator.go index 2ea14429..267effde 100644 --- a/src/Mods/lambdapi/formDecorator.go +++ b/src/Mods/lambdapi/formDecorator.go @@ -35,6 +35,7 @@ import ( "fmt" "github.com/GoelandProver/Goeland/AST" + "github.com/GoelandProver/Goeland/Lib" ) type DecoratedAll struct { @@ -54,12 +55,12 @@ func (da DecoratedAll) ToMappedStringSurround(mapping AST.MapString, displayType return QuantifierToMappedString(mapping[AST.AllQuant], da.GetVarList()) } -func QuantifierToMappedString(quant string, varList []AST.Var) string { - if len(varList) == 0 { +func QuantifierToMappedString(quant string, varList Lib.List[AST.TypedVar]) string { + if varList.Len() == 0 { return "%s" } else { - result := "(" + quant + " (" + toLambdaIntroString(varList[0], "") + ", %s))" - result = fmt.Sprintf(result, QuantifierToMappedString(quant, varList[1:])) + result := "(" + quant + " (" + toLambdaIntroString(varList.At(0), "") + ", %s))" + result = fmt.Sprintf(result, QuantifierToMappedString(quant, varList.Slice(1, varList.Len()))) return result } } diff --git a/src/Mods/lambdapi/proof.go b/src/Mods/lambdapi/proof.go index c0d16dbb..bdeeff51 100644 --- a/src/Mods/lambdapi/proof.go +++ b/src/Mods/lambdapi/proof.go @@ -144,7 +144,15 @@ func allRules(rule string, target AST.Form, composingForms Lib.List[AST.Form], n return result } -func allRulesQuantUniv(rule string, target AST.Form, composingForms Lib.List[AST.Form], nexts []*gs3.GS3Sequent, children []Lib.List[AST.Form], vars []AST.Var, termGen AST.Term) string { +func allRulesQuantUniv( + rule string, + target AST.Form, + composingForms Lib.List[AST.Form], + nexts []*gs3.GS3Sequent, + children []Lib.List[AST.Form], + vars Lib.List[AST.TypedVar], + termGen AST.Term, +) string { quant := "" typeStr := "" @@ -162,7 +170,7 @@ func allRulesQuantUniv(rule string, target AST.Form, composingForms Lib.List[AST result += "(%s, " + toCorrectString(composingForms.At(0)) + ")\n" varStrs := []string{} - for _, singleVar := range vars { + for _, singleVar := range vars.GetSlice() { varStrs = append(varStrs, toLambdaIntroString(singleVar, "")) } result = fmt.Sprintf(result, strings.Join(varStrs, ", "+quant+" ")) @@ -189,7 +197,15 @@ func getRecursionUnivStr(nexts []*gs3.GS3Sequent, children []Lib.List[AST.Form]) return result } -func allRulesQuantExist(rule string, target AST.Form, composingForms Lib.List[AST.Form], nexts []*gs3.GS3Sequent, children []Lib.List[AST.Form], vars []AST.Var, termGen AST.Term) string { +func allRulesQuantExist( + rule string, + target AST.Form, + composingForms Lib.List[AST.Form], + nexts []*gs3.GS3Sequent, + children []Lib.List[AST.Form], + vars Lib.List[AST.TypedVar], + termGen AST.Term, +) string { quant := "" typeStr := "" switch target.(type) { @@ -206,7 +222,7 @@ func allRulesQuantExist(rule string, target AST.Form, composingForms Lib.List[AS result += "(%s, " + toCorrectString(composingForms.At(0)) + ")\n" varStrs := []string{} - for _, singleVar := range vars { + for _, singleVar := range vars.GetSlice() { varStrs = append(varStrs, toLambdaIntroString(singleVar, "")) } result = fmt.Sprintf(result, strings.Join(varStrs, ", "+quant+" ")) @@ -283,7 +299,15 @@ func deltaEx(proof *gs3.GS3Sequent) string { formulaEx = form } - return allRulesQuantExist("GS3ex", proof.GetTargetForm(), proof.GetTargetForm().GetChildFormulas(), proof.Children(), proof.GetResultFormulasOfChildren(), formulaEx.GetVarList(), proof.TermGenerated()) + return allRulesQuantExist( + "GS3ex", + proof.GetTargetForm(), + proof.GetTargetForm().GetChildFormulas(), + proof.Children(), + proof.GetResultFormulasOfChildren(), + formulaEx.GetVarList(), + proof.TermGenerated(), + ) } func deltaNotAll(proof *gs3.GS3Sequent) string { @@ -304,7 +328,15 @@ func gammaAll(proof *gs3.GS3Sequent) string { formulaAll = form } - return allRulesQuantUniv("GS3all", proof.GetTargetForm(), proof.GetTargetForm().GetChildFormulas(), proof.Children(), proof.GetResultFormulasOfChildren(), formulaAll.GetVarList(), proof.TermGenerated()) + return allRulesQuantUniv( + "GS3all", + proof.GetTargetForm(), + proof.GetTargetForm().GetChildFormulas(), + proof.Children(), + proof.GetResultFormulasOfChildren(), + formulaAll.GetVarList(), + proof.TermGenerated(), + ) } func gammaNotEx(proof *gs3.GS3Sequent) string { diff --git a/src/Mods/rocq/context.go b/src/Mods/rocq/context.go index 1fe3360a..3ec82ed9 100644 --- a/src/Mods/rocq/context.go +++ b/src/Mods/rocq/context.go @@ -59,29 +59,29 @@ func makeContextIfNeeded(root AST.Form, metaList Lib.List[AST.Meta]) string { root = AST.MakerAnd(registeredAxioms) } - if AST.EmptyGlobalContext() { - resultingString += strings.Join(getContextFromFormula(root), "\n") + "\n" + // if AST.EmptyGlobalContext() { + resultingString += strings.Join(getContextFromFormula(root), "\n") + "\n" - if metaList.Len() > 0 { - resultingString += contextualizeMetas(metaList) - } - } else { - context := AST.GetGlobalContext() - for k, v := range context { - if typed, ok := v[0].App.(AST.TypeHint); ok { - if k[0] != '$' && k == typed.ToString() { - resultingString += "Parameter " + k + ": Type.\n" - - } - } - } - - resultingString += strings.Join(getContextFromFormula(root), "\n") + "\n" - - if metaList.Len() > 0 { - resultingString += contextualizeMetas(metaList) - } + if metaList.Len() > 0 { + resultingString += contextualizeMetas(metaList) } + // } else { + // context := AST.GetGlobalContext() + // for k, v := range context { + // if typed, ok := v[0].App.(AST.TypeHint); ok { + // if k[0] != '$' && k == typed.ToString() { + // resultingString += "Parameter " + k + ": Type.\n" + + // } + // } + // } + + // resultingString += strings.Join(getContextFromFormula(root), "\n") + "\n" + + // if metaList.Len() > 0 { + // resultingString += contextualizeMetas(metaList) + // } + // } return resultingString } diff --git a/src/Search/incremental/rules.go b/src/Search/incremental/rules.go index f6929cd4..73ac26a0 100644 --- a/src/Search/incremental/rules.go +++ b/src/Search/incremental/rules.go @@ -412,13 +412,13 @@ func (gne *GammaNotExists) getGeneratedMetas() Lib.List[AST.Meta] { return gne.generatedMetas } -func (gne *GammaNotExists) getVarList() []AST.Var { +func (gne *GammaNotExists) getVarList() Lib.List[AST.TypedVar] { if not, isNot := gne.formula.(AST.Not); isNot { if exists, isExists := not.GetForm().(AST.Ex); isExists { return exists.GetVarList() } } - return []AST.Var{} + return Lib.NewList[AST.TypedVar]() } type GammaForall struct { @@ -453,11 +453,11 @@ func (gf *GammaForall) getGeneratedMetas() Lib.List[AST.Meta] { return gf.generatedMetas } -func (gf *GammaForall) getVarList() []AST.Var { +func (gf *GammaForall) getVarList() Lib.List[AST.TypedVar] { if forall, isForall := gf.formula.(AST.All); isForall { return forall.GetVarList() } - return []AST.Var{} + return Lib.NewList[AST.TypedVar]() } type DeltaNotForall struct { diff --git a/src/Typing/apply_rules.go b/src/Typing/apply_rules.go deleted file mode 100644 index 828b7ae9..00000000 --- a/src/Typing/apply_rules.go +++ /dev/null @@ -1,189 +0,0 @@ -/** -* Copyright 2022 by the authors (see AUTHORS). -* -* Goéland is an automated theorem prover for first order logic. -* -* This software is governed by the CeCILL license under French law and -* abiding by the rules of distribution of free software. You can use, -* modify and/ or redistribute the software under the terms of the CeCILL -* license as circulated by CEA, CNRS and INRIA at the following URL -* "http://www.cecill.info". -* -* As a counterpart to the access to the source code and rights to copy, -* modify and redistribute granted by the license, users are provided only -* with a limited warranty and the software's author, the holder of the -* economic rights, and the successive licensors have only limited -* liability. -* -* In this respect, the user's attention is drawn to the risks associated -* with loading, using, modifying and/or developing or reproducing the -* software by the user in light of its specific status of free software, -* that may mean that it is complicated to manipulate, and that also -* therefore means that it is reserved for developers and experienced -* professionals having in-depth computer knowledge. Users are therefore -* encouraged to load and test the software's suitability as regards their -* requirements in conditions enabling the security of their systems and/or -* data to be ensured and, more generally, to use and operate it in the -* same conditions as regards security. -* -* The fact that you are presently reading this means that you have had -* knowledge of the CeCILL license and that you accept its terms. -**/ - -package Typing - -// import ( -// "fmt" - -// "github.com/GoelandProver/Goeland/AST" -// ) - -// /** -// * This file contains all the rules of the typing system. -// **/ - -// const ( -// formIsSet = iota -// termIsSet = iota -// typeIsSet = iota -// schemeIsSet = iota -// noConsequence = iota -// ) - -// /* Launch the rules depending on what's on the right side of the sequent. */ -// func applyRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { -// // Only one of the three should be set -// if !onlyOneConsequenceIsSet(state) { -// return Reconstruct{ -// result: false, -// err: fmt.Errorf("multiple elements on the right-side of the sequent. Cannot type this system"), -// } -// } - -// // The applicable rules depend on what is set: the form, the term, or the type ? -// switch whatIsSet(state.consequence) { -// case formIsSet: -// return applyFormRule(state, root, fatherChan) -// case termIsSet: -// return applyTermRule(state, root, fatherChan) -// case typeIsSet: -// return applyTypeRule(state, root, fatherChan) -// case schemeIsSet: -// return applySymRule(state, root, fatherChan) -// case noConsequence: -// return applyWFRule(state, root, fatherChan) -// } - -// return Reconstruct{result: true, err: nil} -// } - -// /* Applies one of the forms rule based on the type of the form. */ -// func applyFormRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { -// var rec Reconstruct -// switch (state.consequence.f).(type) { -// case AST.All, AST.AllType, AST.Ex: -// rec = applyQuantRule(state, root, fatherChan) -// case AST.And, AST.Or: -// rec = applyNAryRule(state, root, fatherChan) -// case AST.Imp, AST.Equ: -// rec = applyBinaryRule(state, root, fatherChan) -// case AST.Top, AST.Bot: -// rec = applyBotTopRule(state, root, fatherChan) -// case AST.Not: -// rec = applyNotRule(state, root, fatherChan) -// case AST.Pred: -// rec = applyAppRule(state, root, fatherChan) -// } -// return rec -// } - -// /* Applies one of the terms rule based on the type of the form. */ -// func applyTermRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { -// var rec Reconstruct -// switch (state.consequence.t).(type) { -// case AST.Fun: -// rec = applyAppRule(state, root, fatherChan) -// case AST.Var: -// rec = applyVarRule(state, root, fatherChan) -// // Metas shoudln't appear in the formula yet. -// // IDs are not a real Term. -// } -// return rec -// } - -// /* Applies one of the types rule based on the type of the form. */ -// func applyTypeRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { -// var rec Reconstruct -// switch type_ := (state.consequence.a).(type) { -// case AST.TypeHint: -// if type_.Equals(metaType) { -// rec = applyTypeWFRule(state, root, fatherChan) -// } else { -// rec = applyGlobalTypeVarRule(state, root, fatherChan) -// } -// case AST.TypeVar: -// rec = applyLocalTypeVarRule(state, root, fatherChan) -// case AST.TypeCross: -// // Apply composed rule: launch a child for each TypeHint of the composed type. -// rec = applyCrossRule(state, root, fatherChan) -// // There shouldn't be any TypeArrow: can not type a variable with it in first order. -// case AST.ParameterizedType: -// // Apply app rule, we only need to check if the name of the type exists. -// rec = applyAppTypeRule(state, root, fatherChan) -// } -// return rec -// } - -// /* Applies one of the WF rule based on the type of the form. */ -// func applyWFRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { -// if state.localContext.isEmpty() && state.globalContext.isEmpty() { -// root.appliedRule = "WF_0" -// return Reconstruct{result: true, err: nil} -// } -// if state.localContext.isEmpty() { -// root.appliedRule = "WF_1" -// return Reconstruct{result: true, err: nil} -// } - -// return applyWF2(state, root, fatherChan) -// } - -// /* Checks that at most one consequence of the sequent is set. */ -// func onlyOneConsequenceIsSet(state Sequent) bool { -// numberSet := 0 -// if state.consequence.f != nil { -// numberSet++ -// } -// if state.consequence.t != nil { -// numberSet++ -// } -// if state.consequence.a != nil { -// numberSet++ -// } -// if state.consequence.s != nil { -// numberSet++ -// } - -// return numberSet < 2 -// } - -// /** -// * Returns what is set in the consequence of the sequent. Either it's the form, -// * the term, or the type. -// * It doesn't check if multiple elements are set, it should be done before. -// **/ -// func whatIsSet(cons Consequence) int { -// var set int -// if cons.f != nil { -// set = formIsSet -// } else if cons.t != nil { -// set = termIsSet -// } else if cons.a != nil { -// set = typeIsSet -// } else if cons.s != nil { -// set = schemeIsSet -// } else { -// set = noConsequence -// } -// return set -// } diff --git a/src/Typing/contexts.go b/src/Typing/contexts.go deleted file mode 100644 index 1a78e62f..00000000 --- a/src/Typing/contexts.go +++ /dev/null @@ -1,341 +0,0 @@ -/** -* Copyright 2022 by the authors (see AUTHORS). -* -* Goéland is an automated theorem prover for first order logic. -* -* This software is governed by the CeCILL license under French law and -* abiding by the rules of distribution of free software. You can use, -* modify and/ or redistribute the software under the terms of the CeCILL -* license as circulated by CEA, CNRS and INRIA at the following URL -* "http://www.cecill.info". -* -* As a counterpart to the access to the source code and rights to copy, -* modify and redistribute granted by the license, users are provided only -* with a limited warranty and the software's author, the holder of the -* economic rights, and the successive licensors have only limited -* liability. -* -* In this respect, the user's attention is drawn to the risks associated -* with loading, using, modifying and/or developing or reproducing the -* software by the user in light of its specific status of free software, -* that may mean that it is complicated to manipulate, and that also -* therefore means that it is reserved for developers and experienced -* professionals having in-depth computer knowledge. Users are therefore -* encouraged to load and test the software's suitability as regards their -* requirements in conditions enabling the security of their systems and/or -* data to be ensured and, more generally, to use and operate it in the -* same conditions as regards security. -* -* The fact that you are presently reading this means that you have had -* knowledge of the CeCILL license and that you accept its terms. -**/ - -package Typing - -// import ( -// "fmt" - -// "github.com/GoelandProver/Goeland/AST" -// "github.com/GoelandProver/Goeland/Glob" -// "github.com/GoelandProver/Goeland/Lib" -// ) - -// /** -// * This file defines the global & local contexts types. -// **/ - -// /* Stores the local context */ -// type LocalContext struct { -// vars []AST.Var -// typeVars []AST.TypeVar -// } - -// /* LocalContext methods */ - -// /* Adds a var to a copy of the local context and returns it. */ -// func (lc LocalContext) addVar(var_ AST.Var) LocalContext { -// newLc := lc.copy() -// newLc.vars = append(newLc.vars, var_) -// return newLc -// } - -// /* Adds a type var to a copy of the local context and returns it. */ -// func (lc LocalContext) addTypeVar(var_ AST.TypeVar) LocalContext { -// newLc := lc.copy() -// newLc.typeVars = append(newLc.typeVars, var_) -// return newLc -// } - -// /* Copies a LocalContext. */ -// func (lc LocalContext) copy() LocalContext { -// newVars := make([]AST.Var, len(lc.vars)) -// newTypeVars := make([]AST.TypeVar, len(lc.typeVars)) -// copy(newVars, lc.vars) -// copy(newTypeVars, lc.typeVars) -// return LocalContext{vars: newVars, typeVars: newTypeVars} -// } - -// /* True if all the slices are cleared */ -// func (lc LocalContext) isEmpty() bool { -// return len(lc.vars)+len(lc.typeVars) == 0 -// } - -// /** -// * Copies the context and pops the first var (and returns it with the new local context). -// * It doesn't check if the size of the array is positive, it should be checked before. -// **/ -// func (lc LocalContext) popVar() (AST.Var, LocalContext) { -// newLc := lc.copy() -// newLc.vars = newLc.vars[1:] -// return lc.vars[0], newLc -// } - -// /** -// * Copies the context and pops the first type var (and returns it with the new local context). -// * It doesn't check if the size of the array is positive, it should be checked before. -// **/ -// func (lc LocalContext) popTypeVar() (AST.TypeVar, LocalContext) { -// newLc := lc.copy() -// newLc.typeVars = newLc.typeVars[1:] -// return lc.typeVars[0], newLc -// } - -// /* Stores the global context */ -// type GlobalContext struct { -// primitiveTypes []AST.TypeHint -// parameterizedTypes []string -// composedType map[string]AST.TypeCross -// simpleSchemes map[string][]AST.TypeScheme -// polymorphSchemes map[string][]AST.QuantifiedType -// } - -// /* Copies a GlobalContext into a new variable and returns it. */ -// func (gc GlobalContext) copy() GlobalContext { -// context := GlobalContext{ -// primitiveTypes: make([]AST.TypeHint, len(gc.primitiveTypes)), -// parameterizedTypes: make([]string, len(gc.parameterizedTypes)), -// simpleSchemes: make(map[string][]AST.TypeScheme), -// polymorphSchemes: make(map[string][]AST.QuantifiedType), -// } -// copy(context.primitiveTypes, gc.primitiveTypes) -// copy(context.parameterizedTypes, gc.parameterizedTypes) - -// for name, list := range gc.simpleSchemes { -// context.simpleSchemes[name] = make([]AST.TypeScheme, len(list)) -// copy(context.simpleSchemes[name], list) -// } - -// for name, list := range gc.polymorphSchemes { -// context.polymorphSchemes[name] = make([]AST.QuantifiedType, len(list)) -// copy(context.polymorphSchemes[name], list) -// } - -// return context -// } - -// /* Gets a simple / polymorphic type scheme from an ID, type variables, and terms */ -// func (gc GlobalContext) getTypeScheme( -// id AST.Id, -// vars []AST.TypeApp, -// terms Lib.List[AST.Term], -// ) (AST.TypeScheme, error) { -// args, err := getArgsTypes(gc, terms) -// if err != nil { -// return nil, err -// } - -// typeScheme, err := gc.getSimpleTypeScheme(id.GetName(), args) - -// if typeScheme == nil { -// typeScheme, err = gc.getPolymorphicTypeScheme( -// id.GetName(), -// len(vars), -// terms.Len(), -// ) -// // Instantiate type scheme with actual types -// if typeScheme != nil { -// typeScheme = Glob.To[AST.QuantifiedType](typeScheme).Instanciate(vars) -// } -// } - -// if err != nil { -// return nil, err -// } - -// return typeScheme, nil -// } - -// func flattenCross(ty AST.TypeApp) []AST.TypeApp { -// switch nty := ty.(type) { -// case AST.TypeCross: -// flattened := []AST.TypeApp{} -// for _, uty := range nty.GetAllUnderlyingTypes() { -// flattened = append(flattened, flattenCross(uty)...) -// } -// return []AST.TypeApp{AST.MkTypeCross(flattened...)} -// } -// return []AST.TypeApp{ty} -// } - -// /* Search for a TypeScheme with the name & the arguments type */ -// func (gc GlobalContext) getSimpleTypeScheme(name string, termsType AST.TypeApp) (AST.TypeScheme, error) { -// if termsType == nil { -// if typeScheme, found := gc.simpleSchemes[name]; found { -// return typeScheme[0], nil -// } else { -// return nil, fmt.Errorf("no constant function with the name %s in the global context", name) -// } -// } - -// termsType = flattenCross(termsType)[0] -// if typeSchemeList, found := gc.simpleSchemes[name]; found { -// for _, typeScheme := range typeSchemeList { -// if AST.GetInputType(typeScheme).Equals(Lib.ComparableList[AST.TypeApp]{termsType}) { -// return typeScheme, nil -// } -// } -// } -// return nil, fmt.Errorf("no predicate/function with the name %s in the global context and arguments of type %s", name, termsType.ToString()) -// } - -// /* Gets the polymorphic type scheme corresponding to the input. */ -// func (gc GlobalContext) getPolymorphicTypeScheme(name string, varsLen, termsLen int) (AST.TypeScheme, error) { -// if typeSchemeList, found := gc.polymorphSchemes[name]; found { -// for _, typeScheme := range typeSchemeList { -// if termsLen == typeScheme.Size()-1 && varsLen == typeScheme.QuantifiedVarsLen() { -// return typeScheme, nil -// } -// } -// } -// return nil, fmt.Errorf("no predicate/function with the name %s in the global context", name) -// } - -// /* Returns true if the TypeHint is found in the context */ -// func (gc GlobalContext) isTypeInContext(typeApp AST.TypeScheme) bool { -// for _, type_ := range gc.primitiveTypes { -// if type_.Equals(typeApp) { -// return true -// } -// } -// for _, type_ := range gc.composedType { -// if type_.Equals(typeApp) { -// return true -// } -// } -// return false -// } - -// /* Tests if there are no more TypeScheme stored (doesn't check for primitive types) */ -// func (gc GlobalContext) isEmpty() bool { -// result := true - -// for _, app := range gc.simpleSchemes { -// result = result && (len(app) == 0) -// } -// for _, app := range gc.polymorphSchemes { -// result = result && (len(app) == 0) -// } - -// return result -// } - -// /* Checks if the parameterized types contains the given name */ -// func (gc GlobalContext) parameterizedTypesContains(name string) bool { -// for _, parameterTypeName := range gc.parameterizedTypes { -// if name == parameterTypeName { -// return true -// } -// } -// return false -// } - -// /* Utils */ - -// /** -// * Creates a global context from all the types / type schemes recorded in the map of types. -// * Incrementally verifies if the context is well typed. -// * If not, an error is returned. -// **/ -// func createGlobalContext(context map[string][]AST.App) (GlobalContext, error) { -// globalContext := GlobalContext{ -// primitiveTypes: []AST.TypeHint{}, -// parameterizedTypes: []string{}, -// composedType: make(map[string]AST.TypeCross), -// simpleSchemes: make(map[string][]AST.TypeScheme), -// polymorphSchemes: make(map[string][]AST.QuantifiedType), -// } - -// // Fill first the primitive types -// for name, appList := range context { -// if len(appList) == 0 { -// globalContext.parameterizedTypes = append(globalContext.parameterizedTypes, name) -// } -// for _, app := range appList { -// if type_, isTypeHint := app.App.(AST.TypeHint); isTypeHint { -// if !AST.IsConstant(name) { -// globalContext.primitiveTypes = append(globalContext.primitiveTypes, type_) -// } -// } -// } -// } - -// for name, appList := range context { -// // Then, fill everything else -// for _, app := range appList { -// switch type_ := app.App.(type) { -// case AST.TypeHint: -// if AST.IsConstant(name) { -// globalContext.simpleSchemes[name] = append(globalContext.simpleSchemes[name], type_) -// } -// case AST.TypeCross: -// globalContext.composedType[name] = type_ -// case AST.TypeArrow: -// globalContext.simpleSchemes[name] = append(globalContext.simpleSchemes[name], type_) -// case AST.QuantifiedType: -// globalContext.polymorphSchemes[name] = append(globalContext.polymorphSchemes[name], type_) -// case AST.ParameterizedType: -// globalContext.simpleSchemes[name] = append(globalContext.simpleSchemes[name], type_) -// } -// if err := incrementalVerificationOfGlobalContext(globalContext.copy(), name, app.App); err != nil { -// return GlobalContext{}, err -// } -// } -// } - -// if !globalContextIsWellTyped { -// globalContextIsWellTyped = true -// } -// return globalContext, nil -// } - -// /** -// * Triggers rules to verify the global context while it's constructed. -// * It will avoid combinatorial explosion on global context well formedness verification. -// **/ -// func incrementalVerificationOfGlobalContext(globalContext GlobalContext, name string, app AST.TypeScheme) error { -// if globalContextIsWellTyped { -// return nil -// } - -// sequent := Sequent{ -// globalContext: globalContext, -// localContext: LocalContext{}, -// } -// rec := Reconstruct{err: nil} -// proofTree, chan_ := new(ProofTree), make(chan Reconstruct) - -// switch type_ := app.(type) { -// case AST.TypeCross: -// sequent.consequence = Consequence{a: type_} -// rec = applyCrossRule(sequent, proofTree, chan_) -// case AST.QuantifiedType, AST.TypeArrow: -// sequent.consequence = Consequence{s: app} -// rec = applySymRule(sequent, proofTree, chan_) -// case AST.TypeHint: -// if AST.IsConstant(name) { -// sequent.consequence = Consequence{a: type_} -// rec = applyGlobalTypeVarRule(sequent, proofTree, chan_) -// } -// } -// return rec.err -// } diff --git a/src/Typing/env-and-context.go b/src/Typing/env-and-context.go new file mode 100644 index 00000000..e544f6c4 --- /dev/null +++ b/src/Typing/env-and-context.go @@ -0,0 +1,136 @@ +/** +* Copyright 2022 by the authors (see AUTHORS). +* +* Goéland is an automated theorem prover for first order logic. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +**/ + +/** + * This file declares the environments of the typing process. + * In particular, it handles the global context and its accesses. +**/ + +package Typing + +import ( + "sync" + + "github.com/GoelandProver/Goeland/AST" + "github.com/GoelandProver/Goeland/Lib" +) + +// We define an ordered type of pairs of (string, Ty) in order to use sets. +type definedType struct { + name string + ty AST.Ty +} + +func (dty definedType) Less(oth any) bool { + if other, ok := oth.(definedType); ok { + return dty.name < other.name + } + return false +} + +func (dty definedType) Equals(oth any) bool { + if other, ok := oth.(definedType); ok { + return dty.name == other.name && dty.ty.Equals(other.ty) + } + return false +} + +// A context is a set of defined types +type Con struct { + defs Lib.Set[definedType] +} + +func emptyCon() Con { + return Con{Lib.EmptySet[definedType]()} +} + +func (con Con) Copy() Con { + return Con{con.defs.Copy()} +} + +func (con Con) add(name string, ty AST.Ty) Con { + return Con{con.defs.Add(definedType{name, ty})} +} + +func (con Con) contains(name string, ty AST.Ty) bool { + return con.defs.Contains(definedType{name, ty}) +} + +// We could use [Con] to do environments, but as we need to query by name it's faster to use a map. +type Env struct { + con map[string]AST.Ty + mut sync.Mutex +} + +func safeGlobalOperation[T any](f func() T) T { + global_env.mut.Lock() + res := f() + global_env.mut.Unlock() + return res +} + +func AddToGlobalEnv(name string, ty AST.Ty) { + safeGlobalOperation( + func() any { + global_env.con[name] = ty + return nil + }, + ) +} + +func unsafeQuery(name string) Lib.Option[AST.Ty] { + if ty, ok := global_env.con[name]; ok { + return Lib.MkSome(ty) + } + return Lib.MkNone[AST.Ty]() +} + +func QueryGlobalEnv(name string) Lib.Option[AST.Ty] { + return safeGlobalOperation(func() Lib.Option[AST.Ty] { return unsafeQuery(name) }) +} + +// Queries the environment and, if found, instantiate the definition with the given types. +// Guaranteed to not return a Pi-type. +func QueryEnvInstance(name string, instance Lib.List[AST.Ty]) Lib.Option[AST.Ty] { + return safeGlobalOperation( + func() Lib.Option[AST.Ty] { + // If [name] is safely found in the environment, instantiates it with the given vars + // Otherwise, return None + return Lib.OptBind( + unsafeQuery(name), + func(ty AST.Ty) Lib.Option[AST.Ty] { + return Lib.MkSome(AST.InstantiateTy(ty, instance)) + }, + ) + }, + ) +} diff --git a/src/Typing/form_rules.go b/src/Typing/form_rules.go deleted file mode 100644 index 772ec291..00000000 --- a/src/Typing/form_rules.go +++ /dev/null @@ -1,234 +0,0 @@ -/** -* Copyright 2022 by the authors (see AUTHORS). -* -* Goéland is an automated theorem prover for first order logic. -* -* This software is governed by the CeCILL license under French law and -* abiding by the rules of distribution of free software. You can use, -* modify and/ or redistribute the software under the terms of the CeCILL -* license as circulated by CEA, CNRS and INRIA at the following URL -* "http://www.cecill.info". -* -* As a counterpart to the access to the source code and rights to copy, -* modify and redistribute granted by the license, users are provided only -* with a limited warranty and the software's author, the holder of the -* economic rights, and the successive licensors have only limited -* liability. -* -* In this respect, the user's attention is drawn to the risks associated -* with loading, using, modifying and/or developing or reproducing the -* software by the user in light of its specific status of free software, -* that may mean that it is complicated to manipulate, and that also -* therefore means that it is reserved for developers and experienced -* professionals having in-depth computer knowledge. Users are therefore -* encouraged to load and test the software's suitability as regards their -* requirements in conditions enabling the security of their systems and/or -* data to be ensured and, more generally, to use and operate it in the -* same conditions as regards security. -* -* The fact that you are presently reading this means that you have had -* knowledge of the CeCILL license and that you accept its terms. -**/ - -package Typing - -// import ( -// "github.com/GoelandProver/Goeland/AST" -// "github.com/GoelandProver/Goeland/Lib" -// ) - -// /** -// * This file contains all the rules that the typing system can apply on a formula. -// **/ - -// /* Applies quantification rule and launches 2 goroutines waiting its children. */ -// func applyQuantRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { -// // Add rule to prooftree -// switch (state.consequence.f).(type) { -// case AST.All, AST.AllType: -// root.appliedRule = "∀" -// case AST.Ex: -// root.appliedRule = "∃" -// } - -// var newForm AST.Form -// var varTreated AST.Var -// var typeTreated AST.TypeVar - -// varInstantiated := false - -// switch f := (state.consequence.f).(type) { -// case AST.All, AST.Ex: -// varTreated, newForm = removeOneVar(state.consequence.f) -// varInstantiated = true -// case AST.AllType: -// v := f.GetVarList()[0] -// if len(f.GetVarList()) > 1 { -// typeTreated, newForm = v, AST.MakeAllType(f.GetIndex(), f.GetVarList()[1:], f.GetForm()) -// } else { -// typeTreated, newForm = v, f.GetForm() -// } -// } - -// // Create 2 children: -// // 1 - First one with the type of the quantified variable. It should be a TypeApp. -// // 2 - Second one with the quantified variable added in the local context. -// // => copy the local context and use the function to get the global context (copy or not). -// // The underlying form should be gotten to be properly typed. -// children := mkQuantChildren(state, varInstantiated, varTreated, typeTreated, newForm) - -// // Launch the children in a goroutine, and wait for it to close. -// // If one branch closes with an error, then the system is not well-typed. -// return reconstructForm(launchChildren(children, root, fatherChan), state.consequence.f) -// } - -// /* Applies OR or AND rule and launches n goroutines waiting its children */ -// func applyNAryRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { -// formList := Lib.NewList[AST.Form]() -// // Add rule to prooftree -// switch f := (state.consequence.f).(type) { -// case AST.And: -// root.appliedRule = "∧" -// formList = f.GetChildFormulas() -// case AST.Or: -// root.appliedRule = "∨" -// formList = f.GetChildFormulas() -// } - -// // Construct children with all the formulas -// children := []Sequent{} -// for _, form := range formList.GetSlice() { -// children = append(children, Sequent{ -// globalContext: state.globalContext, -// localContext: state.localContext.copy(), -// consequence: Consequence{f: form}, -// }) -// } - -// // Launch the children in a goroutine, and wait for it to close. -// // If one branch closes with an error, then the system is not well-typed. -// return reconstructForm(launchChildren(children, root, fatherChan), state.consequence.f) -// } - -// /* Applies => or <=> rule and launches 2 goroutines waiting its children */ -// func applyBinaryRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { -// var f1, f2 AST.Form -// // Add rule to prooftree -// switch f := (state.consequence.f).(type) { -// case AST.Imp: -// root.appliedRule = "⇒" -// f1, f2 = f.GetF1(), f.GetF2() -// case AST.Equ: -// root.appliedRule = "⇔" -// f1, f2 = f.GetF1(), f.GetF2() -// } - -// // Construct children with the 2 formulas -// children := []Sequent{ -// { -// globalContext: state.globalContext, -// localContext: state.localContext.copy(), -// consequence: Consequence{f: f1}, -// }, -// { -// globalContext: state.globalContext, -// localContext: state.localContext.copy(), -// consequence: Consequence{f: f2}, -// }, -// } - -// // Launch the children in a goroutine, and wait for it to close. -// // If one branch closes with an error, then the system is not well-typed. -// return reconstructForm(launchChildren(children, root, fatherChan), state.consequence.f) -// } - -// /* Applies BOT or TOP rule and does not create a new goroutine */ -// func applyBotTopRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { -// // Add rule to prooftree -// switch (state.consequence.f).(type) { -// case AST.Top: -// root.appliedRule = "⊤" -// case AST.Bot: -// root.appliedRule = "⊥" -// } - -// // Construct children with the contexts -// children := []Sequent{ -// { -// globalContext: state.globalContext, -// localContext: state.localContext.copy(), -// consequence: Consequence{}, -// }, -// } - -// // If the branch closes with an error, then the system is not well-typed. -// return reconstructForm(launchChildren(children, root, fatherChan), state.consequence.f) -// } - -// func applyNotRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { -// // Add rule to prooftree -// root.appliedRule = "¬" -// form := (state.consequence.f).(AST.Not).GetForm() - -// // Construct children with the contexts -// children := []Sequent{ -// { -// globalContext: state.globalContext, -// localContext: state.localContext.copy(), -// consequence: Consequence{f: form}, -// }, -// } - -// // If the branch closes with an error, then the system is not well-typed. -// return reconstructForm(launchChildren(children, root, fatherChan), state.consequence.f) -// } - -// /** -// * Removes the first variable of an exitential or universal form, and returns a -// * universal / existential form iff it still possesses other vars. -// * Otherwise, it returns the form gotten with GetForm(). -// **/ -// func removeOneVar(form AST.Form) (AST.Var, AST.Form) { -// // It's pretty much the same thing, but I don't have a clue on how to factorize this.. -// switch f := form.(type) { -// case AST.Ex: -// v := f.GetVarList()[0] -// if len(f.GetVarList()) > 1 { -// return v, AST.MakeEx(f.GetIndex(), f.GetVarList()[1:], f.GetForm()) -// } -// return v, f.GetForm() -// case AST.All: -// v := f.GetVarList()[0] -// if len(f.GetVarList()) > 1 { -// return v, AST.MakeAll(f.GetIndex(), f.GetVarList()[1:], f.GetForm()) -// } -// return v, f.GetForm() -// } -// return AST.Var{}, nil -// } - -// /* Makes the child treating the variable depending on which is set. */ -// func mkQuantChildren(state Sequent, varInstantiated bool, varTreated AST.Var, typeTreated AST.TypeVar, newForm AST.Form) []Sequent { -// var type_ AST.TypeApp -// var newLocalContext LocalContext -// if varInstantiated { -// type_ = varTreated.GetTypeApp() -// newLocalContext = state.localContext.addVar(varTreated) -// } else { -// type_ = metaType -// newLocalContext = state.localContext.addTypeVar(typeTreated) -// } - -// return []Sequent{ -// { -// globalContext: state.globalContext, -// localContext: state.localContext.copy(), -// consequence: Consequence{a: type_}, -// }, -// { -// globalContext: state.globalContext, -// localContext: newLocalContext, -// consequence: Consequence{f: newForm}, -// }, -// } -// } diff --git a/src/Typing/wf_rules.go b/src/Typing/init.go similarity index 61% rename from src/Typing/wf_rules.go rename to src/Typing/init.go index 186217dc..f145b260 100644 --- a/src/Typing/wf_rules.go +++ b/src/Typing/init.go @@ -30,38 +30,19 @@ * knowledge of the CeCILL license and that you accept its terms. **/ -package Typing +/** + * This file initializes the global environment (e.g., with TPTP primitives) +**/ -// /** -// * This file defines the WF rules. -// **/ +package Typing -// /* WF1 rule first empties the variables, and then the types. */ -// func applyWF2(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { -// root.appliedRule = "WF_2" +import ( + "github.com/GoelandProver/Goeland/AST" + "sync" +) -// // Try to empty vars first -// if len(state.localContext.vars) > 0 { -// // Launch child on the type of the first var -// var_, newLocalContext := state.localContext.popVar() -// child := []Sequent{ -// { -// localContext: newLocalContext, -// globalContext: state.globalContext, -// consequence: Consequence{a: var_.GetTypeApp()}, -// }, -// } -// return launchChildren(child, root, fatherChan) -// } +var global_env Env -// // Then, if vars is not empty, empty the types -// _, newLocalContext := state.localContext.popTypeVar() -// child := []Sequent{ -// { -// localContext: newLocalContext, -// globalContext: state.globalContext, -// consequence: Consequence{a: metaType}, -// }, -// } -// return launchChildren(child, root, fatherChan) -// } +func Init() { + global_env = Env{make(map[string]AST.Ty), sync.Mutex{}} +} diff --git a/src/Typing/launch_rules.go b/src/Typing/launch_rules.go deleted file mode 100644 index 7e78036b..00000000 --- a/src/Typing/launch_rules.go +++ /dev/null @@ -1,177 +0,0 @@ -/** -* Copyright 2022 by the authors (see AUTHORS). -* -* Goéland is an automated theorem prover for first order logic. -* -* This software is governed by the CeCILL license under French law and -* abiding by the rules of distribution of free software. You can use, -* modify and/ or redistribute the software under the terms of the CeCILL -* license as circulated by CEA, CNRS and INRIA at the following URL -* "http://www.cecill.info". -* -* As a counterpart to the access to the source code and rights to copy, -* modify and redistribute granted by the license, users are provided only -* with a limited warranty and the software's author, the holder of the -* economic rights, and the successive licensors have only limited -* liability. -* -* In this respect, the user's attention is drawn to the risks associated -* with loading, using, modifying and/or developing or reproducing the -* software by the user in light of its specific status of free software, -* that may mean that it is complicated to manipulate, and that also -* therefore means that it is reserved for developers and experienced -* professionals having in-depth computer knowledge. Users are therefore -* encouraged to load and test the software's suitability as regards their -* requirements in conditions enabling the security of their systems and/or -* data to be ensured and, more generally, to use and operate it in the -* same conditions as regards security. -* -* The fact that you are presently reading this means that you have had -* knowledge of the CeCILL license and that you accept its terms. -**/ - -package Typing - -// import ( -// "fmt" -// "reflect" - -// "github.com/GoelandProver/Goeland/AST" -// "github.com/GoelandProver/Goeland/Lib" -// ) - -// /** -// * This file manages everything related to parallelism / concurrency. -// **/ - -// type Reconstruct struct { -// result bool -// forms Lib.List[AST.Form] -// terms Lib.List[AST.Term] -// err error -// } - -// /* Launches the first instance of applyRule. Do this to launch the typing system. */ -// func launchRuleApplication(state Sequent, root *ProofTree) (AST.Form, error) { -// superFatherChan := make(chan Reconstruct) -// go tryApplyRule(state, root, superFatherChan) -// res := <-superFatherChan -// return treatReturns(res) -// } - -// /* Launches applyRule and manages the error return. */ -// func tryApplyRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) { -// select { -// case <-fatherChan: // Message from the father received: it can only be a kill order. -// default: -// // No kill order, it's still properly typed, let's apply the next rules. -// reconstruct := applyRule(state, root, fatherChan) -// select { -// case <-fatherChan: // Kill order received, it's finished anyway. -// case fatherChan <- reconstruct: // Otherwise, send result to father. -// } -// } -// } - -// /* Launch each sequent in a goroutine if sequent length > 1. */ -// func launchChildren(sequents []Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { -// if len(sequents) == 1 { -// // Do not launch another goroutine if the applied rule has only 1 child. -// return applyRule(sequents[0], root.addChildWith(sequents[0]), fatherChan) -// } else { -// // Create a channel for each child, and launch it in a goroutine. -// chanTab := make([](chan Reconstruct), len(sequents)) -// for i := range sequents { -// childChan := make(chan Reconstruct) -// chanTab[i] = childChan -// go tryApplyRule(sequents[i], root.addChildWith(sequents[i]), childChan) -// } -// // If a child dies with an error, stops the typesearch procedure. -// return selectSequents(chanTab, fatherChan) -// } -// } - -// /** -// * Waits for all the children to close. -// * If an error is received, stops the type-search of every children and sends an error -// * to the parent. -// **/ -// func selectSequents(chansTab [](chan Reconstruct), chanQuit chan Reconstruct) Reconstruct { -// // Instantiation -// cases := makeCases(chansTab, chanQuit) -// hasAnswered := make([]bool, len(chansTab)) // Everything to false -// remaining, indexQuit := len(chansTab), len(chansTab) -// var errorFound error = nil - -// forms := make([]AST.Form, len(chansTab)) -// terms := Lib.MkList[AST.Term](len(chansTab)) - -// // Wait for all children to finish. -// for remaining > 0 && errorFound == nil { -// index, value, _ := reflect.Select(cases) -// remaining-- -// if index == indexQuit { -// errorFound = fmt.Errorf("father detected an error") -// } else { -// res := value.Interface().(Reconstruct) -// hasAnswered[index] = true -// if !res.result { -// errorFound = res.err -// } else { -// // Once the child sends back to the father, it should only have one item. -// if res.forms.Len() == 1 { -// forms[index] = res.forms.At(0) -// } -// if res.terms.Len() == 1 { -// terms.Upd(index, res.terms.At(0)) -// } -// } -// } -// } - -// selectCleanup(errorFound, hasAnswered, chansTab) -// return Reconstruct{result: errorFound == nil, forms: Lib.MkListV(forms...), terms: terms, err: errorFound} -// } - -// /* Utils functions for selectSequents */ - -// /* Makes the array of cases from the channels */ -// func makeCases(chansTab [](chan Reconstruct), chanQuit chan Reconstruct) []reflect.SelectCase { -// cases := make([]reflect.SelectCase, len(chansTab)+1) -// // Children -// for i, chan_ := range chansTab { -// cases[i] = reflect.SelectCase{Dir: reflect.SelectRecv, Chan: reflect.ValueOf(chan_)} -// } -// // Father -// cases[len(chansTab)] = reflect.SelectCase{Dir: reflect.SelectRecv, Chan: reflect.ValueOf(chanQuit)} -// return cases -// } - -// /* If an error was found, kills all the children. */ -// func selectCleanup(errorFound error, hasAnswered []bool, chansTab [](chan Reconstruct)) { -// if errorFound != nil { -// for i, answered := range hasAnswered { -// if !answered { -// select { -// case <-chansTab[i]: // Filter out, he already responded -// case chansTab[i] <- Reconstruct{result: false, err: errorFound}: // Kill child -// } -// } -// } -// } -// } - -// /* Treats the different return types of the system. */ -// func treatReturns(res Reconstruct) (AST.Form, error) { -// if !res.result { -// return nil, res.err -// } else { -// if res.forms.Len() == 0 { -// return nil, res.err -// } -// if res.forms.Len() > 1 { -// return nil, fmt.Errorf("more than one formula is returned by the typing system") -// } -// return res.forms.At(0), res.err -// } -// } diff --git a/src/Typing/prooftree_dump.go b/src/Typing/prooftree_dump.go deleted file mode 100644 index 60a50da4..00000000 --- a/src/Typing/prooftree_dump.go +++ /dev/null @@ -1,151 +0,0 @@ -/** -* Copyright 2022 by the authors (see AUTHORS). -* -* Goéland is an automated theorem prover for first order logic. -* -* This software is governed by the CeCILL license under French law and -* abiding by the rules of distribution of free software. You can use, -* modify and/ or redistribute the software under the terms of the CeCILL -* license as circulated by CEA, CNRS and INRIA at the following URL -* "http://www.cecill.info". -* -* As a counterpart to the access to the source code and rights to copy, -* modify and redistribute granted by the license, users are provided only -* with a limited warranty and the software's author, the holder of the -* economic rights, and the successive licensors have only limited -* liability. -* -* In this respect, the user's attention is drawn to the risks associated -* with loading, using, modifying and/or developing or reproducing the -* software by the user in light of its specific status of free software, -* that may mean that it is complicated to manipulate, and that also -* therefore means that it is reserved for developers and experienced -* professionals having in-depth computer knowledge. Users are therefore -* encouraged to load and test the software's suitability as regards their -* requirements in conditions enabling the security of their systems and/or -* data to be ensured and, more generally, to use and operate it in the -* same conditions as regards security. -* -* The fact that you are presently reading this means that you have had -* knowledge of the CeCILL license and that you accept its terms. -**/ - -package Typing - -// import ( -// "encoding/json" -// "errors" -// "fmt" -// "os" -// "strings" - -// "github.com/GoelandProver/Goeland/AST" -// "github.com/GoelandProver/Goeland/Glob" -// ) - -// /** -// * This file contains the methods to dump a prooftree in a json. -// **/ - -// /* Dumps the prooftree in a json. */ -// func (root *ProofTree) DumpJson() error { -// // Dump folder should be a flag in the future -// dump := "../visualization/types/" -// // Create a new file -// i := 0 -// for fileExists(getFileName(dump, i)) { -// i++ -// } - -// f, err := os.OpenFile(getFileName(dump, i), os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) -// if err != nil { -// return err -// } -// json, err := root.dump() - -// if err != nil { -// return err -// } - -// _, err = f.WriteString(json) -// Glob.PrintInfo("DUMP", fmt.Sprintf("Dumped type proof in %s\n", f.Name())) -// return err -// } - -// /* Creates file if not exists, dump informations in it, and calls recursively on each child */ -// func (root *ProofTree) dump() (string, error) { -// varsString := []string{} -// var consequence string = "" -// var ts string -// if root.typeScheme != nil { -// ts = root.typeScheme.ToString() -// } - -// for _, var_ := range root.sequent.localContext.vars { -// varsString = append(varsString, var_.ToString()) -// } -// for _, var_ := range root.sequent.localContext.typeVars { -// varsString = append(varsString, fmt.Sprintf("%s: Type", var_.ToString())) -// } - -// switch whatIsSet(root.sequent.consequence) { -// case formIsSet: -// consequence = root.sequent.consequence.f.ToString() -// if root.typeScheme == nil { -// ts = root.sequent.consequence.f.GetType().ToString() -// } -// case termIsSet: -// consequence = root.sequent.consequence.t.ToString() -// if root.typeScheme == nil { -// if root.sequent.consequence.t.(AST.TypedTerm).GetTypeHint() == nil { -// ts = root.sequent.consequence.t.(AST.TypedTerm).GetTypeApp().ToString() -// } else { -// ts = root.sequent.consequence.t.(AST.TypedTerm).GetTypeHint().ToString() -// } -// } -// case typeIsSet: -// consequence = root.sequent.consequence.a.ToString() -// if root.typeScheme == nil { -// ts = "Type" -// } -// } - -// childrenProofs := []string{} - -// for _, child := range root.children { -// bytes, err := child.dump() -// if err != nil { -// return "", err -// } -// childrenProofs = append(childrenProofs, bytes) -// } - -// bytes, err := json.Marshal(&struct { -// LocalContext string `json:"localContext"` -// Consequence string `json:"consequence"` -// TypeScheme string `json:"typeScheme"` -// Rule string `json:"rule"` -// Children []string `json:"children"` -// }{ -// LocalContext: strings.Join(varsString, ", "), -// Consequence: consequence, -// TypeScheme: ts, -// Rule: root.appliedRule, -// Children: childrenProofs, -// }) - -// return strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(string(bytes), "\\", ""), "\"{", "{"), "}\"", "}"), err -// } - -// /* Utils */ - -// /* Checks if file exists at given path */ -// func fileExists(path string) bool { -// _, err := os.Stat(path) -// return !errors.Is(err, os.ErrNotExist) -// } - -// /* Create a formated file name */ -// func getFileName(folder string, i int) string { -// return fmt.Sprintf("%sproof_%d.json", folder, i) -// } diff --git a/src/Typing/rules.go b/src/Typing/rules.go index 2850fcc2..7b2f9768 100644 --- a/src/Typing/rules.go +++ b/src/Typing/rules.go @@ -30,207 +30,17 @@ * knowledge of the CeCILL license and that you accept its terms. **/ -package Typing - -// import ( -// "reflect" - -// "github.com/GoelandProver/Goeland/AST" -// "github.com/GoelandProver/Goeland/Glob" -// "github.com/GoelandProver/Goeland/Lib" -// ) - -// /** -// * This file contains the functions to create a typing proof tree. -// * It defines the TypingProofTree structure and all the rules to check if a -// * system is well-typed. -// **/ - -// /* Stores the consequence of the sequent */ -// type Consequence struct { -// f AST.Form -// t AST.Term -// a AST.TypeApp -// s AST.TypeScheme -// } - -// /* A Sequent is formed of a global context, local context, and a formula or a term to type */ -// type Sequent struct { -// globalContext GlobalContext -// localContext LocalContext -// consequence Consequence -// } - -// /* Makes a typing prooftree to output. */ -// type ProofTree struct { -// sequent Sequent -// appliedRule string -// typeScheme AST.TypeScheme -// children []*ProofTree -// } - -// /* ProofTree meta-type */ -// var metaType AST.TypeHint - -// /* ProofTree methods */ - -// /* Creates and adds a child to the prooftree and returns it. */ -// func (pt *ProofTree) addChildWith(sequent Sequent) *ProofTree { -// child := ProofTree{ -// sequent: sequent, -// children: []*ProofTree{}, -// } -// pt.children = append(pt.children, &child) -// return &child -// } - -// var globalContextIsWellTyped bool = false - -// /** -// * Tries to type form. -// * If not well-typed, will return an error. -// **/ -// func WellFormedVerification(form AST.Form, dump bool) error { -// // Instanciate meta type -// metaType = AST.MkTypeHint("$tType") - -// // Second pass to type variables & to give the typevars to functions and predicates -// form = SecondPass(form) - -// globalContext, err := createGlobalContext(AST.GetGlobalContext()) -// if err != nil { -// return err -// } - -// // Sequent creation -// state := Sequent{ -// globalContext: globalContext, -// localContext: LocalContext{vars: []AST.Var{}, typeVars: []AST.TypeVar{}}, -// consequence: Consequence{f: form}, -// } - -// // Prooftree creation -// root := ProofTree{ -// sequent: state, -// children: []*ProofTree{}, -// } - -// // Launch the typing system -// _, err = launchRuleApplication(state, &root) - -// // Dump prooftree in json if it's asked & there is no error -// if dump && err == nil { -// err = root.DumpJson() -// } - -// return err -// } - -// /* Reconstructs a Form depending on what the children has returned */ -// func reconstructForm(reconstruction Reconstruct, baseForm AST.Form) Reconstruct { -// if !reconstruction.result { -// return reconstruction -// } - -// var f AST.Form -// switch form := baseForm.(type) { -// case AST.All: -// f = AST.MakeAll(form.GetIndex(), form.GetVarList(), unquantify(reconstruction.forms.At(1), form)) -// case AST.AllType: -// f = AST.MakeAllType(form.GetIndex(), form.GetVarList(), unquantify(reconstruction.forms.At(1), form)) -// case AST.Ex: -// f = AST.MakeEx(form.GetIndex(), form.GetVarList(), unquantify(reconstruction.forms.At(1), form)) -// case AST.And: -// f = AST.MakeAnd(form.GetIndex(), reconstruction.forms) -// case AST.Or: -// f = AST.MakeOr(form.GetIndex(), reconstruction.forms) -// case AST.Imp: -// f = AST.MakeImp(form.GetIndex(), reconstruction.forms.At(0), reconstruction.forms.At(1)) -// case AST.Equ: -// f = AST.MakeEqu(form.GetIndex(), reconstruction.forms.At(0), reconstruction.forms.At(1)) -// case AST.Not: -// f = AST.MakeNot(form.GetIndex(), reconstruction.forms.At(0)) -// case AST.Pred: -// // The len(form.GetTypeVars()) first children launched are children for typevars. -// // So the len(form.GetTypeVars()) first children will return -// if reconstruction.terms.Len() > len(form.GetTypeVars()) { -// terms := Lib.MkListV(reconstruction.terms.Get( -// len(form.GetTypeVars()), -// reconstruction.terms.Len(), -// )...) -// f = AST.MakePred( -// form.GetIndex(), -// form.GetID(), -// terms, -// form.GetTypeVars(), -// form.GetType(), -// ) -// } else { -// f = AST.MakePred( -// form.GetIndex(), -// form.GetID(), -// Lib.NewList[AST.Term](), -// form.GetTypeVars(), -// form.GetType(), -// ) -// } -// case AST.Top, AST.Bot: -// f = baseForm -// } - -// return Reconstruct{result: true, forms: Lib.MkListV(f), err: nil} -// } - -// /* Reconstructs a Term depending on what the children has returned */ -// func reconstructTerm(reconstruction Reconstruct, baseTerm AST.Term) Reconstruct { -// if !reconstruction.result { -// return reconstruction -// } - -// // fun: reconstruct with children terms -// if Glob.Is[AST.Fun](baseTerm) { -// termFun := Glob.To[AST.Fun](baseTerm) -// var fun AST.Fun -// // The len(form.GetTypeVars()) first children launched are children for typevars. -// // So the len(form.GetTypeVars()) first children will return -// if reconstruction.terms.Len() > len(termFun.GetTypeVars()) { -// terms := Lib.MkListV(reconstruction.terms.Get( -// len(termFun.GetTypeVars()), -// reconstruction.terms.Len(), -// )...) -// fun = AST.MakerFun( -// termFun.GetID(), -// terms, -// termFun.GetTypeVars(), -// termFun.GetTypeHint(), -// ) -// } else { -// fun = AST.MakerFun( -// termFun.GetID(), -// Lib.NewList[AST.Term](), -// termFun.GetTypeVars(), -// termFun.GetTypeHint(), -// ) -// } -// return Reconstruct{result: true, terms: Lib.MkListV[AST.Term](fun), err: nil} -// } +/** + * This file is the entry point to perform typing of a formula. + * It implements all the rules. +**/ -// return Reconstruct{result: true, terms: Lib.MkListV(baseTerm), err: nil} -// } +package Typing -// /* Utils for reconstructions function */ +import ( + "github.com/GoelandProver/Goeland/AST" +) -// /* Removes all the quantifiers of form of the same type of quant. */ -// func unquantify(form AST.Form, quant AST.Form) AST.Form { -// for reflect.TypeOf(form) == reflect.TypeOf(quant) { -// switch quant.(type) { -// case AST.All: -// form = Glob.To[AST.All](form).GetForm() -// case AST.AllType: -// form = Glob.To[AST.AllType](form).GetForm() -// case AST.Ex: -// form = Glob.To[AST.Ex](form).GetForm() -// } -// } -// return form -// } +func TypeCheck(form AST.Form) bool { + return false +} diff --git a/src/Typing/term_rules.go b/src/Typing/term_rules.go deleted file mode 100644 index ced4119e..00000000 --- a/src/Typing/term_rules.go +++ /dev/null @@ -1,216 +0,0 @@ -/** -* Copyright 2022 by the authors (see AUTHORS). -* -* Goéland is an automated theorem prover for first order logic. -* -* This software is governed by the CeCILL license under French law and -* abiding by the rules of distribution of free software. You can use, -* modify and/ or redistribute the software under the terms of the CeCILL -* license as circulated by CEA, CNRS and INRIA at the following URL -* "http://www.cecill.info". -* -* As a counterpart to the access to the source code and rights to copy, -* modify and redistribute granted by the license, users are provided only -* with a limited warranty and the software's author, the holder of the -* economic rights, and the successive licensors have only limited -* liability. -* -* In this respect, the user's attention is drawn to the risks associated -* with loading, using, modifying and/or developing or reproducing the -* software by the user in light of its specific status of free software, -* that may mean that it is complicated to manipulate, and that also -* therefore means that it is reserved for developers and experienced -* professionals having in-depth computer knowledge. Users are therefore -* encouraged to load and test the software's suitability as regards their -* requirements in conditions enabling the security of their systems and/or -* data to be ensured and, more generally, to use and operate it in the -* same conditions as regards security. -* -* The fact that you are presently reading this means that you have had -* knowledge of the CeCILL license and that you accept its terms. -**/ - -package Typing - -// import ( -// "fmt" - -// "github.com/GoelandProver/Goeland/AST" -// "github.com/GoelandProver/Goeland/Glob" -// "github.com/GoelandProver/Goeland/Lib" -// ) - -// /** -// * This file contains the rules for typing terms, and also the App rule. -// * The App rule is used for predicates and functions. -// **/ - -// /* Applies the App rule for predicates or functions */ -// func applyAppRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { -// var index int -// var id AST.Id -// var terms Lib.List[AST.Term] -// var vars []AST.TypeApp - -// if whatIsSet(state.consequence) == formIsSet { -// index = (state.consequence.f).(AST.Pred).GetIndex() -// id = (state.consequence.f).(AST.Pred).GetID() -// terms = (state.consequence.f).(AST.Pred).GetArgs() -// vars = (state.consequence.f).(AST.Pred).GetTypeVars() -// } else { -// id = (state.consequence.t).(AST.Fun).GetID() -// terms = (state.consequence.t).(AST.Fun).GetArgs() -// vars = (state.consequence.t).(AST.Fun).GetTypeVars() -// } - -// root.appliedRule = "App" - -// // Search for the ID in the global context -// typeScheme, err := state.globalContext.getTypeScheme(id, vars, terms) -// if err != nil { -// return Reconstruct{ -// result: false, -// err: err, -// } -// } - -// // Affect new type scheme to the prooftree -// root.typeScheme = typeScheme -// primitives := typeScheme.GetPrimitives() - -// // Type predicate or function -// if whatIsSet(state.consequence) == formIsSet { -// fTyped := AST.MakePred(index, id, terms, vars, typeScheme) -// return reconstructForm(launchChildren( -// createAppChildren(state, vars, terms, primitives), -// root, -// fatherChan, -// ), fTyped) -// } else { -// fTyped := AST.MakerFun(id, terms, vars, typeScheme) -// return reconstructTerm(launchChildren(createAppChildren(state, vars, terms, primitives), root, fatherChan), fTyped) -// } -// } - -// /* Applies the Var rule for a term variable. */ -// func applyVarRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { -// // Add applied rule to the prooftree -// root.appliedRule = "Var" - -// // Find current variable in the local context -// if _, ok := getTermFromLocalContext(state.localContext, state.consequence.t); !ok { -// return Reconstruct{ -// result: false, -// err: fmt.Errorf("term %s not found in the local context", state.consequence.t.ToString()), -// } -// } - -// // No consequence: next rule is the WF rule. -// children := []Sequent{ -// { -// globalContext: state.globalContext, -// localContext: state.localContext.copy(), -// consequence: Consequence{}, -// }, -// } - -// return reconstructTerm(launchChildren(children, root, fatherChan), state.consequence.t) -// } - -// /* Utils functions */ - -// /** -// * Takes all the types of the terms and makes a cross product of everything -// **/ -// func getArgsTypes( -// context GlobalContext, -// terms Lib.List[AST.Term], -// ) (AST.TypeApp, error) { -// if terms.Len() == 0 { -// return nil, nil -// } - -// var types []AST.TypeApp - -// for _, term := range terms.GetSlice() { -// switch tmpTerm := term.(type) { -// case AST.Fun: -// typeScheme, err := context.getTypeScheme( -// tmpTerm.GetID(), -// tmpTerm.GetTypeVars(), -// tmpTerm.GetArgs(), -// ) -// if err != nil { -// return nil, err -// } -// if typeScheme == nil { -// return nil, fmt.Errorf("function %s not found in global context", tmpTerm.GetName()) -// } -// types = append(types, AST.GetOutType(typeScheme)) -// case AST.Var: -// // Variables can't be of type TypeScheme, so this line shouldn't fail. -// types = append(types, tmpTerm.GetTypeApp()) -// // There shouldn't be Metas yet. -// case AST.Meta: -// Glob.PrintDebug("GAT", Lib.MkLazy(func() string { return "Found a Meta while typing everything." })) -// // ID is filtered out -// } -// } - -// if len(types) == 1 { -// return types[0], nil -// } -// typeCross := AST.MkTypeCross(types[0], types[1]) -// for i := 2; i < len(types); i += 1 { -// typeCross = AST.MkTypeCross(typeCross, types[i]) -// } -// return typeCross, nil -// } - -// /* Creates children for app rule */ -// func createAppChildren( -// state Sequent, -// vars []AST.TypeApp, -// terms Lib.List[AST.Term], -// primitives []AST.TypeApp, -// ) []Sequent { -// children := []Sequent{} - -// // 1 for each type in the vars -// for _, var_ := range vars { -// children = append(children, Sequent{ -// globalContext: state.globalContext, -// localContext: state.localContext.copy(), -// consequence: Consequence{a: var_}, -// }) -// } - -// // 1 for each term -// for i, term := range terms.GetSlice() { -// switch t := term.(type) { -// case AST.Fun: -// term = AST.MakerFun(t.GetID(), t.GetArgs(), t.GetTypeVars(), primitives[i].(AST.TypeScheme)) -// case AST.Meta: -// term = AST.MakeMeta(t.GetIndex(), t.GetOccurence(), t.GetName(), t.GetFormula(), primitives[i]) -// case AST.Var: -// term = AST.MakeVar(t.GetIndex(), t.GetName(), primitives[i]) -// } -// children = append(children, Sequent{ -// globalContext: state.globalContext, -// localContext: state.localContext.copy(), -// consequence: Consequence{t: term}, -// }) -// } - -// return children -// } - -// /* Finds the given term in the local context, returns false if it couldn't */ -// func getTermFromLocalContext(localContext LocalContext, term AST.Term) (AST.Var, bool) { -// for _, var_ := range localContext.vars { -// if var_.Equals(term) { -// return var_, true -// } -// } -// return AST.Var{}, false -// } diff --git a/src/Typing/type.go b/src/Typing/type.go deleted file mode 100644 index 9d64162c..00000000 --- a/src/Typing/type.go +++ /dev/null @@ -1,190 +0,0 @@ -/** -* Copyright 2022 by the authors (see AUTHORS). -* -* Goéland is an automated theorem prover for first order logic. -* -* This software is governed by the CeCILL license under French law and -* abiding by the rules of distribution of free software. You can use, -* modify and/ or redistribute the software under the terms of the CeCILL -* license as circulated by CEA, CNRS and INRIA at the following URL -* "http://www.cecill.info". -* -* As a counterpart to the access to the source code and rights to copy, -* modify and redistribute granted by the license, users are provided only -* with a limited warranty and the software's author, the holder of the -* economic rights, and the successive licensors have only limited -* liability. -* -* In this respect, the user's attention is drawn to the risks associated -* with loading, using, modifying and/or developing or reproducing the -* software by the user in light of its specific status of free software, -* that may mean that it is complicated to manipulate, and that also -* therefore means that it is reserved for developers and experienced -* professionals having in-depth computer knowledge. Users are therefore -* encouraged to load and test the software's suitability as regards their -* requirements in conditions enabling the security of their systems and/or -* data to be ensured and, more generally, to use and operate it in the -* same conditions as regards security. -* -* The fact that you are presently reading this means that you have had -* knowledge of the CeCILL license and that you accept its terms. -**/ - -package Typing - -// import ( -// "github.com/GoelandProver/Goeland/AST" -// "github.com/GoelandProver/Goeland/Glob" -// "github.com/GoelandProver/Goeland/Lib" -// ) - -// /** -// * This file implements a second pass on the given formula to: -// * - Type the variables -// * - Give a type to the polymorph predicates / functions -// **/ - -// func SecondPass(form AST.Form) AST.Form { -// after := secondPassAux(form, []AST.Var{}, []AST.TypeApp{}) -// return after -// } - -// func secondPassAux(form AST.Form, vars []AST.Var, types []AST.TypeApp) AST.Form { -// switch f := form.(type) { -// case AST.Pred: -// terms := nArySecondPassTerms(f.GetArgs(), vars, types) - -// // Special case: defined predicate. We need to infer types. -// if f.GetID().Equals(AST.Id_eq) { -// return AST.MakePred( -// f.GetIndex(), -// f.GetID(), -// terms, -// []AST.TypeApp{ -// AST.GetOutType( -// Glob.To[AST.TypedTerm, AST.Term](terms.At(0)).GetTypeHint(), -// )}) -// } - -// // Real case: classical predicate, it should be given -// return AST.MakePred(f.GetIndex(), f.GetID(), terms, f.GetTypeVars()) -// case AST.And: -// return AST.MakeAnd(f.GetIndex(), nArySecondPass(f.GetChildFormulas(), vars, types)) -// case AST.Or: -// return AST.MakeOr(f.GetIndex(), nArySecondPass(f.Get, vars, types)) -// case AST.Imp: -// return AST.MakeImp(f.GetIndex(), secondPassAux(f.GetF1(), vars, types), secondPassAux(f.GetF2(), vars, types)) -// case AST.Equ: -// return AST.MakeEqu(f.GetIndex(), secondPassAux(f.GetF1(), vars, types), secondPassAux(f.GetF2(), vars, types)) -// case AST.Not: -// return AST.MakeNot(f.GetIndex(), secondPassAux(f.GetForm(), vars, types)) -// case AST.All: -// return AST.MakeAll(f.GetIndex(), f.GetVarList(), secondPassAux(f.GetForm(), append(vars, f.GetVarList()...), types)) -// case AST.Ex: -// return AST.MakeEx(f.GetIndex(), f.GetVarList(), secondPassAux(f.GetForm(), append(vars, f.GetVarList()...), types)) -// case AST.AllType: -// return AST.MakeAllType(f.GetIndex(), f.GetVarList(), secondPassAux(f.GetForm(), vars, append(types, Glob.ConvertList[AST.TypeVar, AST.TypeApp](f.GetVarList())...))) -// } -// return form -// } - -// func secondPassTerm(term AST.Term, vars []AST.Var, types []AST.TypeApp) AST.Term { -// switch t := term.(type) { -// case AST.Fun: -// terms := nArySecondPassTerms(t.GetArgs(), vars, types) - -// // - It's a function -// outType := func(term AST.Term) AST.TypeApp { -// return AST.GetOutType(Glob.To[AST.TypedTerm](term).GetTypeHint()) -// } - -// termsType := []AST.TypeApp{} -// for _, tm := range terms.GetSlice() { -// termsType = append(termsType, outType(tm)) -// } - -// return AST.MakerFun(t.GetID(), terms, t.GetTypeVars(), -// getTypeOfFunction(t.GetName(), t.GetTypeVars(), termsType)) - -// case AST.Var: -// return t -// } -// return term -// } - -// func nArySecondPass(forms Lib.List[AST.Form], vars []AST.Var, types []AST.TypeApp) Lib.List[AST.Form] { -// res := Lib.NewList[AST.Form]() - -// for _, form := range forms.GetSlice() { -// res.Append(secondPassAux(form, vars, types)) -// } - -// return res -// } - -// func nArySecondPassTerms( -// terms Lib.List[AST.Term], -// vars []AST.Var, -// types []AST.TypeApp, -// ) Lib.List[AST.Term] { -// resTerms := Lib.NewList[AST.Term]() - -// for _, term := range terms.GetSlice() { -// t := secondPassTerm(term, vars, types) - -// if t != nil { -// resTerms.Append(t) -// } -// } - -// return resTerms -// } - -// func getTypeOfFunction(name string, vars []AST.TypeApp, termsType []AST.TypeApp) AST.TypeScheme { -// // Build TypeCross from termsType -// var tt []AST.TypeApp -// if len(termsType) >= 2 { -// tc := AST.MkTypeCross(termsType[0], termsType[1]) -// for i := 2; i < len(termsType); i += 1 { -// tc = AST.MkTypeCross(tc, termsType[i]) -// } -// tt = []AST.TypeApp{tc} -// } else { -// tt = termsType -// } - -// simpleTypeScheme := AST.GetType(name, tt...) -// if simpleTypeScheme != nil { -// if Glob.Is[AST.QuantifiedType](simpleTypeScheme) { -// return Glob.To[AST.QuantifiedType](simpleTypeScheme).Instanciate(vars) -// } -// return simpleTypeScheme -// } - -// typeScheme := AST.GetPolymorphicType(name, len(vars), len(termsType)) - -// if typeScheme != nil { -// // Instantiate type scheme with actual types -// typeScheme = Glob.To[AST.QuantifiedType](typeScheme).Instanciate(vars) -// } else { -// // As only distinct objects are here, it should work with only this. -// // I leave the other condition if others weirderies are found later. -// if len(termsType) == 0 { -// AST.SaveConstant(name, Glob.To[AST.TypeApp](AST.DefaultFunType(0))) -// } -// /* -// else { -// type_ := DefaultFunType(len(termsType)) -// if len(termsType) == 1 { -// SaveTypeScheme(name, GetInputType(type_)[0], GetOutType(type_)) -// } else { -// SaveTypeScheme(name, AST.MkTypeCross(GetInputType(type_)...), GetOutType(type_)) -// } -// } -// */ -// typeScheme = AST.DefaultFunType(0) - -// } - -// return typeScheme -// } diff --git a/src/Typing/type_rules.go b/src/Typing/type_rules.go deleted file mode 100644 index f285ca85..00000000 --- a/src/Typing/type_rules.go +++ /dev/null @@ -1,220 +0,0 @@ -/** -* Copyright 2022 by the authors (see AUTHORS). -* -* Goéland is an automated theorem prover for first order logic. -* -* This software is governed by the CeCILL license under French law and -* abiding by the rules of distribution of free software. You can use, -* modify and/ or redistribute the software under the terms of the CeCILL -* license as circulated by CEA, CNRS and INRIA at the following URL -* "http://www.cecill.info". -* -* As a counterpart to the access to the source code and rights to copy, -* modify and redistribute granted by the license, users are provided only -* with a limited warranty and the software's author, the holder of the -* economic rights, and the successive licensors have only limited -* liability. -* -* In this respect, the user's attention is drawn to the risks associated -* with loading, using, modifying and/or developing or reproducing the -* software by the user in light of its specific status of free software, -* that may mean that it is complicated to manipulate, and that also -* therefore means that it is reserved for developers and experienced -* professionals having in-depth computer knowledge. Users are therefore -* encouraged to load and test the software's suitability as regards their -* requirements in conditions enabling the security of their systems and/or -* data to be ensured and, more generally, to use and operate it in the -* same conditions as regards security. -* -* The fact that you are presently reading this means that you have had -* knowledge of the CeCILL license and that you accept its terms. -**/ - -package Typing - -// import ( -// "fmt" - -// "github.com/GoelandProver/Goeland/AST" -// "github.com/GoelandProver/Goeland/Glob" -// "github.com/GoelandProver/Goeland/Lib" -// ) - -// /** -// * This file contains the rules for typing terms, and also the App rule. -// * The App rule is used for predicates and functions. -// **/ - -// /* Applies the Var rule for a type variable: erase consequence */ -// func applyLocalTypeVarRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { -// // Add applied rule to the prooftree -// root.appliedRule = "Var" - -// // Find current variable in the local context -// if _, ok := getTypeFromLocalContext(state.localContext, state.consequence.a.(AST.TypeVar)); !ok { -// return Reconstruct{ -// result: false, -// err: fmt.Errorf("TypeVar %s not found in the local context", state.consequence.a.ToString()), -// } -// } - -// // No consequence: next rule is the WF rule. -// children := []Sequent{ -// { -// globalContext: state.globalContext, -// localContext: state.localContext.copy(), -// consequence: Consequence{}, -// }, -// } - -// return launchChildren(children, root, fatherChan) -// } - -// /* Applies the Var rule for a type hint: erase consequence */ -// func applyGlobalTypeVarRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { -// // Add applied rule to the prooftree -// root.appliedRule = "Var" - -// // Find current variable in the local context -// if found := state.globalContext.isTypeInContext(Glob.To[AST.TypeScheme](state.consequence.a)); !found { -// return Reconstruct{ -// result: false, -// err: fmt.Errorf("TypeVar %s not found in the global context", state.consequence.a.ToString()), -// } -// } - -// // No consequence: next rule is the WF rule. -// children := []Sequent{ -// { -// globalContext: state.globalContext, -// localContext: state.localContext.copy(), -// consequence: Consequence{}, -// }, -// } - -// return launchChildren(children, root, fatherChan) -// } - -// /* Applies Type rule: erase consequence */ -// func applyTypeWFRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { -// // Add applied rule to the prooftree -// root.appliedRule = "Type" - -// // WF child -// children := []Sequent{ -// { -// globalContext: state.globalContext, -// localContext: state.localContext.copy(), -// consequence: Consequence{}, -// }, -// } - -// return launchChildren(children, root, fatherChan) -// } - -// /* Applies Cross rule */ -// func applyCrossRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { -// // Add applied rule to the prooftree -// root.appliedRule = "Cross" - -// if tc, ok := state.consequence.a.(AST.TypeCross); ok { -// // Construct a child for every type recovered -// return launchChildren(constructWithTypes(state, tc.GetAllUnderlyingTypes()), root, fatherChan) -// } else { -// return Reconstruct{ -// result: false, -// err: fmt.Errorf("CrossRule type on something that is not a TypeCross: %s", state.consequence.a.ToString()), -// } -// } -// } - -// /* Sym rule: a child for each type in the input, and one for the output if it's a function */ -// func applySymRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { -// root.appliedRule = "Sym" - -// primitives := state.consequence.s.GetPrimitives() -// out := AST.GetOutType(state.consequence.s) - -// newLocalContext := state.localContext.copy() -// if qt, found := state.consequence.s.(AST.QuantifiedType); found { -// newLocalContext.typeVars = append(newLocalContext.typeVars, qt.QuantifiedVars()...) -// } - -// children := []Sequent{} -// if Glob.Is[AST.TypeScheme](out) { -// children = append(children, Sequent{ -// globalContext: state.globalContext, -// localContext: newLocalContext, -// consequence: Consequence{a: out}, -// }) -// } - -// for _, type_ := range primitives[:len(primitives)-1] { -// children = append(children, Sequent{ -// globalContext: state.globalContext, -// localContext: newLocalContext, -// consequence: Consequence{a: type_}, -// }) -// } - -// return launchChildren(children, root, fatherChan) -// } - -// /* AppType rule: a child for each type in the input, and checks if the parameterized type exists. */ -// func applyAppTypeRule(state Sequent, root *ProofTree, fatherChan chan Reconstruct) Reconstruct { -// root.appliedRule = "App" - -// type_ := state.consequence.a.(AST.ParameterizedType) -// types := type_.GetParameters() - -// // Search for the ID in the global context -// if !state.globalContext.parameterizedTypesContains(type_.GetName()) { -// return Reconstruct{ -// result: false, -// err: fmt.Errorf("parameterized Type %s not in context", type_.ToString()), -// } -// } - -// children := []Sequent{} -// for _, type_ := range types { -// children = append(children, Sequent{ -// globalContext: state.globalContext, -// localContext: state.localContext.copy(), -// consequence: Consequence{a: type_}, -// }) -// } - -// result := launchChildren(children, root, fatherChan) - -// // Only one term needs to be returned because the ParameterizedType is counted as one. -// return Reconstruct{ -// result: result.result, -// err: result.err, -// terms: Lib.NewList[AST.Term](), -// } -// } - -// /* Utils functions */ - -// /* Finds the given term in the local context, returns false if it couldn't */ -// func getTypeFromLocalContext(localContext LocalContext, typeApp AST.TypeVar) (AST.TypeApp, bool) { -// for _, type_ := range localContext.typeVars { -// if typeApp.Equals(type_) { -// return type_, true -// } -// } -// return AST.TypeVar{}, false -// } - -// /* Constructs all the children of a composed type */ -// func constructWithTypes(state Sequent, types []AST.TypeApp) []Sequent { -// children := []Sequent{} -// for _, type_ := range types { -// children = append(children, Sequent{ -// globalContext: state.globalContext, -// localContext: state.localContext.copy(), -// consequence: Consequence{a: type_}, -// }) -// } -// return children -// } diff --git a/src/Unif/matching.go b/src/Unif/matching.go index 9003bf1a..3b7dae18 100644 --- a/src/Unif/matching.go +++ b/src/Unif/matching.go @@ -67,8 +67,10 @@ func (m *Machine) unify(node Node, formula AST.Form) []MatchingSubstitutions { switch formula_type := formula.(type) { case AST.Pred: // Transform the predicate to a function to make the tool work properly + // FIXME: transform type arguments into terms to unify them m.terms = Lib.MkListV[AST.Term](AST.MakerFun( formula_type.GetID(), + formula_type.GetTyArgs(), formula_type.GetArgs(), )) result = m.unifyAux(node) diff --git a/src/Unif/substitutions_type.go b/src/Unif/substitutions_type.go index 138bf430..7c43b118 100644 --- a/src/Unif/substitutions_type.go +++ b/src/Unif/substitutions_type.go @@ -213,7 +213,7 @@ func MakeEmptySubstitutionList() []Substitutions { /* Returns a « failed » substitution. */ func Failure() Substitutions { - fail := AST.MakeMeta(-1, -1, "FAILURE", -1) + fail := AST.MakeEmptyMeta() return Substitutions{Substitution{fail, fail}} } @@ -313,6 +313,7 @@ func eliminateInside(key AST.Meta, value AST.Term, s Substitutions, has_changed_ case AST.Fun: new_value := AST.MakerFun( value_2_type.GetP(), + value_2_type.GetTyArgs(), eliminateList(key, value, value_2_type.GetArgs(), &has_changed), ) if OccurCheckValid(key_2, new_value) { @@ -358,6 +359,7 @@ func eliminateList( case AST.Fun: // If its a function, reccursive call for the arguments tempList.Append(AST.MakerFun( lt.GetP(), + lt.GetTyArgs(), eliminateList(key, value, lt.GetArgs(), &hasChanged), )) default: diff --git a/src/main.go b/src/main.go index b0eab71f..d6eea737 100644 --- a/src/main.go +++ b/src/main.go @@ -58,7 +58,7 @@ import ( "github.com/GoelandProver/Goeland/Parser" "github.com/GoelandProver/Goeland/Search" "github.com/GoelandProver/Goeland/Search/incremental" - _ "github.com/GoelandProver/Goeland/Typing" + "github.com/GoelandProver/Goeland/Typing" "github.com/GoelandProver/Goeland/Unif" ) @@ -135,12 +135,12 @@ func presearchLoader() (AST.Form, int) { ) statements, bound, containsEquality := Parser.ParseTPTPFile(problem) - actualStatements := Engine.ToInternalSyntax(statements) + actual_statements, is_typed_problem := Engine.ToInternalSyntax(statements) debug( Lib.MkLazy(func() string { return fmt.Sprintf( - "Statement : %s", Core.StatementListToString(actualStatements)) + "Statement : %s", Core.StatementListToString(actual_statements)) }), ) @@ -148,7 +148,7 @@ func presearchLoader() (AST.Form, int) { bound = Glob.GetLimit() } - form, bound, contEq := StatementListToFormula(actualStatements, bound, path.Dir(problem)) + form, bound, contEq, is_typed_include := StatementListToFormula(actual_statements, bound, path.Dir(problem)) containsEquality = containsEquality || contEq if !containsEquality { @@ -160,7 +160,9 @@ func presearchLoader() (AST.Form, int) { Glob.Fatal(main_label, "Problem not found") } - form = checkForTypedProof(form) + if is_typed_problem || is_typed_include { + checkForTypedProof(form) + } return form, bound } @@ -190,6 +192,7 @@ func initEverything() { initOpts() runtime.GOMAXPROCS(Glob.GetCoreLimit()) AST.Init() + Typing.Init() } func initDebuggers() { @@ -205,8 +208,14 @@ func initDebuggers() { Unif.InitDebugger() } -func StatementListToFormula(statements []Core.Statement, old_bound int, problemDir string) (form AST.Form, bound int, containsEquality bool) { +// FIXME: eventually, we would want to add an "interpretation" layer between elab and internal representation that does this +func StatementListToFormula( + statements []Core.Statement, + old_bound int, + problemDir string, +) (form AST.Form, bound int, containsEquality bool, is_typed_problem bool) { and_list := Lib.NewList[AST.Form]() + is_typed_problem = false var not_form AST.Form bound = old_bound @@ -220,18 +229,19 @@ func StatementListToFormula(statements []Core.Statement, old_bound int, problemD if err != nil { Glob.PrintError(main_label, err.Error()) - return nil, -1, false + return nil, -1, false, false } new_lstm, bound_tmp, contEq := Parser.ParseTPTPFile(realname) - actual_new_lstm := Engine.ToInternalSyntax(new_lstm) + actual_new_lstm, is_typed := Engine.ToInternalSyntax(new_lstm) containsEquality = containsEquality || contEq - new_form_list, new_bound, contEq := StatementListToFormula( + new_form_list, new_bound, contEq, is_typed := StatementListToFormula( actual_new_lstm, bound_tmp, path.Join(problemDir, path.Dir(file_name)), ) containsEquality = containsEquality || contEq + is_typed_problem = is_typed_problem || is_typed if new_form_list != nil { bound = new_bound @@ -266,15 +276,15 @@ func StatementListToFormula(statements []Core.Statement, old_bound int, problemD switch { case and_list.Empty() && not_form == nil: - return nil, bound, containsEquality + return nil, bound, containsEquality, is_typed_problem case and_list.Empty(): - return AST.MakerNot(not_form), bound, containsEquality + return AST.MakerNot(not_form), bound, containsEquality, is_typed_problem case not_form == nil: - return AST.MakerAnd(and_list), bound, containsEquality + return AST.MakerAnd(and_list), bound, containsEquality, is_typed_problem default: flattened := AST.LsFlatten(and_list) flattened.Append(AST.MakerNot(not_form)) - return AST.MakerAnd(flattened), bound, containsEquality + return AST.MakerAnd(flattened), bound, containsEquality, is_typed_problem } } @@ -305,33 +315,13 @@ func doConjectureStatement(f AST.Form) AST.Form { } func doTypeStatement(atomTyping Core.TFFAtomTyping) { - typeScheme := atomTyping.Ts + typeScheme := atomTyping.Ty if typeScheme == nil { Glob.PrintWarn("main", fmt.Sprintf("The constant %s has no type!", atomTyping.Literal.ToString())) - return } - if typeScheme.Size() == 1 { - isNewType := typeScheme.ToString() == "$tType" - if isNewType { - AST.MkTypeHint(atomTyping.Literal.GetName()) - } else { - isConstant := !Glob.Is[AST.QuantifiedType](typeScheme) - if isConstant { - AST.SaveConstant(atomTyping.Literal.GetName(), typeScheme.GetPrimitives()[0]) - } else { - AST.SavePolymorphScheme(atomTyping.Literal.GetName(), typeScheme) - } - } - } else { - switch typeScheme.(type) { - case AST.TypeArrow: - AST.SaveTypeScheme(atomTyping.Literal.GetName(), AST.GetInputType(typeScheme)[0], AST.GetOutType(typeScheme)) - case AST.QuantifiedType: - AST.SavePolymorphScheme(atomTyping.Literal.GetName(), typeScheme) - } - } + Typing.AddToGlobalEnv(atomTyping.Literal.GetName(), atomTyping.Ty) } func getFile(filename string, dir string) (string, error) { @@ -362,18 +352,9 @@ func getFile(filename string, dir string) (string, error) { return "", fmt.Errorf("file %s not found", filename) } -func checkForTypedProof(form AST.Form) AST.Form { - isTypedProof := !AST.EmptyGlobalContext() && !Glob.NoTypeCheck() - - if isTypedProof { - // err := Typing.WellFormedVerification(form.Copy(), Glob.GetTypeProof()) - - // if err != nil { - // Glob.Fatal(main_label, fmt.Sprintf("Typing error: %v", err)) - // } else { - // Glob.PrintInfo(main_label, "Well typed.") - // } +func checkForTypedProof(form AST.Form) { + if !Glob.NoTypeCheck() && !Typing.TypeCheck(form) { + Glob.Fatal(main_label, fmt.Sprintf("Formula %s is not well typed", form.ToString())) } - - return form + Glob.PrintInfo(main_label, "Problem is well typed") } From 75610ed0b384cb76cdd1900c6a3923228e1f3b08 Mon Sep 17 00:00:00 2001 From: Johann Rosain Date: Wed, 23 Jul 2025 22:32:14 +0200 Subject: [PATCH 06/30] Implementation of the new typing system --- devtools/test-suite/basic/tf1_syntax_chk.p | 4 +- devtools/test-suite/basic/tfa_syntax_chk.p | 2 +- devtools/test-suite/bugs/bug_53-1.p | 33 +++ src/AST/formsDef.go | 72 ++++- src/AST/formula.go | 8 + src/AST/maker.go | 2 +- src/AST/quantifiers.go | 43 ++- src/AST/term.go | 1 + src/AST/termsDef.go | 35 ++- src/AST/tptp-native-types.go | 153 +++-------- src/AST/ty-syntax.go | 96 +++++-- src/AST/typed-vars.go | 6 +- src/Engine/pretyper.go | 113 +++++++- src/Engine/syntax-translation.go | 257 ++++++++++++++---- src/Engine/tptp-defined-types.go | 155 +++++++++++ src/Lib/par.go | 86 ++++++ src/Lib/string.go | 10 +- .../equality/bse/equality_problem_list.go | 13 +- src/Parser/pprinter.go | 34 +-- src/Parser/psyntax.go | 48 +++- src/Typing/env-and-context.go | 15 + src/Typing/init.go | 111 ++++++++ src/Typing/rules.go | 248 +++++++++++++++++ src/Unif/parsing.go | 3 + src/main.go | 1 + 25 files changed, 1305 insertions(+), 244 deletions(-) create mode 100644 devtools/test-suite/bugs/bug_53-1.p create mode 100644 src/Engine/tptp-defined-types.go create mode 100644 src/Lib/par.go diff --git a/devtools/test-suite/basic/tf1_syntax_chk.p b/devtools/test-suite/basic/tf1_syntax_chk.p index ddbabeb5..fbddcf04 100644 --- a/devtools/test-suite/basic/tf1_syntax_chk.p +++ b/devtools/test-suite/basic/tf1_syntax_chk.p @@ -1,5 +1,5 @@ -% TODO: args -one_step and result NOT_VALID once typing is working again (this is satisfiable) -% exit: 3 +% args: -one_step +% result: NOT VALID tff(beverage_type,type, beverage: $tType ). diff --git a/devtools/test-suite/basic/tfa_syntax_chk.p b/devtools/test-suite/basic/tfa_syntax_chk.p index bcf3c0bb..aa731dfc 100644 --- a/devtools/test-suite/basic/tfa_syntax_chk.p +++ b/devtools/test-suite/basic/tfa_syntax_chk.p @@ -1,5 +1,5 @@ % As arithmetic is not handled by Goeland, we simply check that parsing is OK -% args: -ari -one_step -l 1 +% args: -one_step -l 1 % result: NOT VALID tff(p_int_type,type, diff --git a/devtools/test-suite/bugs/bug_53-1.p b/devtools/test-suite/bugs/bug_53-1.p new file mode 100644 index 00000000..942299af --- /dev/null +++ b/devtools/test-suite/bugs/bug_53-1.p @@ -0,0 +1,33 @@ +% args: -one_step +% exit: 1 + +tff(list_type,type, + list: $tType > $tType ). + +tff(maybe_type,type, + maybe: $tType > $tType ). + +%----Polymorphic symbols +tff(nil_type,type, + nil: + !>[A: $tType] : list(A) ). + +tff(cons_type,type, + cons: + !>[A: $tType] : ( ( A * list(A) ) > list(A) ) ). + +tff(none_type,type, + none: + !>[A: $tType] : maybe(A) ). + +tff(some_type,type, + some: + !>[A: $tType] : ( A > maybe(A) ) ). + +tff(head_type,type, + head: + !>[A: $tType] : ( list(A) > maybe(A) ) ). + +%----This cannot be well typed, the last cons is not well formed +tff(solve_this,conjecture, + head($int,cons($int,1,cons($int,2,cons($int,3)))) = some($int,1) ). diff --git a/src/AST/formsDef.go b/src/AST/formsDef.go index bf1922c3..a1149588 100644 --- a/src/AST/formsDef.go +++ b/src/AST/formsDef.go @@ -120,6 +120,10 @@ func (a All) ReplaceTermByTerm(old Term, new Term) (Form, bool) { return All{quant}, isReplaced } +func (a All) ReplaceTyVar(old TyBound, new Ty) Form { + return All{a.quantifier.replaceTyVar(old, new)} +} + func (a All) SubstituteVarByMeta(old Var, new Meta) Form { return All{a.quantifier.substituteVarByMeta(old, new)} } @@ -168,6 +172,10 @@ func (e Ex) ReplaceTermByTerm(old Term, new Term) (Form, bool) { return Ex{quant}, isReplaced } +func (e Ex) ReplaceTyVar(old TyBound, new Ty) Form { + return Ex{e.quantifier.replaceTyVar(old, new)} +} + func (e Ex) SubstituteVarByMeta(old Var, new Meta) Form { return Ex{e.quantifier.substituteVarByMeta(old, new)} } @@ -271,6 +279,11 @@ func (o Or) ReplaceTermByTerm(old Term, new Term) (Form, bool) { return no, res } +func (o Or) ReplaceTyVar(old TyBound, new Ty) Form { + formList := replaceTyVarInFormList(o.forms, old, new) + return MakeOrSimple(o.GetIndex(), formList, o.metas.Raw()) +} + func (o Or) RenameVariables() Form { return MakeOr(o.GetIndex(), renameFormList(o.forms)) } @@ -407,6 +420,11 @@ func (a And) ReplaceTermByTerm(old Term, new Term) (Form, bool) { return na, res } +func (a And) ReplaceTyVar(old TyBound, new Ty) Form { + formList := replaceTyVarInFormList(a.forms, old, new) + return MakeAndSimple(a.GetIndex(), formList, a.metas.Raw()) +} + func (a And) RenameVariables() Form { return MakeAnd(a.GetIndex(), renameFormList(a.forms)) } @@ -518,6 +536,15 @@ func (e Equ) ReplaceTermByTerm(old Term, new Term) (Form, bool) { return ne, res1 || res2 } +func (e Equ) ReplaceTyVar(old TyBound, new Ty) Form { + return MakeEquSimple( + e.GetIndex(), + e.f1.ReplaceTyVar(old, new), + e.f2.ReplaceTyVar(old, new), + e.metas.Raw(), + ) +} + func (e Equ) RenameVariables() Form { return MakeEqu(e.GetIndex(), e.GetF1().RenameVariables(), e.GetF2().RenameVariables()) } @@ -639,6 +666,15 @@ func (i Imp) ReplaceTermByTerm(old Term, new Term) (Form, bool) { return ni, res1 || res2 } +func (i Imp) ReplaceTyVar(old TyBound, new Ty) Form { + return MakeImpSimple( + i.GetIndex(), + i.f1.ReplaceTyVar(old, new), + i.f2.ReplaceTyVar(old, new), + i.metas.Raw(), + ) +} + func (i Imp) RenameVariables() Form { return MakeImp(i.GetIndex(), i.GetF1().RenameVariables(), i.GetF2().RenameVariables()) } @@ -757,6 +793,14 @@ func (n Not) ReplaceTermByTerm(old Term, new Term) (Form, bool) { return nn, res } +func (n Not) ReplaceTyVar(old TyBound, new Ty) Form { + return MakeNotSimple( + n.GetIndex(), + n.f.ReplaceTyVar(old, new), + n.metas.Raw(), + ) +} + func (n Not) RenameVariables() Form { return MakeNot(n.GetIndex(), n.f.RenameVariables()) } @@ -882,11 +926,17 @@ func (p Pred) ToString() string { } func (p Pred) ToMappedStringSurround(mapping MapString, displayTypes bool) string { - if p.GetArgs().Len() == 0 { + if p.tys.Empty() && p.GetArgs().Empty() { return p.GetID().ToMappedString(mapping, displayTypes) + "%s" } args := []string{} + if !p.tys.Empty() { + if tv := Lib.ListToString(p.tys, ", ", mapping[PredEmpty]); tv != "" { + args = append(args, tv) + } + } + args = append(args, "%s") if p.GetID().GetName() == "=" { @@ -982,6 +1032,24 @@ func (p Pred) ReplaceTermByTerm(old Term, new Term) (Form, bool) { return np, res } +func (p Pred) ReplaceTyVar(old TyBound, new Ty) Form { + typed_args := Lib.ListMap( + p.tys, + func(t Ty) Ty { return t.ReplaceTyVar(old, new) }, + ) + args := Lib.ListMap( + p.args, + func(t Term) Term { return t.ReplaceTyVar(old, new) }, + ) + return MakePredSimple( + p.GetIndex(), + p.GetID(), + typed_args, + args, + p.metas.Raw(), + ) +} + func (p Pred) GetSubTerms() Lib.List[Term] { res := Lib.NewList[Term]() @@ -1073,6 +1141,7 @@ func (t Top) Copy() Form { return MakeTop(t.Get func (Top) Equals(f any) bool { _, isTop := f.(Top); return isTop } func (Top) GetMetas() Lib.Set[Meta] { return Lib.EmptySet[Meta]() } func (t Top) ReplaceTermByTerm(Term, Term) (Form, bool) { return MakeTop(t.GetIndex()), false } +func (t Top) ReplaceTyVar(TyBound, Ty) Form { return t } func (t Top) RenameVariables() Form { return MakeTop(t.GetIndex()) } func (t Top) GetIndex() int { return t.index } func (t Top) GetSubTerms() Lib.List[Term] { return Lib.NewList[Term]() } @@ -1115,6 +1184,7 @@ func (b Bot) Copy() Form { return MakeBot(b.Get func (Bot) Equals(f any) bool { _, isBot := f.(Bot); return isBot } func (Bot) GetMetas() Lib.Set[Meta] { return Lib.EmptySet[Meta]() } func (b Bot) ReplaceTermByTerm(Term, Term) (Form, bool) { return MakeBot(b.GetIndex()), false } +func (b Bot) ReplaceTyVar(TyBound, Ty) Form { return b } func (b Bot) RenameVariables() Form { return MakeBot(b.GetIndex()) } func (b Bot) GetIndex() int { return b.index } func (b Bot) GetSubTerms() Lib.List[Term] { return Lib.NewList[Term]() } diff --git a/src/AST/formula.go b/src/AST/formula.go index 18532b5c..843675c7 100644 --- a/src/AST/formula.go +++ b/src/AST/formula.go @@ -54,6 +54,7 @@ type Form interface { MappableString ReplaceTermByTerm(old Term, new Term) (Form, bool) + ReplaceTyVar(old TyBound, new Ty) Form RenameVariables() Form SubstituteVarByMeta(old Var, new Meta) Form ReplaceMetaByTerm(meta Meta, term Term) Form @@ -135,6 +136,13 @@ func replaceTermInFormList(oldForms Lib.List[Form], oldTerm Term, newTerm Term) return newForms, res } +func replaceTyVarInFormList(oldForms Lib.List[Form], old TyBound, new Ty) Lib.List[Form] { + return Lib.ListMap( + oldForms, + func(f Form) Form { return f.ReplaceTyVar(old, new) }, + ) +} + func renameFormList(forms Lib.List[Form]) Lib.List[Form] { newForms := Lib.MkList[Form](forms.Len()) diff --git a/src/AST/maker.go b/src/AST/maker.go index 3b509884..c67aa8f4 100644 --- a/src/AST/maker.go +++ b/src/AST/maker.go @@ -66,10 +66,10 @@ var EmptyPredEq Pred /* Initialization */ func Init() { Reset() - initTPTPNativeTypes() Id_eq = MakerId("=") EmptyPredEq = MakerPred(Id_eq, Lib.NewList[Ty](), Lib.NewList[Term]()) initDefaultMap() + initTPTPNativeTypes() } /* Reset all the maps and counters */ diff --git a/src/AST/quantifiers.go b/src/AST/quantifiers.go index 75b770dc..4a0db4a5 100644 --- a/src/AST/quantifiers.go +++ b/src/AST/quantifiers.go @@ -106,11 +106,9 @@ func ChangeVarSeparator(sep string) string { func (q quantifier) ToMappedStringSurround(mapping MapString, displayTypes bool) string { varStrings := []string{} - for _ = range q.GetVarList().GetSlice() { - str := mapping[QuantVarOpen] - str += ListToMappedString(q.GetVarList().GetSlice(), varSeparator, "", mapping, false) - varStrings = append(varStrings, str+mapping[QuantVarClose]) - } + str := mapping[QuantVarOpen] + str += ListToMappedString(q.GetVarList().GetSlice(), varSeparator, "", mapping, false) + varStrings = append(varStrings, str+mapping[QuantVarClose]) return "(" + mapping[q.symbol] + " " + strings.Join(varStrings, " ") + mapping[QuantVarSep] + " (%s))" } @@ -162,20 +160,49 @@ func (q quantifier) replaceTermByTerm(old Term, new Term) (quantifier, bool) { ), res } +func (q quantifier) replaceTyVar(old TyBound, new Ty) quantifier { + f := q.GetForm().ReplaceTyVar(old, new) + return makeQuantifier( + q.GetIndex(), + Lib.ListMap( + q.GetVarList(), + func(p TypedVar) TypedVar { return p.ReplaceTyVar(old, new) }, + ), + f, + q.metas.Raw().Copy(), + q.symbol, + ) +} + func (q quantifier) renameVariables() quantifier { newVarList := Lib.NewList[TypedVar]() - newForm := q.GetForm() + newForm := q.GetForm().RenameVariables() + newTyBv := Lib.NewList[Lib.Pair[TyBound, Ty]]() for _, v := range q.GetVarList().GetSlice() { newVar := MakerNewVar(v.GetName()) newVar = MakerVar(fmt.Sprintf("%s%d", newVar.GetName(), newVar.GetIndex())) newVarList.Append(MkTypedVar(newVar.name, newVar.index, v.ty)) - newForm, _ = newForm.RenameVariables().ReplaceTermByTerm(v.ToBoundVar(), newVar) + f, replaced := newForm.ReplaceTermByTerm(v.ToBoundVar(), newVar) + if !replaced { + newBv := MkTyBV(newVar.name, newVar.index) + f = f.ReplaceTyVar(v.ToTyBoundVar(), newBv) + newTyBv.Append(Lib.MkPair(v.ToTyBoundVar(), newBv)) + } + newForm = f } return makeQuantifier( q.GetIndex(), - newVarList, + Lib.ListMap( + newVarList, + func(p TypedVar) TypedVar { + for _, pair := range newTyBv.GetSlice() { + p = p.ReplaceTyVar(pair.Fst, pair.Snd) + } + return p + }, + ), newForm, q.metas.Raw().Copy(), q.symbol, diff --git a/src/AST/term.go b/src/AST/term.go index 23adba38..b14e25d4 100644 --- a/src/AST/term.go +++ b/src/AST/term.go @@ -53,6 +53,7 @@ type Term interface { GetMetaList() Lib.List[Meta] // Metas appearing in the term ORDERED GetSubTerms() Lib.List[Term] ReplaceSubTermBy(original_term, new_term Term) Term + ReplaceTyVar(old TyBound, new Ty) Term Less(any) bool } diff --git a/src/AST/termsDef.go b/src/AST/termsDef.go index 49e2bb6f..4fa32076 100644 --- a/src/AST/termsDef.go +++ b/src/AST/termsDef.go @@ -111,6 +111,8 @@ func (i Id) ReplaceSubTermBy(original_term, new_term Term) Term { return i } +func (i Id) ReplaceTyVar(TyBound, Ty) Term { return i } + func (i Id) GetSubTerms() Lib.List[Term] { return Lib.MkListV[Term](i) } @@ -161,10 +163,17 @@ func (f Fun) ToMappedStringChild(mapping MapString, displayTypes bool) (separato } func (f Fun) ToMappedStringSurroundWithId(idString string, mapping MapString, displayTypes bool) string { - if f.GetArgs().Len() == 0 { + if f.tys.Empty() && f.GetArgs().Empty() { return idString + "%s" } + args := []string{} + if !f.tys.Empty() { + if tv := Lib.ListToString(f.tys, ", ", mapping[PredEmpty]); tv != "" { + args = append(args, tv) + } + } + args = append(args, "%s") str := idString + "(" + strings.Join(args, mapping[PredTypeVarSep]) + ")" @@ -268,6 +277,23 @@ func (f Fun) ReplaceSubTermBy(oldTerm, newTerm Term) Term { } } +func (f Fun) ReplaceTyVar(old TyBound, new Ty) Term { + typed_args := Lib.ListMap( + f.tys, + func(t Ty) Ty { return t.ReplaceTyVar(old, new) }, + ) + args := Lib.ListMap( + f.args, + func(t Term) Term { return t.ReplaceTyVar(old, new) }, + ) + return MakeFun( + f.GetID(), + typed_args, + args, + f.metas.Raw(), + ) +} + func (f Fun) ReplaceAllSubTerm(oldTerm, newTerm Term) Term { if f.Equals(oldTerm) { return newTerm.Copy() @@ -338,10 +364,9 @@ func (v Var) ReplaceSubTermBy(original_term, new_term Term) Term { return v } +func (v Var) ReplaceTyVar(TyBound, Ty) Term { return v } + func (v Var) ToMappedString(map_ MapString, type_ bool) string { - if type_ { - return fmt.Sprintf("%s_%d", v.GetName(), v.GetIndex()) - } return v.GetName() } @@ -429,6 +454,8 @@ func (m Meta) ReplaceSubTermBy(original_term, new_term Term) Term { return m } +func (m Meta) ReplaceTyVar(TyBound, Ty) Term { return m } + func (m Meta) GetSubTerms() Lib.List[Term] { return Lib.MkListV[Term](m) } diff --git a/src/AST/tptp-native-types.go b/src/AST/tptp-native-types.go index 7bc401e1..3b4b821d 100644 --- a/src/AST/tptp-native-types.go +++ b/src/AST/tptp-native-types.go @@ -38,130 +38,61 @@ package AST -// FIXME: update this file with the new type system +import ( + "github.com/GoelandProver/Goeland/Lib" +) -// var tInt TypeHint -// var tRat TypeHint -// var tReal TypeHint -// var defaultType TypeHint -// var defaultProp TypeHint +var tType Ty -// var intCrossInt TypeApp -// var ratCrossRat TypeApp -// var realCrossReal TypeApp +var tInt Ty +var tRat Ty +var tReal Ty -var tType Ty +var tIndividual Ty +var tProp Ty func initTPTPNativeTypes() { tType = MkTyConst("$tType") - // FIXME: always register the equality type in the context. + + tInt = MkTyConst("$int") + tRat = MkTyConst("$rat") + tReal = MkTyConst("$real") + + tIndividual = MkTyConst("$i") + tProp = MkTyConst("$o") } func TType() Ty { return tType } +func TInt() Ty { + return tInt +} + +func TRat() Ty { + return tRat +} + +func TReal() Ty { + return tReal +} + +func TIndividual() Ty { + return tIndividual +} + +func TProp() Ty { + return tProp +} + func IsTType(ty Ty) bool { return ty.Equals(tType) } -// func InitTPTPArithmetic() { -// // Types -// tInt = MkTypeHint("$int") -// tRat = MkTypeHint("$rat") -// tReal = MkTypeHint("$real") - -// intCrossInt = MkTypeCross(tInt, tInt) -// ratCrossRat = MkTypeCross(tRat, tRat) -// realCrossReal = MkTypeCross(tReal, tReal) - -// // Schemes -// // 1 - Binary predicates -// recordBinaryProp("$less") -// recordBinaryProp("$lesseq") -// recordBinaryProp("$greater") -// recordBinaryProp("$greatereq") - -// // 2 - Binary input arguments -// recordBinaryInArgs("$sum") -// recordBinaryInArgs("$difference") -// recordBinaryInArgs("$product") -// recordBinaryInArgs("$quotient_e") -// recordBinaryInArgs("$quotient_t") -// recordBinaryInArgs("$quotient_f") -// recordBinaryInArgs("$remainder_e") -// recordBinaryInArgs("$remainder_t") -// recordBinaryInArgs("$remainder_f") - -// // 3 - $quotient -// SaveTypeScheme("$quotient", ratCrossRat, tRat) -// SaveTypeScheme("$quotient", realCrossReal, tReal) - -// // 4 - Unary input arguments -// recordUnaryInArgs("$uminus") -// recordUnaryInArgs("$floor") -// recordUnaryInArgs("$ceiling") -// recordUnaryInArgs("$truncate") -// recordUnaryInArgs("$round") - -// // 5 - Unary predicates -// recordUnaryProp("$is_int") -// recordUnaryProp("$is_rat") - -// // 6 - Conversion -// recordConversion("$to_int", tInt) -// recordConversion("$to_rat", tRat) -// recordConversion("$to_real", tReal) -// } - -// func recordBinaryProp(name string) { -// SaveTypeScheme(name, intCrossInt, defaultProp) -// SaveTypeScheme(name, ratCrossRat, defaultProp) -// SaveTypeScheme(name, realCrossReal, defaultProp) -// } - -// func recordBinaryInArgs(name string) { -// SaveTypeScheme(name, intCrossInt, tInt) -// SaveTypeScheme(name, ratCrossRat, tRat) -// SaveTypeScheme(name, realCrossReal, tReal) -// } - -// func recordUnaryInArgs(name string) { -// SaveTypeScheme(name, tInt, tInt) -// SaveTypeScheme(name, tRat, tRat) -// SaveTypeScheme(name, tReal, tReal) -// } - -// func recordUnaryProp(name string) { -// SaveTypeScheme(name, tInt, defaultProp) -// SaveTypeScheme(name, tRat, defaultProp) -// SaveTypeScheme(name, tReal, defaultProp) -// } - -// func recordConversion(name string, out TypeApp) { -// SaveTypeScheme(name, tInt, out) -// SaveTypeScheme(name, tRat, out) -// SaveTypeScheme(name, tReal, out) -// } - -// func IsInt(tType TypeScheme) bool { return tType.Equals(tInt) } -// func IsRat(tType TypeScheme) bool { return tType.Equals(tRat) } -// func IsReal(tType TypeScheme) bool { return tType.Equals(tReal) } -// func DefaultType() TypeApp { return defaultType } -// func DefaultProp() TypeApp { return defaultProp } -// func DefaultFunType(len int) TypeScheme { return defaultAppType(len, defaultType) } -// func DefaultPropType(len int) TypeScheme { return defaultAppType(len, defaultProp) } - -// func defaultAppType(len int, out TypeApp) TypeScheme { -// if len == 0 { -// return Glob.To[TypeScheme](out) -// } else if len == 1 { -// return MkTypeArrow(defaultType, out) -// } else { -// ts := []TypeApp{} -// for i := 0; i < len; i++ { -// ts = append(ts, defaultType) -// } -// return MkTypeArrow(MkTypeCross(ts...), out) -// } -// } +func DefinedTPTPTypes() Lib.List[TyConstr] { + return Lib.ListMap( + Lib.MkListV(tType, tInt, tRat, tReal, tIndividual, tProp), + func(ty Ty) TyConstr { return ty.(TyConstr) }, + ) +} diff --git a/src/AST/ty-syntax.go b/src/AST/ty-syntax.go index 950d4847..f2b374a7 100644 --- a/src/AST/ty-syntax.go +++ b/src/AST/ty-syntax.go @@ -48,6 +48,7 @@ type Ty interface { ToString() string Equals(any) bool Copy() Ty + ReplaceTyVar(TyBound, Ty) Ty } // Internal, shouldn't get out so no upper case @@ -65,6 +66,8 @@ func (v tyVar) Equals(oth any) bool { } func (v tyVar) Copy() Ty { return tyVar{v.repr} } +func (v tyVar) ReplaceTyVar(TyBound, Ty) Ty { return v } + type TyBound struct { name string index int @@ -78,7 +81,15 @@ func (b TyBound) Equals(oth any) bool { } return false } -func (b TyBound) Copy() Ty { return TyBound{b.name, b.index} } +func (b TyBound) Copy() Ty { return TyBound{b.name, b.index} } +func (b TyBound) GetName() string { return b.name } + +func (b TyBound) ReplaceTyVar(old TyBound, new Ty) Ty { + if b.Equals(old) { + return new + } + return b +} type TyMeta struct { name string @@ -94,6 +105,8 @@ func (m TyMeta) Equals(oth any) bool { } func (m TyMeta) Copy() Ty { return TyMeta{m.name} } +func (m TyMeta) ReplaceTyVar(TyBound, Ty) Ty { return m } + // Type constructors, e.g., list, option, ... // Include constants, e.g., $i, $o, ... type TyConstr struct { @@ -122,6 +135,21 @@ func (c TyConstr) Copy() Ty { return TyConstr{c.symbol, Lib.ListCpy(c.args)} } +func (c TyConstr) Symbol() string { + return c.symbol +} + +func (c TyConstr) Args() Lib.List[Ty] { + return c.args +} + +func (c TyConstr) ReplaceTyVar(old TyBound, new Ty) Ty { + return TyConstr{ + c.symbol, + Lib.ListMap(c.args, func(t Ty) Ty { return t.ReplaceTyVar(old, new) }), + } +} + type TyProd struct { args Lib.List[Ty] } @@ -147,6 +175,12 @@ func (p TyProd) Copy() Ty { return TyProd{Lib.ListCpy(p.args)} } +func (p TyProd) ReplaceTyVar(old TyBound, new Ty) Ty { + return TyProd{ + Lib.ListMap(p.args, func(t Ty) Ty { return t.ReplaceTyVar(old, new) }), + } +} + type TyFunc struct { in, out Ty } @@ -166,6 +200,10 @@ func (f TyFunc) Copy() Ty { return TyFunc{f.in.Copy(), f.out.Copy()} } +func (f TyFunc) ReplaceTyVar(old TyBound, new Ty) Ty { + return TyFunc{f.in.ReplaceTyVar(old, new), f.out.ReplaceTyVar(old, new)} +} + type TyPi struct { vars Lib.List[string] ty Ty @@ -188,6 +226,10 @@ func (p TyPi) Copy() Ty { return TyPi{p.vars.Copy(func(x string) string { return x }), p.ty.Copy()} } +func (p TyPi) ReplaceTyVar(old TyBound, new Ty) Ty { + return TyPi{p.vars, p.ty.ReplaceTyVar(old, new)} +} + // Makers func MkTyVar(repr string) Ty { @@ -240,29 +282,28 @@ func MakerTyBV(name string) Ty { } func InstantiateTy(ty Ty, instance Lib.List[Ty]) Ty { + fatal := func(expected int) { + Glob.Fatal( + "Ty.Instantiate", + fmt.Sprintf( + "On instantiation of %s: given instance %s does not have the right number of arguments (expected %d)", + ty.ToString(), + Lib.ListToString(instance, ", ", "(empty instance)"), + expected, + ), + ) + } + switch rty := ty.(type) { - case TyFunc: + case TyConstr, TyFunc: if !instance.Empty() { - Glob.Anomaly( - "Ty.Instantiate", - fmt.Sprintf( - "On instantiation of %s: given instance %s has arguments when it shouldn't", - ty.ToString(), - Lib.ListToString(instance, ", ", "(empty instance)"), - ), - ) + fatal(0) } + return ty case TyPi: if instance.Len() != rty.vars.Len() { - Glob.Anomaly( - "Ty.Instantiate", - fmt.Sprintf( - "On instantiation of %s: given instance %s does not have the right number of arguments", - ty.ToString(), - Lib.ListToString(instance, ", ", "(empty instance)"), - ), - ) + fatal(rty.vars.Len()) } instanceMap := make(map[string]Ty) @@ -320,8 +361,12 @@ func instantiateTyRec(ty, source Ty, instance map[string]Ty) Ty { func GetArgsTy(ty Ty) Lib.List[Ty] { switch rty := ty.(type) { + case TyConstr: + return Lib.NewList[Ty]() case TyFunc: switch nty := rty.in.(type) { + case TyBound, TyConstr: + return Lib.MkListV(rty.in) case TyProd: return nty.args } @@ -332,3 +377,18 @@ func GetArgsTy(ty Ty) Lib.List[Ty] { ) return Lib.NewList[Ty]() } + +func GetOutTy(ty Ty) Ty { + switch rty := ty.(type) { + case TyConstr: + return tType + case TyFunc: + return rty.out + } + + Glob.Anomaly( + "Ty.GetOutTy", + fmt.Sprintf("Tried to extract out type of a non-functional type %s", ty.ToString()), + ) + return nil +} diff --git a/src/AST/typed-vars.go b/src/AST/typed-vars.go index f9514fb4..598488f9 100644 --- a/src/AST/typed-vars.go +++ b/src/AST/typed-vars.go @@ -59,7 +59,7 @@ func (v TypedVar) Equals(oth any) bool { } func (v TypedVar) ToString() string { - return fmt.Sprintf("%s_%d : %s", v.name, v.index, v.ty.ToString()) + return fmt.Sprintf("%s : %s", v.name, v.ty.ToString()) } func (v TypedVar) GetName() string { @@ -82,6 +82,10 @@ func (v TypedVar) ToTyBoundVar() TyBound { return MkTyBV(v.name, v.index).(TyBound) } +func (v TypedVar) ReplaceTyVar(old TyBound, new Ty) TypedVar { + return TypedVar{v.name, v.index, v.ty.ReplaceTyVar(old, new)} +} + func MkTypedVar(name string, index int, ty Ty) TypedVar { return TypedVar{name, index, ty} } diff --git a/src/Engine/pretyper.go b/src/Engine/pretyper.go index 1a1b82c6..16386a83 100644 --- a/src/Engine/pretyper.go +++ b/src/Engine/pretyper.go @@ -38,6 +38,7 @@ package Engine import ( "fmt" + "github.com/GoelandProver/Goeland/AST" "github.com/GoelandProver/Goeland/Glob" "github.com/GoelandProver/Goeland/Lib" @@ -50,10 +51,15 @@ var defaultType = Parser.MkTypeConst("$i").(Parser.PType) func pretype(con Context, terms []Parser.PTerm) []Lib.Pair[Parser.PTerm, Parser.PType] { tys := []Lib.Pair[Parser.PTerm, Parser.PType]{} for _, term := range terms { + debug(Lib.MkLazy(func() string { return fmt.Sprintf("pretyping %s", term.ToString()) })) lookupName := "" + args := []Parser.PTerm{} + defined_type := Lib.MkNone[Parser.PType]() switch t := term.(type) { case Parser.PFun: lookupName = t.Symbol() + args = t.Args() + defined_type = t.DefinedType() case Parser.PVar: lookupName = t.Name() } @@ -62,21 +68,38 @@ func pretype(con Context, terms []Parser.PTerm) []Lib.Pair[Parser.PTerm, Parser. switch ty := lookupInContext(con, lookupName).(type) { case Lib.Some[Parser.PType]: - tys = append(tys, Lib.MkPair(term, ty.Val)) + real_ty := instantiateType(ty.Val, lookupName, args) + debug_low_level(Lib.MkLazy(func() string { + return fmt.Sprintf("Term in context with type %s", real_ty.ToString()) + })) + + tys = append(tys, Lib.MkPair(term, real_ty)) typed = true + case Lib.None[Parser.PType]: + debug_low_level(Lib.MkLazy(func() string { return "Term not in context, is it defined?" })) + switch oty := defined_type.(type) { + case Lib.Some[Parser.PTypeFun]: + debug_low_level(Lib.MkLazy(func() string { + return fmt.Sprintf("%s has defined type %s", lookupName, oty.Val.ToString()) + })) + tys = append(tys, Lib.MkPair(term, Parser.PType(oty.Val))) + typed = true + } } if !typed { + debug_low_level(Lib.MkLazy(func() string { return "Term is not a defined term, assigning default type" })) tys = append(tys, Lib.MkPair(term, defaultType)) } + } return tys } func lookupInContext(con Context, name string) Lib.Option[Parser.PType] { - for _, p := range con { - if p.Fst == name { - return Lib.MkSome(p.Snd) + for i := len(con) - 1; i >= 0; i-- { + if con[i].Fst == name { + return Lib.MkSome(con[i].Snd) } } return Lib.MkNone[Parser.PType]() @@ -86,13 +109,6 @@ func isTyConstr(pty Parser.PType) bool { switch ty := pty.(type) { case Parser.PTypeFun: return ty.Symbol() == "$tType" - case Parser.PTypeBin: - switch ty.Operator() { - case Parser.PTypeMap: - return isTyConstr(ty.Right()) - } - case Parser.PTypeQuant: - return isTyConstr(ty.Ty()) } return false } @@ -151,3 +167,78 @@ func pretypeVars(vars []Lib.Pair[string, Parser.PAtomicType]) Lib.List[AST.Typed } return res } + +func instantiateType(ty Parser.PType, lookupName string, args []Parser.PTerm) Parser.PType { + switch nty := ty.(type) { + case Parser.PTypeVar, Parser.PTypeFun: + if len(args) > 0 { + Glob.Fatal( + elab_label, + fmt.Sprintf("Expected constant, got %s which is a function", lookupName), + ) + } + + return nty + + case Parser.PTypeBin: + if nty.Operator() != Parser.PTypeMap { + Glob.Fatal( + elab_label, + fmt.Sprintf("Expected map type, got %s", nty.ToString()), + ) + } + + return nty.Right() + + case Parser.PTypeQuant: + type_args := map[string]Parser.PType{} + for i, v := range nty.Vars() { + type_args[v.Fst] = parserTermToType(args[i]) + } + return instantiateRec(nty.Ty(), type_args) + } + Glob.Fatal( + elab_label, + fmt.Sprintf("Expected functional type, got %s", ty.ToString()), + ) + return ty +} + +func instantiateRec(ty Parser.PType, instance map[string]Parser.PType) Parser.PType { + switch nty := ty.(type) { + case Parser.PTypeVar: + if val, ok := instance[nty.Name()]; ok { + return val + } + Glob.Fatal( + elab_label, + fmt.Sprintf("Type variable %s not found in the instance", ty.ToString()), + ) + return ty + + case Parser.PTypeFun: + args := []Parser.PAtomicType{} + for _, arg := range nty.Args() { + args = append(args, instantiateRec(arg.(Parser.PType), instance).(Parser.PAtomicType)) + } + + return Parser.MkPTypeFun(nty.Symbol(), args) + + case Parser.PTypeBin: + new_left := instantiateRec(nty.Left(), instance) + new_right := instantiateRec(nty.Right(), instance) + switch nty.Operator() { + case Parser.PTypeProd: + return Parser.MkTypeProd(new_left, new_right) + + case Parser.PTypeMap: + return new_right + } + } + + Glob.Anomaly( + elab_label, + fmt.Sprintf("Unexpected type on instantiation: %s", ty.ToString()), + ) + return ty +} diff --git a/src/Engine/syntax-translation.go b/src/Engine/syntax-translation.go index 92b258d8..62cd659a 100644 --- a/src/Engine/syntax-translation.go +++ b/src/Engine/syntax-translation.go @@ -47,14 +47,20 @@ import ( "github.com/GoelandProver/Goeland/Typing" ) -type Context []Lib.Pair[string, Parser.PType] - var elab_label string = "Elab" var parsing_label string = "Parsing" +var debug Glob.Debugger +var debug_low_level Glob.Debugger + +func InitDebugger() { + debug = Glob.CreateDebugger("elab") + debug_low_level = Glob.CreateDebugger("elab-low") +} + func ToInternalSyntax(parser_statements []Parser.PStatement) (statements []Core.Statement, is_typed bool) { is_typed = false - con := Context{} + con := initialContext() for _, statement := range parser_statements { new_con, stmt, is_typed_stmt := elaborateParsingStatement(con, statement) statements = append(statements, stmt) @@ -74,18 +80,28 @@ func elaborateParsingStatement( switch f := statement.Form().(type) { case Lib.Some[Parser.PForm]: - form, is_typed_form := elaborateParsingForm(con, f.Val) + debug(Lib.MkLazy(func() string { return fmt.Sprintf("Elaborating formula %s", f.Val.ToString()) })) + + new_con, form, is_typed_form := elaborateParsingForm(con, f.Val) core_statement = Core.MakeFormStatement( statement.Name(), statement_role, form, ) is_typed = is_typed || is_typed_form + con = new_con case Lib.None[Parser.PForm]: switch ty := statement.TypedConst().(type) { case Lib.Some[Lib.Pair[string, Parser.PType]]: + debug(Lib.MkLazy(func() string { + return fmt.Sprintf( + "Elaborating type statement %s: %s", + ty.Val.Fst, + ty.Val.Snd.ToString()) + })) + con = append(con, ty.Val) core_statement = Core.MakeTypingStatement( statement.Name(), @@ -130,13 +146,13 @@ func elaborateRole(parsing_role Parser.PFormulaRole, stmt Parser.PStatement) Cor return Core.Unknown } -func elaborateParsingForm(con Context, f Parser.PForm) (AST.Form, bool) { +func elaborateParsingForm(con Context, f Parser.PForm) (Context, AST.Form, bool) { return elaborateForm(con, f, f) } // The [source_form] argument is here for error printing purposes. -func elaborateForm(con Context, f, source_form Parser.PForm) (AST.Form, bool) { - aux := func(t Parser.PTerm) (AST.Term, bool) { +func elaborateForm(con Context, f, source_form Parser.PForm) (Context, AST.Form, bool) { + aux := func(con Context, t Parser.PTerm) (Context, AST.Term, bool) { return elaborateParsingTerm(con, t) } @@ -145,24 +161,34 @@ func elaborateForm(con Context, f, source_form Parser.PForm) (AST.Form, bool) { case Parser.PConst: switch pform.PConstant { case Parser.PTop: - return AST.MakerTop(), false + return con, AST.MakerTop(), false case Parser.PBot: - return AST.MakerBot(), false + return con, AST.MakerBot(), false } case Parser.PPred: typed_arguments := pretype(con, pform.Args()) typed_args, term_args := splitTypes(typed_arguments) - args := Lib.MkList[AST.Term](term_args.Len()) is_typed := false + args := Lib.MkList[AST.Term](term_args.Len()) for i, trm := range term_args.GetSlice() { - arg, b := aux(trm) + new_con, arg, b := aux(con, trm) + con = new_con is_typed = is_typed || b args.Upd(i, arg) } - return AST.MakerPred( + // Special cases: defined types get elaborated to manage ad-hoc polymorphism + if isDefined(pform.Symbol()) { + tys := Lib.ListMap(Lib.MkListV(typed_arguments[typed_args.Len():]...), + func(p Lib.Pair[Parser.PTerm, Parser.PType]) Parser.PType { return p.Snd }) + typed_args = elaborateDefinedFunctionals(con, pform.Symbol(), tys, args) + } else { + is_typed = !typed_args.Empty() + } + + return con, AST.MakerPred( AST.MakerId(pform.Symbol()), Lib.ListMap( typed_args, @@ -170,13 +196,13 @@ func elaborateForm(con Context, f, source_form Parser.PForm) (AST.Form, bool) { return elaborateType(pty, pty, false) }), args, - ), is_typed || !typed_args.Empty() + ), is_typed case Parser.PUnary: switch pform.PUnaryOp { case Parser.PUnaryNeg: - nf, b := elaborateForm(con, pform.PForm, source_form) - return AST.MakerNot(nf), b + new_con, nf, b := elaborateForm(con, pform.PForm, source_form) + return new_con, AST.MakerNot(nf), b } case Parser.PBin: @@ -186,13 +212,13 @@ func elaborateForm(con Context, f, source_form Parser.PForm) (AST.Form, bool) { case Parser.PBinaryAnd: return maybeFlattenAnd(con, pform, source_form) case Parser.PBinaryImp: - lft, b1 := elaborateForm(con, pform.Left(), source_form) - rgt, b2 := elaborateForm(con, pform.Right(), source_form) - return AST.MakerImp(lft, rgt), b1 || b2 + con1, lft, b1 := elaborateForm(con, pform.Left(), source_form) + new_con, rgt, b2 := elaborateForm(con1, pform.Right(), source_form) + return new_con, AST.MakerImp(lft, rgt), b1 || b2 case Parser.PBinaryEqu: - lft, b1 := elaborateForm(con, pform.Left(), source_form) - rgt, b2 := elaborateForm(con, pform.Right(), source_form) - return AST.MakerEqu(lft, rgt), b1 || b2 + con1, lft, b1 := elaborateForm(con, pform.Left(), source_form) + new_con, rgt, b2 := elaborateForm(con1, pform.Right(), source_form) + return new_con, AST.MakerEqu(lft, rgt), b1 || b2 } case Parser.PQuant: @@ -205,11 +231,12 @@ func elaborateForm(con Context, f, source_form Parser.PForm) (AST.Form, bool) { return Lib.MkPair(p.Fst, p.Snd.(Parser.PType)) }, ) - form, b := elaborateForm(append(con, actualVars.GetSlice()...), pform.PForm, source_form) + new_con, form, b := elaborateForm(append(con, actualVars.GetSlice()...), pform.PForm, source_form) if !vars.Empty() { form = AST.MakerAll(vars, form) } - return form, b + return new_con, form, b + case Parser.PQuantEx: if vars.Any(func(v AST.TypedVar) bool { return AST.IsTType(v.GetTy()) }) { Glob.Anomaly( @@ -223,21 +250,21 @@ func elaborateForm(con Context, f, source_form Parser.PForm) (AST.Form, bool) { return Lib.MkPair(p.Fst, p.Snd.(Parser.PType)) }, ) - form, b := elaborateForm(append(con, actualVars.GetSlice()...), pform.PForm, source_form) + new_con, form, b := elaborateForm(append(con, actualVars.GetSlice()...), pform.PForm, source_form) if !vars.Empty() { form = AST.MakerEx(vars, form) } - return form, b + return new_con, form, b } } Glob.Anomaly( elab_label, "Parsed formula "+source_form.ToString()+" does not correspond to any internal formula", ) - return nil, false + return con, nil, false } -func maybeFlattenOr(con Context, f Parser.PBin, source_form Parser.PForm) (AST.Form, bool) { +func maybeFlattenOr(con Context, f Parser.PBin, source_form Parser.PForm) (Context, AST.Form, bool) { return maybeFlattenBin( con, f, source_form, func(ls Lib.List[AST.Form]) AST.Form { return AST.MakerOr(ls) }, @@ -245,7 +272,7 @@ func maybeFlattenOr(con Context, f Parser.PBin, source_form Parser.PForm) (AST.F ) } -func maybeFlattenAnd(con Context, f Parser.PBin, source_form Parser.PForm) (AST.Form, bool) { +func maybeFlattenAnd(con Context, f Parser.PBin, source_form Parser.PForm) (Context, AST.Form, bool) { return maybeFlattenBin( con, f, source_form, func(ls Lib.List[AST.Form]) AST.Form { return AST.MakerAnd(ls) }, @@ -259,22 +286,23 @@ func maybeFlattenBin( source_form Parser.PForm, maker Lib.Func[Lib.List[AST.Form], AST.Form], op Parser.PBinOp, -) (AST.Form, bool) { +) (Context, AST.Form, bool) { if !Glob.Flatten() { - lft, b1 := elaborateForm(con, f.Left(), source_form) - rgt, b2 := elaborateForm(con, f.Right(), source_form) - return maker(Lib.MkListV(lft, rgt)), b1 || b2 + con1, lft, b1 := elaborateForm(con, f.Left(), source_form) + new_con, rgt, b2 := elaborateForm(con1, f.Right(), source_form) + return new_con, maker(Lib.MkListV(lft, rgt)), b1 || b2 } subforms := flatten(f, op) is_typed := false real_subforms := Lib.MkList[AST.Form](subforms.Len()) for i, subform := range subforms.GetSlice() { - real_subform, b := elaborateForm(con, subform, source_form) + new_con, real_subform, b := elaborateForm(con, subform, source_form) + con = new_con real_subforms.Upd(i, real_subform) is_typed = is_typed || b } - return maker(real_subforms), is_typed + return con, maker(real_subforms), is_typed } func flatten(f Parser.PForm, op Parser.PBinOp) Lib.List[Parser.PForm] { @@ -289,36 +317,46 @@ func flatten(f Parser.PForm, op Parser.PBinOp) Lib.List[Parser.PForm] { return Lib.MkListV(f) } -func elaborateParsingTerm(con Context, t Parser.PTerm) (AST.Term, bool) { +func elaborateParsingTerm(con Context, t Parser.PTerm) (Context, AST.Term, bool) { return elaborateTerm(con, t, t) } // The argument [source_term] is here for error printing purposes. -func elaborateTerm(con Context, t, source_term Parser.PTerm) (AST.Term, bool) { - aux := func(t Parser.PTerm) (AST.Term, bool) { +func elaborateTerm(con Context, t, source_term Parser.PTerm) (Context, AST.Term, bool) { + aux := func(con Context, t Parser.PTerm) (Context, AST.Term, bool) { return elaborateTerm(con, t, source_term) } switch pterm := t.(type) { case Parser.PVar: - return AST.MakerVar(pterm.Name()), false + return con, AST.MakerVar(pterm.Name()), false case Parser.PFun: typed_arguments := pretype(con, pterm.Args()) - ty_args, trm_args := splitTypes(typed_arguments) - args := Lib.MkList[AST.Term](trm_args.Len()) + typed_args, term_args := splitTypes(typed_arguments) is_typed := false - for i, trm := range trm_args.GetSlice() { - arg, b := aux(trm) + args := Lib.MkList[AST.Term](term_args.Len()) + for i, trm := range term_args.GetSlice() { + new_con, arg, b := aux(con, trm) + con = new_con is_typed = is_typed || b args.Upd(i, arg) } + // Special cases: defined types get elaborated to manage ad-hoc polymorphism + if isDefined(pterm.Symbol()) { + tys := Lib.ListMap(Lib.MkListV(typed_arguments[typed_args.Len():]...), + func(p Lib.Pair[Parser.PTerm, Parser.PType]) Parser.PType { return p.Snd }) + typed_args = elaborateDefinedFunctionals(con, pterm.Symbol(), tys, args) + } else { + is_typed = !typed_args.Empty() + } + fun := AST.MakerFun( AST.MakerId(pterm.Symbol()), Lib.ListMap( - ty_args, + typed_args, func(pty Parser.PType) AST.Ty { return elaborateType(pty, pty, false) }), @@ -326,17 +364,22 @@ func elaborateTerm(con Context, t, source_term Parser.PTerm) (AST.Term, bool) { ) switch oty := pterm.DefinedType().(type) { case Lib.Some[Parser.PTypeFun]: + debug(Lib.MkLazy(func() string { return fmt.Sprintf("%s is a defined function", pterm.Symbol()) })) + debug_low_level(Lib.MkLazy(func() string { + return fmt.Sprintf("%s has defined type %s", pterm.Symbol(), oty.Val.ToString()) + })) + con = append(con, Lib.MkPair(pterm.Symbol(), Parser.PType(oty.Val))) ty := elaborateType(oty.Val, oty.Val, false) Typing.AddToGlobalEnv(pterm.Symbol(), ty) } - return fun, is_typed || !ty_args.Empty() + return con, fun, is_typed || !typed_args.Empty() } Glob.Anomaly( elab_label, "Parsed term "+source_term.ToString()+" does not correspond to any internal term", ) - return nil, false + return con, nil, false } func elaborateParsingType(pty Lib.Pair[string, Parser.PType]) Core.TFFAtomTyping { @@ -369,14 +412,25 @@ func elaborateType(pty, source_type Parser.PType, from_top_level bool) AST.Ty { case Parser.PTypeBin: fail_if_forbidden := func(ty Parser.PType) { - Glob.Fatal( - parsing_label, - fmt.Sprintf( - "Non-atomic type (%s) found under the type %s", - ty.ToString(), - source_type.ToString(), - ), - ) + fatal := func() { + Glob.Fatal( + parsing_label, + fmt.Sprintf( + "Non-atomic type (%s) found under the type %s", + ty.ToString(), + source_type.ToString(), + ), + ) + } + + switch nty := ty.(type) { + case Parser.PTypeBin: + if nty.Operator() == Parser.PTypeMap { + fatal() + } + case Parser.PTypeQuant: + fatal() + } } fail_if_forbidden(ty.Left()) @@ -436,3 +490,100 @@ func flattenProd(ty AST.Ty) []AST.Ty { } return []AST.Ty{ty} } + +func elaborateDefinedFunctionals( + con Context, + name string, + ty_arguments Lib.List[Parser.PType], + arguments Lib.List[AST.Term], +) Lib.List[Parser.PType] { + debug(Lib.MkLazy(func() string { + return fmt.Sprintf("Elaborating defined functional %s(%s)", name, Lib.ListToString(arguments, ", ", "")) + })) + + // Invariant: call from isDefined, defined_length should be defined as well + if arguments.Len() != defined_length[name] { + Glob.Fatal( + elab_label, + fmt.Sprintf("%s expects %d arguments, got %d", name, defined_length[name], arguments.Len()), + ) + } + + ty_args := Lib.NewList[Parser.PType]() + tys := Lib.NewList[Parser.PType]() + for i, arg := range arguments.GetSlice() { + var ty Lib.Option[Parser.PType] + ty_args := Lib.NewList[Parser.PTerm]() + switch term := arg.(type) { + case AST.Fun: + ty = lookupInContext(con, term.GetName()) + for _, ty := range term.GetTyArgs().GetSlice() { + switch t := ty.(type) { + case AST.TyConstr: + ty_args.Append(Parser.MkFunConst(t.Symbol())) + case AST.TyBound: + ty_args.Append(Parser.MkVar(t.GetName())) + default: + Glob.Anomaly(elab_label, "Found non-constant type parameter in defined type") + } + } + case AST.Var: + ty = lookupInContext(con, term.GetName()) + default: + Glob.Anomaly(elab_label, "Parsed argument is neither a function nor a variable") + } + + switch rty := ty.(type) { + case Lib.Some[Parser.PType]: + tys.Append(instantiateType(rty.Val, arg.GetName(), ty_args.GetSlice())) + case Lib.None[Parser.PType]: + // This is not a defined, let's use the inferred type + tys.Append(ty_arguments.At(i)) + } + } + + // Take the first allowed argument and hope for the best (leave the rest for the typechecker) + elab_ty := Lib.MkNone[Parser.PType]() + for _, ty := range tys.GetSlice() { + if isAllowed(name, ty) { + elab_ty = Lib.MkSome(ty) + break + } + } + + switch ety := elab_ty.(type) { + case Lib.Some[Parser.PType]: + ty_args.Append(ety.Val) + case Lib.None[Parser.PType]: + switch allowed := allowed_elab[name].(type) { + case Lib.Some[Lib.List[Parser.PType]]: + Glob.Fatal( + elab_label, + fmt.Sprintf( + "%s expects arguments in {%s}, but found none with the right type", + name, Lib.ListToString(allowed.Val, ", ", ""), + )) + case Lib.None[Lib.List[Parser.PType]]: + Glob.Anomaly( + elab_label, + fmt.Sprintf("allowed_elab[%s] is None but term is not allowed", name), + ) + } + } + + // Special case: quotient of two integers + if name == "$quotient" { + if tys.At(0).Equals(Parser.MkTypeConst("$int")) { + ty_args.Append(Parser.MkTypeConst("$rat").(Parser.PType)) + } else { + ty_args.Append(ty_args.At(0)) + } + } + + debug(Lib.MkLazy(func() string { + return fmt.Sprintf("Defined functional elaborated to %s(%s ; %s)", + name, Lib.ListToString(ty_args, ", ", ""), Lib.ListToString(arguments, ", ", "")) + })) + + return ty_args +} diff --git a/src/Engine/tptp-defined-types.go b/src/Engine/tptp-defined-types.go new file mode 100644 index 00000000..8ddc3e90 --- /dev/null +++ b/src/Engine/tptp-defined-types.go @@ -0,0 +1,155 @@ +/** +* Copyright 2022 by the authors (see AUTHORS). +* +* Goéland is an automated theorem prover for first order logic. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +**/ + +/** + * This file returns an initial context (one augmented with TPTP defined types) +**/ + +package Engine + +import ( + "fmt" + "github.com/GoelandProver/Goeland/Lib" + "github.com/GoelandProver/Goeland/Parser" +) + +type Context []Lib.Pair[string, Parser.PType] + +var defined Lib.Set[Lib.String] +var defined_length map[string]int +var allowed_elab map[string]Lib.Option[Lib.List[Parser.PType]] // None: no restriction + +func initialContext() Context { + defined = Lib.EmptySet[Lib.String]() + defined_length = make(map[string]int) + allowed_elab = make(map[string]Lib.Option[Lib.List[Parser.PType]]) + + tType := Parser.MkTypeConst("$tType").(Parser.PType) + tInt := Parser.MkTypeConst("$int").(Parser.PType) + tRat := Parser.MkTypeConst("$rat").(Parser.PType) + tReal := Parser.MkTypeConst("$real").(Parser.PType) + tProp := Parser.MkTypeConst("$o").(Parser.PType) + + con := []Lib.Pair[string, Parser.PType]{ + Lib.MkPair("$tType", tType), + Lib.MkPair("$int", tType), + Lib.MkPair("$rat", tType), + Lib.MkPair("$real", tType), + Lib.MkPair("$i", tType), + Lib.MkPair("$o", tType), + } + + mkDefined := func(name string, length int, allowed Lib.Option[Lib.List[Parser.PType]], ty Parser.PType) { + defined = defined.Add(Lib.MkString(name)) + defined_length[name] = length + allowed_elab[name] = allowed + con = append(con, Lib.MkPair(name, ty)) + } + + tNumber := Parser.MkPTypeVar("number") + binPoly := func(out Parser.PType) Parser.PType { + return Parser.MkTypeAll( + []Lib.Pair[string, Parser.PAtomicType]{Lib.MkPair("number", tType.(Parser.PAtomicType))}, + Parser.MkTypeMap( + Parser.MkTypeProd(tNumber, tNumber), + out, + ), + ) + } + unPoly := func(out Parser.PType) Parser.PType { + return Parser.MkTypeAll( + []Lib.Pair[string, Parser.PAtomicType]{Lib.MkPair("number", tType.(Parser.PAtomicType))}, + Parser.MkTypeMap(tNumber, out), + ) + } + + mkDefined("$less", 2, Lib.MkSome(Lib.MkListV(tInt, tRat, tReal)), binPoly(tProp)) + mkDefined("$lesseq", 2, Lib.MkSome(Lib.MkListV(tInt, tRat, tReal)), binPoly(tProp)) + mkDefined("$greater", 2, Lib.MkSome(Lib.MkListV(tInt, tRat, tReal)), binPoly(tProp)) + mkDefined("$greatereq", 2, Lib.MkSome(Lib.MkListV(tInt, tRat, tReal)), binPoly(tProp)) + + mkDefined("$sum", 2, Lib.MkSome(Lib.MkListV(tInt, tRat, tReal)), binPoly(tNumber)) + mkDefined("$difference", 2, Lib.MkSome(Lib.MkListV(tInt, tRat, tReal)), binPoly(tNumber)) + mkDefined("$product", 2, Lib.MkSome(Lib.MkListV(tInt, tRat, tReal)), binPoly(tNumber)) + mkDefined("$quotient_e", 2, Lib.MkSome(Lib.MkListV(tInt, tRat, tReal)), binPoly(tNumber)) + mkDefined("$quotient_t", 2, Lib.MkSome(Lib.MkListV(tInt, tRat, tReal)), binPoly(tNumber)) + mkDefined("$quotient_f", 2, Lib.MkSome(Lib.MkListV(tInt, tRat, tReal)), binPoly(tNumber)) + mkDefined("$remainder_e", 2, Lib.MkSome(Lib.MkListV(tInt, tRat, tReal)), binPoly(tNumber)) + mkDefined("$remainder_t", 2, Lib.MkSome(Lib.MkListV(tInt, tRat, tReal)), binPoly(tNumber)) + mkDefined("$remainder_f", 2, Lib.MkSome(Lib.MkListV(tInt, tRat, tReal)), binPoly(tNumber)) + mkDefined("$quotient", 2, Lib.MkSome(Lib.MkListV(tRat, tReal)), Parser.MkTypeAll( + []Lib.Pair[string, Parser.PAtomicType]{ + Lib.MkPair("number", tType.(Parser.PAtomicType)), + Lib.MkPair("rat_or_real", tType.(Parser.PAtomicType)), + }, + Parser.MkTypeMap( + Parser.MkTypeProd(tNumber, tNumber), + Parser.MkPTypeVar("rat_or_real"), + ))) + + mkDefined("$uminus", 1, Lib.MkSome(Lib.MkListV(tInt, tRat, tReal)), unPoly(tNumber)) + mkDefined("$floor", 1, Lib.MkSome(Lib.MkListV(tInt, tRat, tReal)), unPoly(tNumber)) + mkDefined("$ceiling", 1, Lib.MkSome(Lib.MkListV(tInt, tRat, tReal)), unPoly(tNumber)) + mkDefined("$truncate", 1, Lib.MkSome(Lib.MkListV(tInt, tRat, tReal)), unPoly(tNumber)) + mkDefined("$round", 1, Lib.MkSome(Lib.MkListV(tInt, tRat, tReal)), unPoly(tNumber)) + + mkDefined("$is_int", 1, Lib.MkSome(Lib.MkListV(tInt, tRat, tReal)), unPoly(tProp)) + mkDefined("$is_rat", 1, Lib.MkSome(Lib.MkListV(tInt, tRat, tReal)), unPoly(tProp)) + + mkDefined("$to_int", 1, Lib.MkSome(Lib.MkListV(tInt, tRat, tReal)), unPoly(tInt)) + mkDefined("$to_rat", 1, Lib.MkSome(Lib.MkListV(tInt, tRat, tReal)), unPoly(tRat)) + mkDefined("$to_real", 1, Lib.MkSome(Lib.MkListV(tInt, tRat, tReal)), unPoly(tReal)) + + mkDefined(Parser.PEqSymbol, 2, Lib.MkNone[Parser.PType](), binPoly(tProp)) + + debug_low_level(Lib.MkLazy(func() string { + str := "Defined symbols:" + for _, s := range defined.Elements().GetSlice() { + str += fmt.Sprintf("\n- %s with %d arguments", s, defined_length[string(s)]) + } + return str + })) + + return con +} + +func isDefined(name string) bool { + return defined.Contains(Lib.MkString(name)) +} + +func isAllowed(name string, ty Parser.PType) bool { + switch allowed := allowed_elab[name].(type) { + case Lib.Some[Lib.List[Parser.PType]]: + return Lib.ListMem(ty, allowed.Val) + } + return true +} diff --git a/src/Lib/par.go b/src/Lib/par.go new file mode 100644 index 00000000..21e1b5df --- /dev/null +++ b/src/Lib/par.go @@ -0,0 +1,86 @@ +/** +* Copyright 2022 by the authors (see AUTHORS). +* +* Goéland is an automated theorem prover for first order logic. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +**/ + +/** + * This file provides a generic interface to launch goroutines on functions, + * collect their result and compute a final value. + * The computation of the final value is done incrementally at the answer of each child, + * consequently, the function taking care of reconciliating the output of two children + * should be associative, commutative, and have a neutral. + **/ + +package Lib + +import ( + "fmt" + "reflect" +) + +func GenericParallel[T any]( + calls []func(chan T), + reconciliation func(T, T) T, + neutral T, +) (T, error) { + channels := make([](chan T), len(calls)) + for i, call := range calls { + call_chan := make(chan T) + channels[i] = call_chan + go call(call_chan) + } + return genericSelect(channels, reconciliation, neutral) +} + +func genericSelect[T any]( + channels [](chan T), + reconciliation func(T, T) T, + neutral T, +) (T, error) { + remaining := len(channels) + res := neutral + cases := make([]reflect.SelectCase, len(channels)) + for i, channel := range channels { + cases[i] = reflect.SelectCase{Dir: reflect.SelectRecv, Chan: reflect.ValueOf(channel)} + } + + for remaining > 0 { + _, value, _ := reflect.Select(cases) + remaining-- + + if v, ok := value.Interface().(T); ok { + res = reconciliation(res, v) + } else { + return neutral, fmt.Errorf("Error in Lib.Par: channel has not answered a value of the right type.") + } + } + + return res, nil +} diff --git a/src/Lib/string.go b/src/Lib/string.go index c84d5674..05c00449 100644 --- a/src/Lib/string.go +++ b/src/Lib/string.go @@ -37,24 +37,22 @@ package Lib -type String struct { - value string -} +type String string func (s String) Equals(oth any) bool { if str, ok := oth.(String); ok { - return s.value == str.value + return s == str } return false } func (s String) Less(oth any) bool { if str, ok := oth.(String); ok { - return s.value < str.value + return s < str } return false } func MkString(s string) String { - return String{s} + return String(s) } diff --git a/src/Mods/equality/bse/equality_problem_list.go b/src/Mods/equality/bse/equality_problem_list.go index a6b6479d..4491dff3 100644 --- a/src/Mods/equality/bse/equality_problem_list.go +++ b/src/Mods/equality/bse/equality_problem_list.go @@ -45,7 +45,6 @@ import ( "strings" "github.com/GoelandProver/Goeland/AST" - "github.com/GoelandProver/Goeland/Glob" "github.com/GoelandProver/Goeland/Lib" "github.com/GoelandProver/Goeland/Typing" "github.com/GoelandProver/Goeland/Unif" @@ -210,17 +209,15 @@ func buildEqualityProblemMultiListFromPredList(pred AST.Pred, tn Unif.DataStruct predId := pred.GetID() metas := Lib.NewList[AST.Meta]() - var ty AST.Ty + tys := Lib.NewList[AST.Ty]() switch rty := Typing.QueryEnvInstance(predId.GetName(), pred.GetTyArgs()).(type) { case Lib.Some[AST.Ty]: - ty = rty.Val + tys = AST.GetArgsTy(rty.Val) case Lib.None[AST.Ty]: - Glob.Anomaly( - "Equality.Build", - fmt.Sprintf("Type of predicate %s not found", pred.ToString()), - ) + for range pred.GetArgs().GetSlice() { + tys.Append(AST.TIndividual()) + } } - tys := AST.GetArgsTy(ty) for i, arg := range pred.GetArgs().GetSlice() { metas = Lib.ListAdd(metas, AST.MakerMeta("METAEQ_"+arg.ToString(), -1, tys.At(i))) diff --git a/src/Parser/pprinter.go b/src/Parser/pprinter.go index b8233333..c9318312 100644 --- a/src/Parser/pprinter.go +++ b/src/Parser/pprinter.go @@ -40,27 +40,27 @@ import ( ) func (t PVar) ToString() string { - return fmt.Sprintf("Var{%s}", t.name) + return fmt.Sprintf("Var(%s)", t.name) } func (f PFun) ToString() string { args := Lib.MkListV(f.arguments...) - return fmt.Sprintf("Fun{%s, %s}", f.symbol, args.ToString(PTerm.ToString, ", ", "[]")) + return fmt.Sprintf("%s(%s)", f.symbol, args.ToString(PTerm.ToString, ", ", "")) } func (c PConst) ToString() string { switch c.PConstant { case PTop: - return "Const{$true}" + return "$true" case PBot: - return "Const{$false}" + return "$false" } - return "Const{$unknown}" + return "Const{unknown}" } func (p PPred) ToString() string { args := Lib.MkListV(p.arguments...) - return fmt.Sprintf("Pred{%s, %s}", p.symbol, args.ToString(PTerm.ToString, ", ", "[]")) + return fmt.Sprintf("%s(%s)", p.symbol, args.ToString(PTerm.ToString, ", ", "")) } func (u PUnary) ToString() string { @@ -69,37 +69,37 @@ func (u PUnary) ToString() string { case PUnaryNeg: prefix = "Neg" } - return fmt.Sprintf("%s{%s}", prefix, u.PForm.ToString()) + return fmt.Sprintf("%s(%s)", prefix, u.PForm.ToString()) } func (b PBin) ToString() string { - prefix := "" + infix := "" switch b.operator { case PBinaryAnd: - prefix = "And" + infix = "&" case PBinaryOr: - prefix = "Or" + infix = "|" case PBinaryImp: - prefix = "Imp" + infix = "=>" case PBinaryEqu: - prefix = "Equ" + infix = "<=>" } - return fmt.Sprintf("%s{%s, %s}", prefix, b.left.ToString(), b.right.ToString()) + return fmt.Sprintf("(%s) %s (%s)", b.left.ToString(), infix, b.right.ToString()) } func (q PQuant) ToString() string { prefix := "" switch q.PQuantifier { case PQuantAll: - prefix = "All" + prefix = "!" case PQuantEx: - prefix = "Ex" + prefix = "?" } vars := Lib.MkListV(q.vars...) pairStr := func(p Lib.Pair[string, PAtomicType]) string { return "(" + p.Fst + ": " + p.Snd.(PType).ToString() + ")" } - return fmt.Sprintf("%s{%s, %s}", prefix, vars.ToString(pairStr, ", ", ""), q.PForm.ToString()) + return fmt.Sprintf("%s [%s]: (%s)", prefix, vars.ToString(pairStr, ", ", ""), q.PForm.ToString()) } func (v PTypeVar) ToString() string { @@ -140,7 +140,7 @@ func (q PTypeQuant) ToString() string { pairStr := func(p Lib.Pair[string, PAtomicType]) string { return "(" + p.Fst + ": " + p.Snd.(PType).ToString() + ")" } - return fmt.Sprintf("%s[%s]: (%s)", prefix, vars.ToString(pairStr, ", ", ""), q.t.ToString()) + return fmt.Sprintf("%s [%s]: (%s)", prefix, vars.ToString(pairStr, ", ", ""), q.t.ToString()) } func (stmt PStatement) ToString() string { diff --git a/src/Parser/psyntax.go b/src/Parser/psyntax.go index 8fd2dde8..24c4bf1c 100644 --- a/src/Parser/psyntax.go +++ b/src/Parser/psyntax.go @@ -51,6 +51,7 @@ type PAtomicType interface { type PType interface { isPType() ToString() string + Equals(any) bool } type PTypeVar struct { @@ -59,6 +60,12 @@ type PTypeVar struct { func MkPTypeVar(name string) PType { return PTypeVar{name} } func (v PTypeVar) Name() string { return v.name } +func (v PTypeVar) Equals(other any) bool { + if oth, ok := other.(PTypeVar); ok { + return oth.name == v.name + } + return false +} type PTypeFun struct { symbol string @@ -69,7 +76,20 @@ func MkPTypeFun(symbol string, args []PAtomicType) PType { return PTypeFun{symbo func (f PTypeFun) Symbol() string { return f.symbol } func (f PTypeFun) Args() []PAtomicType { return f.arguments } - +func (f PTypeFun) Equals(other any) bool { + if oth, ok := other.(PTypeFun); ok { + if len(f.arguments) != len(oth.arguments) { + return false + } + for i := range f.arguments { + if !f.arguments[i].(PType).Equals(oth.arguments[i]) { + return false + } + } + return oth.symbol == f.symbol + } + return false +} func (PTypeVar) isPAtomicType() {} func (PTypeVar) isPType() {} func (PTypeFun) isPAtomicType() {} @@ -100,6 +120,12 @@ type PTypeBin struct { func (b PTypeBin) Operator() PTypeBinOp { return b.op } func (b PTypeBin) Left() PType { return b.left } func (b PTypeBin) Right() PType { return b.right } +func (b PTypeBin) Equals(other any) bool { + if oth, ok := other.(PTypeBin); ok { + return oth.op == b.op && oth.left.Equals(b.left) && oth.right.Equals(b.right) + } + return false +} type PTypeQuantifier int @@ -116,7 +142,21 @@ type PTypeQuant struct { func (q PTypeQuant) Quant() PTypeQuantifier { return q.quant } func (q PTypeQuant) Vars() []Lib.Pair[string, PAtomicType] { return q.vars } func (q PTypeQuant) Ty() PType { return q.t } - +func (q PTypeQuant) Equals(other any) bool { + if oth, ok := other.(PTypeQuant); ok { + if len(oth.vars) != len(q.vars) { + return false + } + for i := range q.vars { + if q.vars[i].Fst != oth.vars[i].Fst || + !q.vars[i].Snd.(PType).Equals(oth.vars[i].Snd) { + return false + } + } + return oth.quant == q.quant && oth.t.Equals(q.t) + } + return false +} func (PTypeBin) isPType() {} func (PTypeQuant) isPType() {} @@ -156,6 +196,10 @@ type PVar struct { func (v PVar) Name() string { return v.name } +func MkVar(name string) PTerm { + return PVar{name} +} + func (PFun) isPTerm() {} func (PVar) isPTerm() {} diff --git a/src/Typing/env-and-context.go b/src/Typing/env-and-context.go index e544f6c4..2a61b6d6 100644 --- a/src/Typing/env-and-context.go +++ b/src/Typing/env-and-context.go @@ -40,6 +40,7 @@ package Typing import ( "sync" + "fmt" "github.com/GoelandProver/Goeland/AST" "github.com/GoelandProver/Goeland/Lib" ) @@ -85,6 +86,20 @@ func (con Con) contains(name string, ty AST.Ty) bool { return con.defs.Contains(definedType{name, ty}) } +func (con Con) addTypedVars(typed_vars Lib.List[AST.TypedVar]) Con { + for _, tv := range typed_vars.GetSlice() { + con = con.add(tv.GetName(), tv.GetTy()) + } + return con +} + +func (con Con) toString() string { + to_string := func(def definedType) string { + return fmt.Sprintf("%s: %s", def.name, def.ty.ToString()) + } + return con.defs.Elements().ToString(to_string, ", ", "{}") +} + // We could use [Con] to do environments, but as we need to query by name it's faster to use a map. type Env struct { con map[string]AST.Ty diff --git a/src/Typing/init.go b/src/Typing/init.go index f145b260..6411a329 100644 --- a/src/Typing/init.go +++ b/src/Typing/init.go @@ -38,11 +38,122 @@ package Typing import ( "github.com/GoelandProver/Goeland/AST" + "github.com/GoelandProver/Goeland/Lib" "sync" ) var global_env Env +var ari_var string func Init() { global_env = Env{make(map[string]AST.Ty), sync.Mutex{}} + ari_var = "number" + + initTPTPNativeTypes() +} + +func initTPTPNativeTypes() { + for _, ty := range AST.DefinedTPTPTypes().GetSlice() { + AddToGlobalEnv(ty.Symbol(), AST.TType()) + } + + AddToGlobalEnv( + AST.Id_eq.GetName(), + AST.MkTyPi( + Lib.MkListV("α"), + AST.MkTyFunc(AST.MkTyProd(Lib.MkListV(AST.MkTyVar("α"), AST.MkTyVar("α"))), AST.TProp()), + ), + ) + + // 1 - Binary predicates + recordBinaryProp("$less") + recordBinaryProp("$lesseq") + recordBinaryProp("$greater") + recordBinaryProp("$greatereq") + + // 2 - Binary input arguments + recordBinaryInArgs("$sum") + recordBinaryInArgs("$difference") + recordBinaryInArgs("$product") + recordBinaryInArgs("$quotient_e") + recordBinaryInArgs("$quotient_t") + recordBinaryInArgs("$quotient_f") + recordBinaryInArgs("$remainder_e") + recordBinaryInArgs("$remainder_t") + recordBinaryInArgs("$remainder_f") + + // 3 - $quotient + AddToGlobalEnv("$quotient", + AST.MkTyPi( + Lib.MkListV(ari_var, "rat_or_real"), + AST.MkTyFunc( + AST.MkTyProd(Lib.MkListV(AST.MkTyVar(ari_var), AST.MkTyVar(ari_var))), + AST.MkTyVar("rat_or_real")), + )) + + // 4 - Unary input arguments + recordUnaryInArgs("$uminus") + recordUnaryInArgs("$floor") + recordUnaryInArgs("$ceiling") + recordUnaryInArgs("$truncate") + recordUnaryInArgs("$round") + + // 5 - Unary predicates + recordUnaryProp("$is_int") + recordUnaryProp("$is_rat") + + // 6 - Conversion + recordConversion("$to_int", AST.TInt()) + recordConversion("$to_rat", AST.TRat()) + recordConversion("$to_real", AST.TReal()) +} + +func recordBinaryProp(name string) { + AddToGlobalEnv( + name, + AST.MkTyPi( + Lib.MkListV(ari_var), + AST.MkTyFunc(AST.MkTyProd(Lib.MkListV(AST.MkTyVar(ari_var), AST.MkTyVar(ari_var))), AST.TProp()), + ), + ) +} + +func recordBinaryInArgs(name string) { + AddToGlobalEnv( + name, + AST.MkTyPi( + Lib.MkListV(ari_var), + AST.MkTyFunc(AST.MkTyProd(Lib.MkListV(AST.MkTyVar(ari_var), AST.MkTyVar(ari_var))), AST.MkTyVar(ari_var)), + ), + ) +} + +func recordUnaryInArgs(name string) { + AddToGlobalEnv( + name, + AST.MkTyPi( + Lib.MkListV(ari_var), + AST.MkTyFunc(AST.MkTyVar(ari_var), AST.MkTyVar(ari_var)), + ), + ) +} + +func recordUnaryProp(name string) { + AddToGlobalEnv( + name, + AST.MkTyPi( + Lib.MkListV(ari_var), + AST.MkTyFunc(AST.MkTyVar(ari_var), AST.TProp()), + ), + ) +} + +func recordConversion(name string, out AST.Ty) { + AddToGlobalEnv( + name, + AST.MkTyPi( + Lib.MkListV(ari_var), + AST.MkTyFunc(AST.MkTyVar(ari_var), out), + ), + ) } diff --git a/src/Typing/rules.go b/src/Typing/rules.go index 7b2f9768..098aab67 100644 --- a/src/Typing/rules.go +++ b/src/Typing/rules.go @@ -38,9 +38,257 @@ package Typing import ( + "fmt" "github.com/GoelandProver/Goeland/AST" + "github.com/GoelandProver/Goeland/Glob" + "github.com/GoelandProver/Goeland/Lib" ) +var label = "typing" + func TypeCheck(form AST.Form) bool { + return typecheckForm(emptyCon(), form) +} + +func typecheckForm(con Con, form AST.Form) bool { + switch f := form.(type) { + case AST.Bot, AST.Top: + return true + case AST.Pred: + return checkFunctional( + con, + f.GetID().GetName(), + f.GetTyArgs(), + f.GetArgs(), + Lib.MkLazy(func() string { return form.ToString() }), + ) + + case AST.Not, AST.And, AST.Or, AST.Imp, AST.Equ: + return typecheckRec( + con, + f.GetChildFormulas(), + Lib.NewList[Lib.Pair[AST.Term, AST.Ty]](), + Lib.NewList[AST.Ty](), + ) + + case AST.All: + return typecheckRec( + con.addTypedVars(f.GetVarList()), + Lib.MkListV(f.GetForm()), + Lib.NewList[Lib.Pair[AST.Term, AST.Ty]](), + Lib.NewList[AST.Ty](), + ) + + case AST.Ex: + return typecheckRec( + con.addTypedVars(f.GetVarList()), + Lib.MkListV(f.GetForm()), + Lib.NewList[Lib.Pair[AST.Term, AST.Ty]](), + Lib.NewList[AST.Ty](), + ) + } + + Glob.Anomaly( + label, + fmt.Sprintf("%s is not a known internal formula", form.ToString()), + ) + return false +} + +func typecheckTerm(con Con, term AST.Term, ty AST.Ty) bool { + switch t := term.(type) { + case AST.Var: + if !con.contains(t.GetName(), ty) { + Glob.Fatal( + label, + fmt.Sprintf( + "Variable %s is either not in the context or should not have type %s\nContext: %s", + t.GetName(), + ty.ToString(), + con.toString(), + )) + return false + } + + return typecheckRec( + con, + Lib.NewList[AST.Form](), + Lib.NewList[Lib.Pair[AST.Term, AST.Ty]](), + Lib.MkListV(ty), + ) + + case AST.Fun: + return checkFunctional( + con, + t.GetID().GetName(), + t.GetTyArgs(), + t.GetArgs(), + Lib.MkLazy(func() string { return t.ToString() }), + ) + } + + Glob.Anomaly( + label, + fmt.Sprintf("Only bound variables and functions should be typechecked, but found %s", term.ToString()), + ) return false } + +func typecheckType(con Con, ty AST.Ty) bool { + switch nty := ty.(type) { + case AST.TyBound: + if !con.contains(nty.GetName(), AST.TType()) { + Glob.PrintInfo("Context", con.toString()) + Glob.Fatal( + label, + fmt.Sprintf( + "Variable %s is either not in the context or is not a type variable\nContext: %s", + nty.ToString(), + con.toString(), + )) + return false + } + + return true + + case AST.TyConstr: + oty := QueryGlobalEnv(nty.Symbol()) + + switch rty := oty.(type) { + case Lib.Some[AST.Ty]: + args := AST.GetArgsTy(rty.Val) + if args.Len() != nty.Args().Len() { + Glob.Fatal( + label, + fmt.Sprintf( + "Type constructor %s expects %d arguments, got %d", + nty.Symbol(), + args.Len(), + nty.Args().Len(), + ), + ) + return false + } + + if nty.Args().Empty() { + return true + } + + return typecheckRec( + con, + Lib.NewList[AST.Form](), + Lib.NewList[Lib.Pair[AST.Term, AST.Ty]](), + nty.Args(), + ) + + case Lib.None[AST.Ty]: + Glob.Anomaly( + label, + fmt.Sprintf("Unknown type %s", nty.ToString()), + ) + } + } + + Glob.Anomaly( + label, + fmt.Sprintf("On typechecking of types: expected atomic type, got %s", ty.ToString()), + ) + return false +} + +func checkFunctional( + con Con, + name string, + tys Lib.List[AST.Ty], + args Lib.List[AST.Term], + debug_str Lib.Lazy[string], +) bool { + oty := QueryEnvInstance(name, tys) + switch ty := oty.(type) { + case Lib.Some[AST.Ty]: + instantiated_ty := AST.GetArgsTy(ty.Val) + terms_checker := buildTermCheckList( + debug_str, + ty.Val, + args, + instantiated_ty, + ) + tys.Append(AST.GetOutTy(ty.Val)) + + return typecheckRec(con, Lib.NewList[AST.Form](), terms_checker, tys) + + case Lib.None[AST.Ty]: + Glob.Fatal( + label, + fmt.Sprintf("Type of %s not found in the global environment", debug_str.Run()), + ) + } + return false +} + +func typecheckRec( + con Con, + forms Lib.List[AST.Form], + typed_terms Lib.List[Lib.Pair[AST.Term, AST.Ty]], + tys Lib.List[AST.Ty], +) bool { + calls := []func(chan bool){} + + for _, form := range forms.GetSlice() { + loop_form := form + calls = append(calls, func(outchan chan bool) { + outchan <- typecheckForm(con, loop_form) + }) + } + + for _, typed_term := range typed_terms.GetSlice() { + loop_term := typed_term + calls = append(calls, func(outchan chan bool) { + outchan <- typecheckTerm(con, loop_term.Fst, loop_term.Snd) + }) + } + + for _, ty := range tys.GetSlice() { + loop_ty := ty + calls = append(calls, func(outchan chan bool) { + outchan <- typecheckType(con, loop_ty) + }) + } + + res, err := Lib.GenericParallel( + calls, + func(x, y bool) bool { return x && y }, + true, // Neutral of the operation + ) + + if err != nil { + Glob.Anomaly( + label, + fmt.Sprintf("Encountered a Lib error: %s", err.Error()), + ) + } + + return res +} + +func buildTermCheckList( + debug_str Lib.Lazy[string], + ty AST.Ty, + terms Lib.List[AST.Term], + tys Lib.List[AST.Ty], +) Lib.List[Lib.Pair[AST.Term, AST.Ty]] { + if terms.Len() != tys.Len() { + Glob.Fatal( + label, + fmt.Sprintf("Expected %d arguments in %s (which has type %s), but got %d", + tys.Len(), debug_str.Run(), ty.ToString(), terms.Len()), + ) + return Lib.NewList[Lib.Pair[AST.Term, AST.Ty]]() + } + + ls := Lib.MkList[Lib.Pair[AST.Term, AST.Ty]](terms.Len()) + for i := range terms.GetSlice() { + ls.Upd(i, Lib.MkPair(terms.At(i), tys.At(i))) + } + return ls +} diff --git a/src/Unif/parsing.go b/src/Unif/parsing.go index e63b98da..8d61a146 100644 --- a/src/Unif/parsing.go +++ b/src/Unif/parsing.go @@ -61,6 +61,9 @@ func (t TermForm) RenameVariables() AST.Form { return t } func (t TermForm) ReplaceTermByTerm(AST.Term, AST.Term) (AST.Form, bool) { return t, false } +func (t TermForm) ReplaceTyVar(AST.TyBound, AST.Ty) AST.Form { + return t +} func (t TermForm) GetIndex() int { return t.index } func (t TermForm) SubstituteVarByMeta(AST.Var, AST.Meta) AST.Form { return t } func (t TermForm) GetInternalMetas() Lib.List[AST.Meta] { return Lib.NewList[AST.Meta]() } diff --git a/src/main.go b/src/main.go index d6eea737..d4042e94 100644 --- a/src/main.go +++ b/src/main.go @@ -206,6 +206,7 @@ func initDebuggers() { Search.InitDebugger() // Typing.InitDebugger() Unif.InitDebugger() + Engine.InitDebugger() } // FIXME: eventually, we would want to add an "interpretation" layer between elab and internal representation that does this From 1e53850f5dc65bd34ea1552fc0225cfdda1288ad Mon Sep 17 00:00:00 2001 From: Johann Rosain Date: Sat, 26 Jul 2025 11:53:27 +0200 Subject: [PATCH 07/30] Updated gamma and delta rules to deal with type variables --- src/AST/formsDef.go | 34 ++++++++++++++--------------- src/AST/formula.go | 4 ++-- src/AST/quantifiers.go | 8 +++---- src/AST/term.go | 2 +- src/AST/termsDef.go | 12 +++++------ src/AST/tptp-native-types.go | 2 ++ src/AST/ty-syntax.go | 42 ++++++++++++++++++++++-------------- src/AST/typed-vars.go | 4 ++-- src/Core/Sko/interface.go | 2 +- src/Core/instanciation.go | 38 ++++++++++++++++++++++---------- src/Core/skolemisation.go | 21 ++++++++++++------ src/Unif/parsing.go | 2 +- 12 files changed, 103 insertions(+), 68 deletions(-) diff --git a/src/AST/formsDef.go b/src/AST/formsDef.go index a1149588..9a4777b9 100644 --- a/src/AST/formsDef.go +++ b/src/AST/formsDef.go @@ -120,7 +120,7 @@ func (a All) ReplaceTermByTerm(old Term, new Term) (Form, bool) { return All{quant}, isReplaced } -func (a All) ReplaceTyVar(old TyBound, new Ty) Form { +func (a All) SubstTy(old TyBound, new Ty) Form { return All{a.quantifier.replaceTyVar(old, new)} } @@ -172,7 +172,7 @@ func (e Ex) ReplaceTermByTerm(old Term, new Term) (Form, bool) { return Ex{quant}, isReplaced } -func (e Ex) ReplaceTyVar(old TyBound, new Ty) Form { +func (e Ex) SubstTy(old TyBound, new Ty) Form { return Ex{e.quantifier.replaceTyVar(old, new)} } @@ -279,7 +279,7 @@ func (o Or) ReplaceTermByTerm(old Term, new Term) (Form, bool) { return no, res } -func (o Or) ReplaceTyVar(old TyBound, new Ty) Form { +func (o Or) SubstTy(old TyBound, new Ty) Form { formList := replaceTyVarInFormList(o.forms, old, new) return MakeOrSimple(o.GetIndex(), formList, o.metas.Raw()) } @@ -420,7 +420,7 @@ func (a And) ReplaceTermByTerm(old Term, new Term) (Form, bool) { return na, res } -func (a And) ReplaceTyVar(old TyBound, new Ty) Form { +func (a And) SubstTy(old TyBound, new Ty) Form { formList := replaceTyVarInFormList(a.forms, old, new) return MakeAndSimple(a.GetIndex(), formList, a.metas.Raw()) } @@ -536,11 +536,11 @@ func (e Equ) ReplaceTermByTerm(old Term, new Term) (Form, bool) { return ne, res1 || res2 } -func (e Equ) ReplaceTyVar(old TyBound, new Ty) Form { +func (e Equ) SubstTy(old TyBound, new Ty) Form { return MakeEquSimple( e.GetIndex(), - e.f1.ReplaceTyVar(old, new), - e.f2.ReplaceTyVar(old, new), + e.f1.SubstTy(old, new), + e.f2.SubstTy(old, new), e.metas.Raw(), ) } @@ -666,11 +666,11 @@ func (i Imp) ReplaceTermByTerm(old Term, new Term) (Form, bool) { return ni, res1 || res2 } -func (i Imp) ReplaceTyVar(old TyBound, new Ty) Form { +func (i Imp) SubstTy(old TyBound, new Ty) Form { return MakeImpSimple( i.GetIndex(), - i.f1.ReplaceTyVar(old, new), - i.f2.ReplaceTyVar(old, new), + i.f1.SubstTy(old, new), + i.f2.SubstTy(old, new), i.metas.Raw(), ) } @@ -793,10 +793,10 @@ func (n Not) ReplaceTermByTerm(old Term, new Term) (Form, bool) { return nn, res } -func (n Not) ReplaceTyVar(old TyBound, new Ty) Form { +func (n Not) SubstTy(old TyBound, new Ty) Form { return MakeNotSimple( n.GetIndex(), - n.f.ReplaceTyVar(old, new), + n.f.SubstTy(old, new), n.metas.Raw(), ) } @@ -1032,14 +1032,14 @@ func (p Pred) ReplaceTermByTerm(old Term, new Term) (Form, bool) { return np, res } -func (p Pred) ReplaceTyVar(old TyBound, new Ty) Form { +func (p Pred) SubstTy(old TyBound, new Ty) Form { typed_args := Lib.ListMap( p.tys, - func(t Ty) Ty { return t.ReplaceTyVar(old, new) }, + func(t Ty) Ty { return t.SubstTy(old, new) }, ) args := Lib.ListMap( p.args, - func(t Term) Term { return t.ReplaceTyVar(old, new) }, + func(t Term) Term { return t.SubstTy(old, new) }, ) return MakePredSimple( p.GetIndex(), @@ -1141,7 +1141,7 @@ func (t Top) Copy() Form { return MakeTop(t.Get func (Top) Equals(f any) bool { _, isTop := f.(Top); return isTop } func (Top) GetMetas() Lib.Set[Meta] { return Lib.EmptySet[Meta]() } func (t Top) ReplaceTermByTerm(Term, Term) (Form, bool) { return MakeTop(t.GetIndex()), false } -func (t Top) ReplaceTyVar(TyBound, Ty) Form { return t } +func (t Top) SubstTy(TyBound, Ty) Form { return t } func (t Top) RenameVariables() Form { return MakeTop(t.GetIndex()) } func (t Top) GetIndex() int { return t.index } func (t Top) GetSubTerms() Lib.List[Term] { return Lib.NewList[Term]() } @@ -1184,7 +1184,7 @@ func (b Bot) Copy() Form { return MakeBot(b.Get func (Bot) Equals(f any) bool { _, isBot := f.(Bot); return isBot } func (Bot) GetMetas() Lib.Set[Meta] { return Lib.EmptySet[Meta]() } func (b Bot) ReplaceTermByTerm(Term, Term) (Form, bool) { return MakeBot(b.GetIndex()), false } -func (b Bot) ReplaceTyVar(TyBound, Ty) Form { return b } +func (b Bot) SubstTy(TyBound, Ty) Form { return b } func (b Bot) RenameVariables() Form { return MakeBot(b.GetIndex()) } func (b Bot) GetIndex() int { return b.index } func (b Bot) GetSubTerms() Lib.List[Term] { return Lib.NewList[Term]() } diff --git a/src/AST/formula.go b/src/AST/formula.go index 843675c7..16ce1051 100644 --- a/src/AST/formula.go +++ b/src/AST/formula.go @@ -54,7 +54,7 @@ type Form interface { MappableString ReplaceTermByTerm(old Term, new Term) (Form, bool) - ReplaceTyVar(old TyBound, new Ty) Form + SubstTy(old TyBound, new Ty) Form RenameVariables() Form SubstituteVarByMeta(old Var, new Meta) Form ReplaceMetaByTerm(meta Meta, term Term) Form @@ -139,7 +139,7 @@ func replaceTermInFormList(oldForms Lib.List[Form], oldTerm Term, newTerm Term) func replaceTyVarInFormList(oldForms Lib.List[Form], old TyBound, new Ty) Lib.List[Form] { return Lib.ListMap( oldForms, - func(f Form) Form { return f.ReplaceTyVar(old, new) }, + func(f Form) Form { return f.SubstTy(old, new) }, ) } diff --git a/src/AST/quantifiers.go b/src/AST/quantifiers.go index 4a0db4a5..e27c2aca 100644 --- a/src/AST/quantifiers.go +++ b/src/AST/quantifiers.go @@ -161,12 +161,12 @@ func (q quantifier) replaceTermByTerm(old Term, new Term) (quantifier, bool) { } func (q quantifier) replaceTyVar(old TyBound, new Ty) quantifier { - f := q.GetForm().ReplaceTyVar(old, new) + f := q.GetForm().SubstTy(old, new) return makeQuantifier( q.GetIndex(), Lib.ListMap( q.GetVarList(), - func(p TypedVar) TypedVar { return p.ReplaceTyVar(old, new) }, + func(p TypedVar) TypedVar { return p.SubstTy(old, new) }, ), f, q.metas.Raw().Copy(), @@ -186,7 +186,7 @@ func (q quantifier) renameVariables() quantifier { f, replaced := newForm.ReplaceTermByTerm(v.ToBoundVar(), newVar) if !replaced { newBv := MkTyBV(newVar.name, newVar.index) - f = f.ReplaceTyVar(v.ToTyBoundVar(), newBv) + f = f.SubstTy(v.ToTyBoundVar(), newBv) newTyBv.Append(Lib.MkPair(v.ToTyBoundVar(), newBv)) } newForm = f @@ -198,7 +198,7 @@ func (q quantifier) renameVariables() quantifier { newVarList, func(p TypedVar) TypedVar { for _, pair := range newTyBv.GetSlice() { - p = p.ReplaceTyVar(pair.Fst, pair.Snd) + p = p.SubstTy(pair.Fst, pair.Snd) } return p }, diff --git a/src/AST/term.go b/src/AST/term.go index b14e25d4..447728d5 100644 --- a/src/AST/term.go +++ b/src/AST/term.go @@ -53,7 +53,7 @@ type Term interface { GetMetaList() Lib.List[Meta] // Metas appearing in the term ORDERED GetSubTerms() Lib.List[Term] ReplaceSubTermBy(original_term, new_term Term) Term - ReplaceTyVar(old TyBound, new Ty) Term + SubstTy(old TyBound, new Ty) Term Less(any) bool } diff --git a/src/AST/termsDef.go b/src/AST/termsDef.go index 4fa32076..29c997db 100644 --- a/src/AST/termsDef.go +++ b/src/AST/termsDef.go @@ -111,7 +111,7 @@ func (i Id) ReplaceSubTermBy(original_term, new_term Term) Term { return i } -func (i Id) ReplaceTyVar(TyBound, Ty) Term { return i } +func (i Id) SubstTy(TyBound, Ty) Term { return i } func (i Id) GetSubTerms() Lib.List[Term] { return Lib.MkListV[Term](i) @@ -277,14 +277,14 @@ func (f Fun) ReplaceSubTermBy(oldTerm, newTerm Term) Term { } } -func (f Fun) ReplaceTyVar(old TyBound, new Ty) Term { +func (f Fun) SubstTy(old TyBound, new Ty) Term { typed_args := Lib.ListMap( f.tys, - func(t Ty) Ty { return t.ReplaceTyVar(old, new) }, + func(t Ty) Ty { return t.SubstTy(old, new) }, ) args := Lib.ListMap( f.args, - func(t Term) Term { return t.ReplaceTyVar(old, new) }, + func(t Term) Term { return t.SubstTy(old, new) }, ) return MakeFun( f.GetID(), @@ -364,7 +364,7 @@ func (v Var) ReplaceSubTermBy(original_term, new_term Term) Term { return v } -func (v Var) ReplaceTyVar(TyBound, Ty) Term { return v } +func (v Var) SubstTy(TyBound, Ty) Term { return v } func (v Var) ToMappedString(map_ MapString, type_ bool) string { return v.GetName() @@ -454,7 +454,7 @@ func (m Meta) ReplaceSubTermBy(original_term, new_term Term) Term { return m } -func (m Meta) ReplaceTyVar(TyBound, Ty) Term { return m } +func (m Meta) SubstTy(TyBound, Ty) Term { return m } func (m Meta) GetSubTerms() Lib.List[Term] { return Lib.MkListV[Term](m) diff --git a/src/AST/tptp-native-types.go b/src/AST/tptp-native-types.go index 3b4b821d..320cf3b7 100644 --- a/src/AST/tptp-native-types.go +++ b/src/AST/tptp-native-types.go @@ -60,6 +60,8 @@ func initTPTPNativeTypes() { tIndividual = MkTyConst("$i") tProp = MkTyConst("$o") + + count_meta = 0 } func TType() Ty { diff --git a/src/AST/ty-syntax.go b/src/AST/ty-syntax.go index f2b374a7..a1ea319d 100644 --- a/src/AST/ty-syntax.go +++ b/src/AST/ty-syntax.go @@ -39,16 +39,21 @@ package AST import ( "fmt" + "sync" + "github.com/GoelandProver/Goeland/Glob" "github.com/GoelandProver/Goeland/Lib" ) +var meta_mut sync.Mutex +var count_meta int + type Ty interface { isTy() ToString() string Equals(any) bool Copy() Ty - ReplaceTyVar(TyBound, Ty) Ty + SubstTy(TyBound, Ty) Ty } // Internal, shouldn't get out so no upper case @@ -66,7 +71,7 @@ func (v tyVar) Equals(oth any) bool { } func (v tyVar) Copy() Ty { return tyVar{v.repr} } -func (v tyVar) ReplaceTyVar(TyBound, Ty) Ty { return v } +func (v tyVar) SubstTy(TyBound, Ty) Ty { return v } type TyBound struct { name string @@ -84,7 +89,7 @@ func (b TyBound) Equals(oth any) bool { func (b TyBound) Copy() Ty { return TyBound{b.name, b.index} } func (b TyBound) GetName() string { return b.name } -func (b TyBound) ReplaceTyVar(old TyBound, new Ty) Ty { +func (b TyBound) SubstTy(old TyBound, new Ty) Ty { if b.Equals(old) { return new } @@ -92,20 +97,21 @@ func (b TyBound) ReplaceTyVar(old TyBound, new Ty) Ty { } type TyMeta struct { - name string + name string + index int } func (TyMeta) isTy() {} -func (m TyMeta) ToString() string { return m.name } +func (m TyMeta) ToString() string { return fmt.Sprintf("%s_%d", m.name, m.index) } func (m TyMeta) Equals(oth any) bool { if om, ok := oth.(TyMeta); ok { return m.name == om.name } return false } -func (m TyMeta) Copy() Ty { return TyMeta{m.name} } +func (m TyMeta) Copy() Ty { return TyMeta{m.name, m.index} } -func (m TyMeta) ReplaceTyVar(TyBound, Ty) Ty { return m } +func (m TyMeta) SubstTy(TyBound, Ty) Ty { return m } // Type constructors, e.g., list, option, ... // Include constants, e.g., $i, $o, ... @@ -143,10 +149,10 @@ func (c TyConstr) Args() Lib.List[Ty] { return c.args } -func (c TyConstr) ReplaceTyVar(old TyBound, new Ty) Ty { +func (c TyConstr) SubstTy(old TyBound, new Ty) Ty { return TyConstr{ c.symbol, - Lib.ListMap(c.args, func(t Ty) Ty { return t.ReplaceTyVar(old, new) }), + Lib.ListMap(c.args, func(t Ty) Ty { return t.SubstTy(old, new) }), } } @@ -175,9 +181,9 @@ func (p TyProd) Copy() Ty { return TyProd{Lib.ListCpy(p.args)} } -func (p TyProd) ReplaceTyVar(old TyBound, new Ty) Ty { +func (p TyProd) SubstTy(old TyBound, new Ty) Ty { return TyProd{ - Lib.ListMap(p.args, func(t Ty) Ty { return t.ReplaceTyVar(old, new) }), + Lib.ListMap(p.args, func(t Ty) Ty { return t.SubstTy(old, new) }), } } @@ -200,8 +206,8 @@ func (f TyFunc) Copy() Ty { return TyFunc{f.in.Copy(), f.out.Copy()} } -func (f TyFunc) ReplaceTyVar(old TyBound, new Ty) Ty { - return TyFunc{f.in.ReplaceTyVar(old, new), f.out.ReplaceTyVar(old, new)} +func (f TyFunc) SubstTy(old TyBound, new Ty) Ty { + return TyFunc{f.in.SubstTy(old, new), f.out.SubstTy(old, new)} } type TyPi struct { @@ -226,8 +232,8 @@ func (p TyPi) Copy() Ty { return TyPi{p.vars.Copy(func(x string) string { return x }), p.ty.Copy()} } -func (p TyPi) ReplaceTyVar(old TyBound, new Ty) Ty { - return TyPi{p.vars, p.ty.ReplaceTyVar(old, new)} +func (p TyPi) SubstTy(old TyBound, new Ty) Ty { + return TyPi{p.vars, p.ty.SubstTy(old, new)} } // Makers @@ -241,7 +247,11 @@ func MkTyBV(name string, index int) Ty { } func MkTyMeta(name string) Ty { - return TyMeta{name} + meta_mut.Lock() + meta := TyMeta{name, count_meta} + count_meta += 1 + meta_mut.Unlock() + return meta } func MkTyConstr(symbol string, args Lib.List[Ty]) Ty { diff --git a/src/AST/typed-vars.go b/src/AST/typed-vars.go index 598488f9..d1bea6af 100644 --- a/src/AST/typed-vars.go +++ b/src/AST/typed-vars.go @@ -82,8 +82,8 @@ func (v TypedVar) ToTyBoundVar() TyBound { return MkTyBV(v.name, v.index).(TyBound) } -func (v TypedVar) ReplaceTyVar(old TyBound, new Ty) TypedVar { - return TypedVar{v.name, v.index, v.ty.ReplaceTyVar(old, new)} +func (v TypedVar) SubstTy(old TyBound, new Ty) TypedVar { + return TypedVar{v.name, v.index, v.ty.SubstTy(old, new)} } func MkTypedVar(name string, index int, ty Ty) TypedVar { diff --git a/src/Core/Sko/interface.go b/src/Core/Sko/interface.go index 647a24e8..b94c1d5f 100644 --- a/src/Core/Sko/interface.go +++ b/src/Core/Sko/interface.go @@ -64,7 +64,7 @@ func genFreshSymbol(existingSymbols *Lib.Set[AST.Id], x AST.TypedVar) AST.Id { symbol := AST.MakerNewId( fmt.Sprintf("skolem@%v", x.GetName()), ) - existingSymbols.Add(symbol) + *existingSymbols = existingSymbols.Add(symbol) return symbol } diff --git a/src/Core/instanciation.go b/src/Core/instanciation.go index 58a517b0..81cc93aa 100644 --- a/src/Core/instanciation.go +++ b/src/Core/instanciation.go @@ -49,7 +49,7 @@ const ( * Instantiates once the formula fnt. */ func Instantiate(fnt FormAndTerms, index int) (FormAndTerms, Lib.Set[AST.Meta]) { - var meta AST.Meta + var meta Lib.Option[AST.Meta] terms := fnt.GetTerms() switch f := fnt.GetForm().(type) { @@ -61,7 +61,15 @@ func Instantiate(fnt FormAndTerms, index int) (FormAndTerms, Lib.Set[AST.Meta]) fnt, meta = RealInstantiate(f.GetVarList(), index, is_all, f.GetForm(), terms) } - return fnt, Lib.Singleton(meta) + switch m := meta.(type) { + case Lib.Some[AST.Meta]: + return fnt, Lib.Singleton(m.Val) + case Lib.None[AST.Meta]: + return fnt, Lib.EmptySet[AST.Meta]() + } + + Glob.Anomaly("instantiation", "returned bad option type") + return fnt, Lib.EmptySet[AST.Meta]() } func RealInstantiate( @@ -69,16 +77,24 @@ func RealInstantiate( index, status int, subForm AST.Form, terms Lib.List[AST.Term], -) (FormAndTerms, AST.Meta) { +) (FormAndTerms, Lib.Option[AST.Meta]) { v := varList.At(0) - meta := AST.MakerMeta(strings.ToUpper(v.GetName()), index, v.GetTy()) - subForm = subForm.SubstituteVarByMeta(v.ToBoundVar(), meta) + var m Lib.Option[AST.Meta] - terms = terms.Copy(AST.Term.Copy) - terms.Add( - AST.TermEquals, - Glob.To[AST.Term](meta), - ) + if AST.IsTType(v.GetTy()) { + meta := AST.MkTyMeta(strings.ToUpper(v.GetName())) + subForm = subForm.SubstTy(v.ToTyBoundVar(), meta) + m = Lib.MkNone[AST.Meta]() + } else { + meta := AST.MakerMeta(strings.ToUpper(v.GetName()), index, v.GetTy()) + subForm = subForm.SubstituteVarByMeta(v.ToBoundVar(), meta) + terms = terms.Copy(AST.Term.Copy) + terms.Add( + AST.TermEquals, + Glob.To[AST.Term](meta), + ) + m = Lib.MkSome(meta) + } if varList.Len() > 1 { if status == is_exists { @@ -93,5 +109,5 @@ func RealInstantiate( } } - return MakeFormAndTerm(subForm, terms), meta + return MakeFormAndTerm(subForm, terms), m } diff --git a/src/Core/skolemisation.go b/src/Core/skolemisation.go index aade0643..66238d50 100644 --- a/src/Core/skolemisation.go +++ b/src/Core/skolemisation.go @@ -124,13 +124,20 @@ func realSkolemize( metas Lib.Set[AST.Meta], typ int, ) AST.Form { - sko, res := selectedSkolemization.Skolemize( - initialForm, - deltaForm, - x, - metas, - ) - selectedSkolemization = sko + var res AST.Form + + if AST.IsTType(x.GetTy()) { + id := AST.MakerId("skoTy") + res = deltaForm.SubstTy(x.ToTyBoundVar(), AST.MkTyConst(id.ToString())) + } else { + selectedSkolemization, res = selectedSkolemization.Skolemize( + initialForm, + deltaForm, + x, + metas, + ) + } + switch typ { case isNegAll: if allVars.Len() > 1 { diff --git a/src/Unif/parsing.go b/src/Unif/parsing.go index 8d61a146..9674909d 100644 --- a/src/Unif/parsing.go +++ b/src/Unif/parsing.go @@ -61,7 +61,7 @@ func (t TermForm) RenameVariables() AST.Form { return t } func (t TermForm) ReplaceTermByTerm(AST.Term, AST.Term) (AST.Form, bool) { return t, false } -func (t TermForm) ReplaceTyVar(AST.TyBound, AST.Ty) AST.Form { +func (t TermForm) SubstTy(AST.TyBound, AST.Ty) AST.Form { return t } func (t TermForm) GetIndex() int { return t.index } From 403fef098b659d24ee70d9a30b457911005fa409 Mon Sep 17 00:00:00 2001 From: Johann Rosain Date: Sat, 26 Jul 2025 20:00:33 +0200 Subject: [PATCH 08/30] Manage typed proof search and add related tests * non destructive search **does not** manage typed search, only destructive search does * dmt might be incompatible with typed search --- .../test-suite/proofs/tf1_basic_thm-2.out | 28 ++ devtools/test-suite/proofs/tf1_basic_thm-2.p | 40 +++ devtools/test-suite/proofs/tf1_basic_thm.out | 16 + devtools/test-suite/proofs/tf1_basic_thm.p | 40 +++ src/AST/formsDef.go | 38 +-- src/AST/formula.go | 4 +- src/AST/quantifiers.go | 2 +- src/AST/term.go | 2 +- src/AST/termsDef.go | 11 +- src/AST/ty-syntax.go | 91 +++++- src/AST/typed-vars.go | 2 +- src/Core/FormListDS.go | 6 +- src/Core/global_unifier.go | 60 ++-- src/Core/instanciation.go | 2 +- src/Core/int_subst_and_form.go | 8 +- src/Core/subst_and_form.go | 46 ++- src/Core/subst_and_form_and_terms.go | 25 +- src/Core/substitutions_search.go | 283 +++++++++--------- src/Lib/either.go | 103 +++++++ src/Lib/list.go | 10 + src/Mods/assisted/assistant.go | 29 +- src/Mods/assisted/rules.go | 7 +- src/Mods/dmt/rewrite.go | 21 +- src/Mods/dmt/rewritten.go | 3 +- src/Mods/equality/bse/equality.go | 12 +- .../equality/bse/equality_rules_try_apply.go | 3 +- src/Mods/equality/bse/equality_types.go | 8 +- src/Search/child_management.go | 30 +- src/Search/children.go | 30 +- src/Search/destructive.go | 176 +++++++---- src/Search/exchanges.go | 24 +- src/Search/incremental/rulesManager.go | 4 +- src/Search/incremental/search.go | 2 +- src/Search/nonDestructiveSearch.go | 108 ++++--- src/Search/proof.go | 7 +- src/Search/rules.go | 45 +-- src/Search/search.go | 11 +- src/Search/state.go | 23 +- src/Unif/data_structure.go | 2 +- src/Unif/matching.go | 18 +- src/Unif/matching_substitutions.go | 250 ++++++++++++++++ src/Unif/parsing.go | 39 ++- src/Unif/substitutions_tree.go | 5 +- 43 files changed, 1204 insertions(+), 470 deletions(-) create mode 100644 devtools/test-suite/proofs/tf1_basic_thm-2.out create mode 100644 devtools/test-suite/proofs/tf1_basic_thm-2.p create mode 100644 devtools/test-suite/proofs/tf1_basic_thm.out create mode 100644 devtools/test-suite/proofs/tf1_basic_thm.p create mode 100644 src/Lib/either.go diff --git a/devtools/test-suite/proofs/tf1_basic_thm-2.out b/devtools/test-suite/proofs/tf1_basic_thm-2.out new file mode 100644 index 00000000..b87de471 --- /dev/null +++ b/devtools/test-suite/proofs/tf1_basic_thm-2.out @@ -0,0 +1,28 @@ +[0] ALPHA_AND : ((! [A13]: ((maybe(A13) ; head(A13;nil(A13;)) = none(A13;)))) & (! [A15 X17 XS19]: ((maybe(A15) ; head(A15;cons(A15;X17, XS19)) = some(A15;X17)))) & ~((! [A21 X23 Y25 Z27]: ((maybe(A21) ; head(A21;cons(A21;X23, cons(A21;Y25, cons(A21;Z27, nil(A21;))))) = some(A21;X23)))))) + -> [1] (! [A13]: ((maybe(A13) ; head(A13;nil(A13;)) = none(A13;)))), (! [A15 X17 XS19]: ((maybe(A15) ; head(A15;cons(A15;X17, XS19)) = some(A15;X17)))), ~((! [A21 X23 Y25 Z27]: ((maybe(A21) ; head(A21;cons(A21;X23, cons(A21;Y25, cons(A21;Z27, nil(A21;))))) = some(A21;X23))))) + +[1] DELTA_NOT_FORALL : ~((! [A21 X23 Y25 Z27]: ((maybe(A21) ; head(A21;cons(A21;X23, cons(A21;Y25, cons(A21;Z27, nil(A21;))))) = some(A21;X23))))) + -> [2] ~((! [X23 Y25 Z27]: ((maybe(skoTy) ; head(skoTy;cons(skoTy;X23, cons(skoTy;Y25, cons(skoTy;Z27, nil(skoTy;))))) = some(skoTy;X23))))) + +[2] DELTA_NOT_FORALL : ~((! [X23 Y25 Z27]: ((maybe(skoTy) ; head(skoTy;cons(skoTy;X23, cons(skoTy;Y25, cons(skoTy;Z27, nil(skoTy;))))) = some(skoTy;X23))))) + -> [3] ~((! [Y25 Z27]: ((maybe(skoTy) ; head(skoTy;cons(skoTy;skolem@X23, cons(skoTy;Y25, cons(skoTy;Z27, nil(skoTy;))))) = some(skoTy;skolem@X23))))) + +[3] DELTA_NOT_FORALL : ~((! [Y25 Z27]: ((maybe(skoTy) ; head(skoTy;cons(skoTy;skolem@X23, cons(skoTy;Y25, cons(skoTy;Z27, nil(skoTy;))))) = some(skoTy;skolem@X23))))) + -> [4] ~((! [Z27]: ((maybe(skoTy) ; head(skoTy;cons(skoTy;skolem@X23, cons(skoTy;skolem@Y25, cons(skoTy;Z27, nil(skoTy;))))) = some(skoTy;skolem@X23))))) + +[4] DELTA_NOT_FORALL : ~((! [Z27]: ((maybe(skoTy) ; head(skoTy;cons(skoTy;skolem@X23, cons(skoTy;skolem@Y25, cons(skoTy;Z27, nil(skoTy;))))) = some(skoTy;skolem@X23))))) + -> [5] ~((maybe(skoTy) ; head(skoTy;cons(skoTy;skolem@X23, cons(skoTy;skolem@Y25, cons(skoTy;skolem@Z27, nil(skoTy;))))) = some(skoTy;skolem@X23))) + +[5] GAMMA_FORALL : (! [A13]: ((maybe(A13) ; head(A13;nil(A13;)) = none(A13;)))) + -> [6] (maybe(A13_1) ; head(A13_1;nil(A13_1;)) = none(A13_1;)) + +[6] GAMMA_FORALL : (! [A15 X17 XS19]: ((maybe(A15) ; head(A15;cons(A15;X17, XS19)) = some(A15;X17)))) + -> [7] (! [X17 XS19]: ((maybe(skoTy) ; head(skoTy;cons(skoTy;X17, XS19)) = some(skoTy;X17)))) + +[7] GAMMA_FORALL : (! [X17 XS19]: ((maybe(skoTy) ; head(skoTy;cons(skoTy;X17, XS19)) = some(skoTy;X17)))) + -> [8] (! [XS19]: ((maybe(skoTy) ; head(skoTy;cons(skoTy;skolem@X23, XS19)) = some(skoTy;skolem@X23)))) + +[8] GAMMA_FORALL : (! [XS19]: ((maybe(skoTy) ; head(skoTy;cons(skoTy;skolem@X23, XS19)) = some(skoTy;skolem@X23)))) + -> [9] (maybe(skoTy) ; head(skoTy;cons(skoTy;skolem@X23, cons(skoTy;skolem@Y25, cons(skoTy;skolem@Z27, nil(skoTy;))))) = some(skoTy;skolem@X23)) + +[9] CLOSURE : (maybe(skoTy) ; head(skoTy;cons(skoTy;skolem@X23, cons(skoTy;skolem@Y25, cons(skoTy;skolem@Z27, nil(skoTy;))))) = some(skoTy;skolem@X23)) diff --git a/devtools/test-suite/proofs/tf1_basic_thm-2.p b/devtools/test-suite/proofs/tf1_basic_thm-2.p new file mode 100644 index 00000000..f4838a46 --- /dev/null +++ b/devtools/test-suite/proofs/tf1_basic_thm-2.p @@ -0,0 +1,40 @@ +% args: -proof -no_id +% result: VALID + +tff(list_type,type, + list: $tType > $tType ). + +tff(maybe_type,type, + maybe: $tType > $tType ). + +%----Polymorphic symbols +tff(nil_type,type, + nil: + !>[A: $tType] : list(A) ). + +tff(cons_type,type, + cons: + !>[A: $tType] : ( ( A * list(A) ) > list(A) ) ). + +tff(none_type,type, + none: + !>[A: $tType] : maybe(A) ). + +tff(some_type,type, + some: + !>[A: $tType] : ( A > maybe(A) ) ). + +tff(head_type,type, + head: + !>[A: $tType] : ( list(A) > maybe(A) ) ). + +%----Use of polymorphic symbols +tff(head_nil,axiom, + ! [A: $tType] : ( head(A,nil(A)) = none(A) )). + +tff(head_cons,axiom, + ! [A: $tType,X : A,XS : list(A)] : ( head(A,cons(A,X,XS)) = some(A,X) ) ). + +%----With integers +tff(solve_this,conjecture, + ! [A: $tType,X : A,Y : A,Z : A] : ( head(A,cons(A,X,cons(A,Y,cons(A,Z,nil(A))))) = some(A,X) ) ). diff --git a/devtools/test-suite/proofs/tf1_basic_thm.out b/devtools/test-suite/proofs/tf1_basic_thm.out new file mode 100644 index 00000000..39c81f0d --- /dev/null +++ b/devtools/test-suite/proofs/tf1_basic_thm.out @@ -0,0 +1,16 @@ +[0] ALPHA_AND : ((! [A14]: ((maybe(A14) ; head(A14;nil(A14;)) = none(A14;)))) & (! [A16 X18 XS20]: ((maybe(A16) ; head(A16;cons(A16;X18, XS20)) = some(A16;X18)))) & ~((maybe($int) ; head($int;cons($int;1, cons($int;2, cons($int;3, nil($int;))))) = some($int;1)))) + -> [1] (! [A14]: ((maybe(A14) ; head(A14;nil(A14;)) = none(A14;)))), (! [A16 X18 XS20]: ((maybe(A16) ; head(A16;cons(A16;X18, XS20)) = some(A16;X18)))), ~((maybe($int) ; head($int;cons($int;1, cons($int;2, cons($int;3, nil($int;))))) = some($int;1))) + +[1] GAMMA_FORALL : (! [A14]: ((maybe(A14) ; head(A14;nil(A14;)) = none(A14;)))) + -> [2] (maybe(A14_1) ; head(A14_1;nil(A14_1;)) = none(A14_1;)) + +[2] GAMMA_FORALL : (! [A16 X18 XS20]: ((maybe(A16) ; head(A16;cons(A16;X18, XS20)) = some(A16;X18)))) + -> [3] (! [X18 XS20]: ((maybe($int) ; head($int;cons($int;X18, XS20)) = some($int;X18)))) + +[3] GAMMA_FORALL : (! [X18 XS20]: ((maybe($int) ; head($int;cons($int;X18, XS20)) = some($int;X18)))) + -> [4] (! [XS20]: ((maybe($int) ; head($int;cons($int;1, XS20)) = some($int;1)))) + +[4] GAMMA_FORALL : (! [XS20]: ((maybe($int) ; head($int;cons($int;1, XS20)) = some($int;1)))) + -> [5] (maybe($int) ; head($int;cons($int;1, cons($int;2, cons($int;3, nil($int;))))) = some($int;1)) + +[5] CLOSURE : (maybe($int) ; head($int;cons($int;1, cons($int;2, cons($int;3, nil($int;))))) = some($int;1)) diff --git a/devtools/test-suite/proofs/tf1_basic_thm.p b/devtools/test-suite/proofs/tf1_basic_thm.p new file mode 100644 index 00000000..c2ed4f90 --- /dev/null +++ b/devtools/test-suite/proofs/tf1_basic_thm.p @@ -0,0 +1,40 @@ +% args: -proof -no_id +% result: VALID + +tff(list_type,type, + list: $tType > $tType ). + +tff(maybe_type,type, + maybe: $tType > $tType ). + +%----Polymorphic symbols +tff(nil_type,type, + nil: + !>[A: $tType] : list(A) ). + +tff(cons_type,type, + cons: + !>[A: $tType] : ( ( A * list(A) ) > list(A) ) ). + +tff(none_type,type, + none: + !>[A: $tType] : maybe(A) ). + +tff(some_type,type, + some: + !>[A: $tType] : ( A > maybe(A) ) ). + +tff(head_type,type, + head: + !>[A: $tType] : ( list(A) > maybe(A) ) ). + +%----Use of polymorphic symbols +tff(head_nil,axiom, + ! [A: $tType] : ( head(A,nil(A)) = none(A) )). + +tff(head_cons,axiom, + ! [A: $tType,X : A,XS : list(A)] : ( head(A,cons(A,X,XS)) = some(A,X) ) ). + +%----With integers +tff(solve_this,conjecture, + head($int,cons($int,1,cons($int,2,cons($int,3,nil($int))))) = some($int,1) ). diff --git a/src/AST/formsDef.go b/src/AST/formsDef.go index 9a4777b9..b1733121 100644 --- a/src/AST/formsDef.go +++ b/src/AST/formsDef.go @@ -120,7 +120,7 @@ func (a All) ReplaceTermByTerm(old Term, new Term) (Form, bool) { return All{quant}, isReplaced } -func (a All) SubstTy(old TyBound, new Ty) Form { +func (a All) SubstTy(old TyGenVar, new Ty) Form { return All{a.quantifier.replaceTyVar(old, new)} } @@ -172,7 +172,7 @@ func (e Ex) ReplaceTermByTerm(old Term, new Term) (Form, bool) { return Ex{quant}, isReplaced } -func (e Ex) SubstTy(old TyBound, new Ty) Form { +func (e Ex) SubstTy(old TyGenVar, new Ty) Form { return Ex{e.quantifier.replaceTyVar(old, new)} } @@ -279,7 +279,7 @@ func (o Or) ReplaceTermByTerm(old Term, new Term) (Form, bool) { return no, res } -func (o Or) SubstTy(old TyBound, new Ty) Form { +func (o Or) SubstTy(old TyGenVar, new Ty) Form { formList := replaceTyVarInFormList(o.forms, old, new) return MakeOrSimple(o.GetIndex(), formList, o.metas.Raw()) } @@ -420,7 +420,7 @@ func (a And) ReplaceTermByTerm(old Term, new Term) (Form, bool) { return na, res } -func (a And) SubstTy(old TyBound, new Ty) Form { +func (a And) SubstTy(old TyGenVar, new Ty) Form { formList := replaceTyVarInFormList(a.forms, old, new) return MakeAndSimple(a.GetIndex(), formList, a.metas.Raw()) } @@ -536,7 +536,7 @@ func (e Equ) ReplaceTermByTerm(old Term, new Term) (Form, bool) { return ne, res1 || res2 } -func (e Equ) SubstTy(old TyBound, new Ty) Form { +func (e Equ) SubstTy(old TyGenVar, new Ty) Form { return MakeEquSimple( e.GetIndex(), e.f1.SubstTy(old, new), @@ -666,7 +666,7 @@ func (i Imp) ReplaceTermByTerm(old Term, new Term) (Form, bool) { return ni, res1 || res2 } -func (i Imp) SubstTy(old TyBound, new Ty) Form { +func (i Imp) SubstTy(old TyGenVar, new Ty) Form { return MakeImpSimple( i.GetIndex(), i.f1.SubstTy(old, new), @@ -793,7 +793,7 @@ func (n Not) ReplaceTermByTerm(old Term, new Term) (Form, bool) { return nn, res } -func (n Not) SubstTy(old TyBound, new Ty) Form { +func (n Not) SubstTy(old TyGenVar, new Ty) Form { return MakeNotSimple( n.GetIndex(), n.f.SubstTy(old, new), @@ -1032,7 +1032,7 @@ func (p Pred) ReplaceTermByTerm(old Term, new Term) (Form, bool) { return np, res } -func (p Pred) SubstTy(old TyBound, new Ty) Form { +func (p Pred) SubstTy(old TyGenVar, new Ty) Form { typed_args := Lib.ListMap( p.tys, func(t Ty) Ty { return t.SubstTy(old, new) }, @@ -1092,18 +1092,12 @@ func (p Pred) GetChildFormulas() Lib.List[Form] { } func (p Pred) ReplaceMetaByTerm(meta Meta, term Term) Form { - newTerms := Lib.MkList[Term](p.args.Len()) - - for i, old := range p.args.GetSlice() { - // FIXME: old.GetName() == meta.GetName() ?? - if old.Equals(meta) { - newTerms.Upd(i, term) - } else { - newTerms.Upd(i, old) - } - } - - return MakePred(p.GetIndex(), p.id, p.tys, newTerms) + return MakePred( + p.GetIndex(), + p.id, + p.tys, + Lib.ListMap(p.args, func(t Term) Term { return t.ReplaceSubTermBy(meta, term) }), + ) } // ----------------------------------------------------------------------------- @@ -1141,7 +1135,7 @@ func (t Top) Copy() Form { return MakeTop(t.Get func (Top) Equals(f any) bool { _, isTop := f.(Top); return isTop } func (Top) GetMetas() Lib.Set[Meta] { return Lib.EmptySet[Meta]() } func (t Top) ReplaceTermByTerm(Term, Term) (Form, bool) { return MakeTop(t.GetIndex()), false } -func (t Top) SubstTy(TyBound, Ty) Form { return t } +func (t Top) SubstTy(TyGenVar, Ty) Form { return t } func (t Top) RenameVariables() Form { return MakeTop(t.GetIndex()) } func (t Top) GetIndex() int { return t.index } func (t Top) GetSubTerms() Lib.List[Term] { return Lib.NewList[Term]() } @@ -1184,7 +1178,7 @@ func (b Bot) Copy() Form { return MakeBot(b.Get func (Bot) Equals(f any) bool { _, isBot := f.(Bot); return isBot } func (Bot) GetMetas() Lib.Set[Meta] { return Lib.EmptySet[Meta]() } func (b Bot) ReplaceTermByTerm(Term, Term) (Form, bool) { return MakeBot(b.GetIndex()), false } -func (b Bot) SubstTy(TyBound, Ty) Form { return b } +func (b Bot) SubstTy(TyGenVar, Ty) Form { return b } func (b Bot) RenameVariables() Form { return MakeBot(b.GetIndex()) } func (b Bot) GetIndex() int { return b.index } func (b Bot) GetSubTerms() Lib.List[Term] { return Lib.NewList[Term]() } diff --git a/src/AST/formula.go b/src/AST/formula.go index 16ce1051..dc14eff9 100644 --- a/src/AST/formula.go +++ b/src/AST/formula.go @@ -54,7 +54,7 @@ type Form interface { MappableString ReplaceTermByTerm(old Term, new Term) (Form, bool) - SubstTy(old TyBound, new Ty) Form + SubstTy(old TyGenVar, new Ty) Form RenameVariables() Form SubstituteVarByMeta(old Var, new Meta) Form ReplaceMetaByTerm(meta Meta, term Term) Form @@ -136,7 +136,7 @@ func replaceTermInFormList(oldForms Lib.List[Form], oldTerm Term, newTerm Term) return newForms, res } -func replaceTyVarInFormList(oldForms Lib.List[Form], old TyBound, new Ty) Lib.List[Form] { +func replaceTyVarInFormList(oldForms Lib.List[Form], old TyGenVar, new Ty) Lib.List[Form] { return Lib.ListMap( oldForms, func(f Form) Form { return f.SubstTy(old, new) }, diff --git a/src/AST/quantifiers.go b/src/AST/quantifiers.go index e27c2aca..5ceabff2 100644 --- a/src/AST/quantifiers.go +++ b/src/AST/quantifiers.go @@ -160,7 +160,7 @@ func (q quantifier) replaceTermByTerm(old Term, new Term) (quantifier, bool) { ), res } -func (q quantifier) replaceTyVar(old TyBound, new Ty) quantifier { +func (q quantifier) replaceTyVar(old TyGenVar, new Ty) quantifier { f := q.GetForm().SubstTy(old, new) return makeQuantifier( q.GetIndex(), diff --git a/src/AST/term.go b/src/AST/term.go index 447728d5..116efe92 100644 --- a/src/AST/term.go +++ b/src/AST/term.go @@ -53,7 +53,7 @@ type Term interface { GetMetaList() Lib.List[Meta] // Metas appearing in the term ORDERED GetSubTerms() Lib.List[Term] ReplaceSubTermBy(original_term, new_term Term) Term - SubstTy(old TyBound, new Ty) Term + SubstTy(old TyGenVar, new Ty) Term Less(any) bool } diff --git a/src/AST/termsDef.go b/src/AST/termsDef.go index 29c997db..455fc44a 100644 --- a/src/AST/termsDef.go +++ b/src/AST/termsDef.go @@ -111,7 +111,7 @@ func (i Id) ReplaceSubTermBy(original_term, new_term Term) Term { return i } -func (i Id) SubstTy(TyBound, Ty) Term { return i } +func (i Id) SubstTy(TyGenVar, Ty) Term { return i } func (i Id) GetSubTerms() Lib.List[Term] { return Lib.MkListV[Term](i) @@ -277,7 +277,7 @@ func (f Fun) ReplaceSubTermBy(oldTerm, newTerm Term) Term { } } -func (f Fun) SubstTy(old TyBound, new Ty) Term { +func (f Fun) SubstTy(old TyGenVar, new Ty) Term { typed_args := Lib.ListMap( f.tys, func(t Ty) Ty { return t.SubstTy(old, new) }, @@ -364,7 +364,7 @@ func (v Var) ReplaceSubTermBy(original_term, new_term Term) Term { return v } -func (v Var) SubstTy(TyBound, Ty) Term { return v } +func (v Var) SubstTy(TyGenVar, Ty) Term { return v } func (v Var) ToMappedString(map_ MapString, type_ bool) string { return v.GetName() @@ -454,7 +454,7 @@ func (m Meta) ReplaceSubTermBy(original_term, new_term Term) Term { return m } -func (m Meta) SubstTy(TyBound, Ty) Term { return m } +func (m Meta) SubstTy(TyGenVar, Ty) Term { return m } func (m Meta) GetSubTerms() Lib.List[Term] { return Lib.MkListV[Term](m) @@ -471,8 +471,7 @@ func (m Meta) Less(u any) bool { } func MakeEmptyMeta() Meta { - // FIXME: nil are bad - return MakeMeta(-1, -1, "-1", -1, nil) + return MakeMeta(-1, -1, "-1", -1, TIndividual()) } func MetaEquals(x, y Meta) bool { diff --git a/src/AST/ty-syntax.go b/src/AST/ty-syntax.go index a1ea319d..654a80c2 100644 --- a/src/AST/ty-syntax.go +++ b/src/AST/ty-syntax.go @@ -48,12 +48,16 @@ import ( var meta_mut sync.Mutex var count_meta int +type TyGenVar interface { + isGenVar() +} + type Ty interface { isTy() ToString() string Equals(any) bool Copy() Ty - SubstTy(TyBound, Ty) Ty + SubstTy(TyGenVar, Ty) Ty } // Internal, shouldn't get out so no upper case @@ -71,7 +75,7 @@ func (v tyVar) Equals(oth any) bool { } func (v tyVar) Copy() Ty { return tyVar{v.repr} } -func (v tyVar) SubstTy(TyBound, Ty) Ty { return v } +func (v tyVar) SubstTy(TyGenVar, Ty) Ty { return v } type TyBound struct { name string @@ -79,6 +83,7 @@ type TyBound struct { } func (TyBound) isTy() {} +func (TyBound) isGenVar() {} func (b TyBound) ToString() string { return b.name } func (b TyBound) Equals(oth any) bool { if bv, ok := oth.(TyBound); ok { @@ -89,7 +94,7 @@ func (b TyBound) Equals(oth any) bool { func (b TyBound) Copy() Ty { return TyBound{b.name, b.index} } func (b TyBound) GetName() string { return b.name } -func (b TyBound) SubstTy(old TyBound, new Ty) Ty { +func (b TyBound) SubstTy(old TyGenVar, new Ty) Ty { if b.Equals(old) { return new } @@ -97,21 +102,38 @@ func (b TyBound) SubstTy(old TyBound, new Ty) Ty { } type TyMeta struct { - name string - index int + name string + index int + formula int // for compatibility with term metas } func (TyMeta) isTy() {} +func (TyMeta) isGenVar() {} func (m TyMeta) ToString() string { return fmt.Sprintf("%s_%d", m.name, m.index) } func (m TyMeta) Equals(oth any) bool { if om, ok := oth.(TyMeta); ok { - return m.name == om.name + return m.name == om.name && m.index == om.index } return false } -func (m TyMeta) Copy() Ty { return TyMeta{m.name, m.index} } +func (m TyMeta) Copy() Ty { return TyMeta{m.name, m.index, m.formula} } + +func (m TyMeta) SubstTy(v TyGenVar, new Ty) Ty { + if m.Equals(v) { + return new + } + return m +} -func (m TyMeta) SubstTy(TyBound, Ty) Ty { return m } +func (m TyMeta) ToTermMeta() Meta { return MakeMeta(m.index, -1, m.name, m.formula, tType) } + +func TyMetaFromMeta(m Meta) TyMeta { + return TyMeta{ + m.name, + m.index, + m.formula, + } +} // Type constructors, e.g., list, option, ... // Include constants, e.g., $i, $o, ... @@ -149,7 +171,7 @@ func (c TyConstr) Args() Lib.List[Ty] { return c.args } -func (c TyConstr) SubstTy(old TyBound, new Ty) Ty { +func (c TyConstr) SubstTy(old TyGenVar, new Ty) Ty { return TyConstr{ c.symbol, Lib.ListMap(c.args, func(t Ty) Ty { return t.SubstTy(old, new) }), @@ -181,7 +203,7 @@ func (p TyProd) Copy() Ty { return TyProd{Lib.ListCpy(p.args)} } -func (p TyProd) SubstTy(old TyBound, new Ty) Ty { +func (p TyProd) SubstTy(old TyGenVar, new Ty) Ty { return TyProd{ Lib.ListMap(p.args, func(t Ty) Ty { return t.SubstTy(old, new) }), } @@ -206,7 +228,7 @@ func (f TyFunc) Copy() Ty { return TyFunc{f.in.Copy(), f.out.Copy()} } -func (f TyFunc) SubstTy(old TyBound, new Ty) Ty { +func (f TyFunc) SubstTy(old TyGenVar, new Ty) Ty { return TyFunc{f.in.SubstTy(old, new), f.out.SubstTy(old, new)} } @@ -232,10 +254,14 @@ func (p TyPi) Copy() Ty { return TyPi{p.vars.Copy(func(x string) string { return x }), p.ty.Copy()} } -func (p TyPi) SubstTy(old TyBound, new Ty) Ty { +func (p TyPi) SubstTy(old TyGenVar, new Ty) Ty { return TyPi{p.vars, p.ty.SubstTy(old, new)} } +func (p TyPi) VarsLen() int { + return p.vars.Len() +} + // Makers func MkTyVar(repr string) Ty { @@ -246,9 +272,9 @@ func MkTyBV(name string, index int) Ty { return TyBound{name, index} } -func MkTyMeta(name string) Ty { +func MkTyMeta(name string, formula int) Ty { meta_mut.Lock() - meta := TyMeta{name, count_meta} + meta := TyMeta{name, count_meta, formula} count_meta += 1 meta_mut.Unlock() return meta @@ -402,3 +428,40 @@ func GetOutTy(ty Ty) Ty { ) return nil } + +func TyToTerm(ty Ty) Term { + switch nty := ty.(type) { + case TyMeta: + return nty.ToTermMeta() + case TyConstr: + return MakerFun( + MakerId(nty.symbol), + Lib.NewList[Ty](), + Lib.ListMap(nty.args, TyToTerm), + ) + } + + Glob.Anomaly( + "AST.Ty", + fmt.Sprintf("Trying to convert the non-atomic (or bound var) type %s to a term", ty.ToString()), + ) + return nil +} + +func TermToTy(trm Term) Ty { + switch t := trm.(type) { + case Meta: + return TyMetaFromMeta(t) + case Fun: + return MkTyConstr( + t.GetID().name, + Lib.ListMap(t.args, TermToTy), + ) + } + + Glob.Anomaly( + "AST.Ty", + fmt.Sprintf("Trying to convert the non-atomic (or bound var) term %s to a type", trm.ToString()), + ) + return nil +} diff --git a/src/AST/typed-vars.go b/src/AST/typed-vars.go index d1bea6af..d3e42e6c 100644 --- a/src/AST/typed-vars.go +++ b/src/AST/typed-vars.go @@ -82,7 +82,7 @@ func (v TypedVar) ToTyBoundVar() TyBound { return MkTyBV(v.name, v.index).(TyBound) } -func (v TypedVar) SubstTy(old TyBound, new Ty) TypedVar { +func (v TypedVar) SubstTy(old TyGenVar, new Ty) TypedVar { return TypedVar{v.name, v.index, v.ty.SubstTy(old, new)} } diff --git a/src/Core/FormListDS.go b/src/Core/FormListDS.go index c07a6662..d3dcb7ca 100644 --- a/src/Core/FormListDS.go +++ b/src/Core/FormListDS.go @@ -86,11 +86,11 @@ func (fl FormListDS) IsEmpty() bool { return fl.GetFL().Empty() } -func (fl FormListDS) Unify(f AST.Form) (bool, []Unif.MatchingSubstitutions) { +func (fl FormListDS) Unify(f AST.Form) (bool, []Unif.MixedSubstitutions) { for _, element := range fl.GetFL().GetSlice() { if element.Equals(f) { - return true, []Unif.MatchingSubstitutions{} + return true, []Unif.MixedSubstitutions{} } } - return false, []Unif.MatchingSubstitutions{} + return false, []Unif.MixedSubstitutions{} } diff --git a/src/Core/global_unifier.go b/src/Core/global_unifier.go index 3657dca0..089d6e42 100644 --- a/src/Core/global_unifier.go +++ b/src/Core/global_unifier.go @@ -41,7 +41,7 @@ import ( "github.com/GoelandProver/Goeland/Unif" ) -type substitutions = Unif.Substitutions +type substitutions = Lib.List[Unif.MixedSubstitution] /* - The unifier type is a type that keeps the substitutions that close the whole subtree. @@ -86,7 +86,7 @@ func (u *Unifier) AddSubstitutions(cleanedSubst, actualSubst substitutions) { } found := false for i, p := range u.localUnifiers { - if p.Fst.Equals(cleanedSubst) { + if Lib.ListEquals(p.Fst, cleanedSubst) { u.localUnifiers[i].Snd = append(u.localUnifiers[i].Snd, actualSubst) found = true } @@ -102,8 +102,8 @@ func (u *Unifier) PruneUncompatibleSubstitutions(subst substitutions) { } res := make([]Glob.Pair[substitutions, []substitutions], 0) for _, p := range u.localUnifiers { - compat, _ := Unif.MergeSubstitutions(subst, p.Fst) - if !compat.Equals(Unif.Failure()) { + _, succeeded := Unif.MergeMixedSubstitutions(subst, p.Fst) + if succeeded { res = append(res, p) } } @@ -115,29 +115,34 @@ func (u Unifier) IsEmpty() bool { } func (u Unifier) ToString() string { - substsToString := func(index int, element Unif.Substitution) string { - return fmt.Sprintf("(%s -> %s)", element.Key().ToString(), element.Value().ToString()) - } str := "object Unifier{" for _, unifier := range u.localUnifiers { - str += "[ " + strings.Join(Glob.MapTo(unifier.Fst, substsToString), ", ") + " ] --> [ " + strings.Join(Glob.MapTo(unifier.Snd, func(_ int, el substitutions) string { - return strings.Join(Glob.MapTo(el, substsToString), " ; ") - }), " ---- ") + " ], " + str += fmt.Sprintf( + "[ %s ] --> [ %s ]", + Lib.ListToString(unifier.Fst, ", ", ""), + strings.Join(Glob.MapTo( + unifier.Snd, + func(_ int, el substitutions) string { + return Lib.ListToString(el, ", ", "") + }), + " ; ", + ), + ) } str += "}" return str } /** Returns a global unifier: MGU of all the unifiers found */ -func (u Unifier) GetUnifier() Unif.Substitutions { +func (u Unifier) GetUnifier() substitutions { if !Glob.GetProof() || len(u.localUnifiers) == 0 { - return Unif.MakeEmptySubstitution() + return Lib.NewList[Unif.MixedSubstitution]() } debug(Lib.MkLazy(func() string { return u.ToString() })) if len(u.localUnifiers) > 0 && len(u.localUnifiers[0].Snd) > 0 { return u.localUnifiers[0].Snd[0] } - return Unif.MakeEmptySubstitution() + return Lib.NewList[Unif.MixedSubstitution]() } func (u Unifier) Copy() Unifier { @@ -148,9 +153,9 @@ func (u Unifier) Copy() Unifier { for i, unif := range u.localUnifiers { copy := []substitutions{} for _, subst := range unif.Snd { - copy = append(copy, subst.Copy()) + copy = append(copy, Lib.ListCpy(subst)) } - newLocalUnifier[i] = Glob.MakePair(unif.Fst.Copy(), copy) + newLocalUnifier[i] = Glob.MakePair(Lib.ListCpy(unif.Fst), copy) } return Unifier{ localUnifiers: newLocalUnifier, @@ -178,12 +183,12 @@ func (u *Unifier) Merge(other Unifier) { for _, locUnif := range u.localUnifiers { for _, unifier := range other.localUnifiers { newUnifs := []substitutions{} - res, _ := Unif.MergeSubstitutions(unifier.Fst.Copy(), locUnif.Fst.Copy()) - if !res.Equals(Unif.Failure()) { + res, succeeded := Unif.MergeMixedSubstitutions(unifier.Fst, locUnif.Fst) + if succeeded { for _, subst := range locUnif.Snd { for _, s := range unifier.Snd { - merge, _ := Unif.MergeSubstitutions(subst.Copy(), s.Copy()) - if !merge.Equals(Unif.Failure()) { + merge, success := Unif.MergeMixedSubstitutions(subst, s) + if success { newUnifs = append(newUnifs, merge) } } @@ -199,9 +204,18 @@ func (u *Unifier) Merge(other Unifier) { func (u *Unifier) PruneMetasInSubsts(metas Lib.Set[AST.Meta]) { for i, unif := range u.localUnifiers { for _, meta := range metas.Elements().GetSlice() { - _, index := unif.Fst.Get(meta) - if index != -1 { - u.localUnifiers[i].Fst.Remove(index) + index := Lib.MkNone[int]() + for j, subst := range unif.Fst.GetSlice() { + switch s := subst.Substitution().(type) { + case Lib.Some[Unif.Substitution]: + if s.Val.Key().Equals(meta) { + index = Lib.MkSome(j) + } + } + } + switch id := index.(type) { + case Lib.Some[int]: + u.localUnifiers[i].Fst.RemoveAt(id.Val) } } } @@ -214,7 +228,7 @@ func (u *Unifier) PruneMetasInSubsts(metas Lib.Set[AST.Meta]) { func appendNewUnifiersIfNeeded(unifiers []Glob.Pair[substitutions, []substitutions], res substitutions, newUnifs []substitutions) []Glob.Pair[substitutions, []substitutions] { for i, unif := range unifiers { - if unif.Fst.Equals(res) { + if Lib.ListEquals(unif.Fst, res) { unifiers[i].Snd = append(unifiers[i].Snd, newUnifs...) return unifiers } diff --git a/src/Core/instanciation.go b/src/Core/instanciation.go index 81cc93aa..4b1373b3 100644 --- a/src/Core/instanciation.go +++ b/src/Core/instanciation.go @@ -82,7 +82,7 @@ func RealInstantiate( var m Lib.Option[AST.Meta] if AST.IsTType(v.GetTy()) { - meta := AST.MkTyMeta(strings.ToUpper(v.GetName())) + meta := AST.MkTyMeta(strings.ToUpper(v.GetName()), index) subForm = subForm.SubstTy(v.ToTyBoundVar(), meta) m = Lib.MkNone[AST.Meta]() } else { diff --git a/src/Core/int_subst_and_form.go b/src/Core/int_subst_and_form.go index a223dae7..7bf53832 100644 --- a/src/Core/int_subst_and_form.go +++ b/src/Core/int_subst_and_form.go @@ -81,8 +81,8 @@ func (s IntSubstAndForm) Copy() IntSubstAndForm { func (s IntSubstAndForm) ToString() string { res := "{ " + strconv.Itoa(s.GetId_rewrite()) + " - " - if !s.GetSaf().GetSubst().IsEmpty() { - res += s.GetSaf().GetSubst().ToString() + if !s.GetSaf().GetSubst().Empty() { + res += Lib.ListToString(s.GetSaf().GetSubst(), ", ", "[]") } res += " - " if !s.GetSaf().GetForm().Empty() { @@ -128,8 +128,8 @@ func CopyIntSubstAndFormList(sl []IntSubstAndForm) []IntSubstAndForm { } /* Get a subst list from SubstAndForm lsit */ -func GetSubstListFromIntSubstAndFormList(l []IntSubstAndForm) []Unif.Substitutions { - res := []Unif.Substitutions{} +func GetSubstListFromIntSubstAndFormList(l []IntSubstAndForm) []Lib.List[Unif.MixedSubstitution] { + res := []Lib.List[Unif.MixedSubstitution]{} for _, saf := range l { res = append(res, saf.GetSaf().GetSubst()) } diff --git a/src/Core/subst_and_form.go b/src/Core/subst_and_form.go index 997a1dd5..53388662 100644 --- a/src/Core/subst_and_form.go +++ b/src/Core/subst_and_form.go @@ -48,27 +48,27 @@ import ( /* Stock the substitution and the corresponding list of formulas */ type SubstAndForm struct { - s Unif.Substitutions + s Lib.List[Unif.MixedSubstitution] f Lib.List[AST.Form] } -func (s SubstAndForm) GetSubst() Unif.Substitutions { - return s.s.Copy() +func (s SubstAndForm) GetSubst() Lib.List[Unif.MixedSubstitution] { + return Lib.ListCpy(s.s) } func (s SubstAndForm) GetForm() Lib.List[AST.Form] { return Lib.ListCpy(s.f) } -func (s *SubstAndForm) SetSubst(subst Unif.Substitutions) { - s.s = subst.Copy() +func (s *SubstAndForm) SetSubst(subst Lib.List[Unif.MixedSubstitution]) { + s.s = Lib.ListCpy(subst) } func (s *SubstAndForm) SetForm(form Lib.List[AST.Form]) { s.f = Lib.ListCpy(form) } func (saf SubstAndForm) IsEmpty() bool { - return saf.s.IsEmpty() && saf.f.Empty() + return saf.s.Empty() && saf.f.Empty() } func (s1 SubstAndForm) Equals(s2 SubstAndForm) bool { - return s1.GetSubst().Equals(s2.GetSubst()) && + return Lib.ListEquals(s1.GetSubst(), s2.GetSubst()) && Lib.ListEquals(s1.GetForm(), s2.GetForm()) } func (s SubstAndForm) Copy() SubstAndForm { @@ -80,8 +80,8 @@ func (s SubstAndForm) Copy() SubstAndForm { } func (s SubstAndForm) ToString() string { res := "{ " - if !s.GetSubst().IsEmpty() { - res += s.GetSubst().ToString() + if !s.GetSubst().Empty() { + res += Lib.ListToString(s.GetSubst(), ", ", "[]") } res += " - " if !s.GetForm().Empty() { @@ -92,11 +92,11 @@ func (s SubstAndForm) ToString() string { return res } -func MakeSubstAndForm(subst Unif.Substitutions, form Lib.List[AST.Form]) SubstAndForm { - return SubstAndForm{subst.Copy(), Lib.ListCpy(form)} +func MakeSubstAndForm(subst Lib.List[Unif.MixedSubstitution], form Lib.List[AST.Form]) SubstAndForm { + return SubstAndForm{Lib.ListCpy(subst), Lib.ListCpy(form)} } func MakeEmptySubstAndForm() SubstAndForm { - return SubstAndForm{Unif.MakeEmptySubstitution(), Lib.NewList[AST.Form]()} + return SubstAndForm{Lib.NewList[Unif.MixedSubstitution](), Lib.NewList[AST.Form]()} } func (s SubstAndForm) AddFormulas(fl Lib.List[AST.Form]) SubstAndForm { formList := s.GetForm() @@ -105,21 +105,15 @@ func (s SubstAndForm) AddFormulas(fl Lib.List[AST.Form]) SubstAndForm { } /* Remove empty substitution from a substitution list */ -func RemoveEmptySubstFromSubstList(sl []Unif.Substitutions) []Unif.Substitutions { - res := []Unif.Substitutions{} - for _, s := range sl { - if !(s.IsEmpty()) { - res = append(res, s) - } - } - return res +func RemoveEmptySubstFromSubstList(sl Lib.List[Lib.List[Unif.MixedSubstitution]]) Lib.List[Lib.List[Unif.MixedSubstitution]] { + return sl.Filter(func(l Lib.List[Unif.MixedSubstitution]) bool { return !l.Empty() }) } /* Remove empty substitution from a substitution list */ func RemoveEmptySubstFromSubstAndFormList(sl []SubstAndForm) []SubstAndForm { res := []SubstAndForm{} for _, s := range sl { - if !(s.GetSubst().IsEmpty()) { + if !(s.GetSubst().Empty()) { res = append(res, s) } } @@ -127,10 +121,10 @@ func RemoveEmptySubstFromSubstAndFormList(sl []SubstAndForm) []SubstAndForm { } /* Get a subst list from SubstAndForm lsit */ -func GetSubstListFromSubstAndFormList(l []SubstAndForm) []Unif.Substitutions { - res := []Unif.Substitutions{} +func GetSubstListFromSubstAndFormList(l []SubstAndForm) Lib.List[Lib.List[Unif.MixedSubstitution]] { + res := Lib.NewList[Lib.List[Unif.MixedSubstitution]]() for _, saf := range l { - res = append(res, saf.GetSubst()) + res.Append(saf.GetSubst()) } return res } @@ -197,9 +191,9 @@ func MergeSubstAndForm(s1, s2 SubstAndForm) (error, SubstAndForm) { return nil, s1 } - new_subst, _ := Unif.MergeSubstitutions(s1.GetSubst().Copy(), s2.GetSubst().Copy()) + new_subst, succeeded := Unif.MergeMixedSubstitutions(s1.GetSubst(), s2.GetSubst()) - if new_subst.Equals(Unif.Failure()) { + if !succeeded { Glob.PrintError("MSAF", fmt.Sprintf("Error : MergeSubstitutions returns failure between : %v and %v \n", s1.ToString(), s2.ToString())) return errors.New("Couldn't merge two substitutions"), MakeEmptySubstAndForm() } diff --git a/src/Core/subst_and_form_and_terms.go b/src/Core/subst_and_form_and_terms.go index 0b72fe73..fcabb51b 100644 --- a/src/Core/subst_and_form_and_terms.go +++ b/src/Core/subst_and_form_and_terms.go @@ -37,32 +37,33 @@ package Core import ( + "github.com/GoelandProver/Goeland/Lib" "github.com/GoelandProver/Goeland/Unif" ) /* Stock the substitution and the corresponding list of formulas */ type SubstAndFormAndTerms struct { - s Unif.Substitutions + s Lib.List[Unif.MixedSubstitution] f FormAndTermsList } -func (s SubstAndFormAndTerms) GetSubst() Unif.Substitutions { - return s.s.Copy() +func (s SubstAndFormAndTerms) GetSubst() Lib.List[Unif.MixedSubstitution] { + return Lib.ListCpy(s.s) } func (s SubstAndFormAndTerms) GetForm() FormAndTermsList { return s.f.Copy() } -func (s *SubstAndFormAndTerms) SetSubst(subst Unif.Substitutions) { - s.s = subst.Copy() +func (s *SubstAndFormAndTerms) SetSubst(subst Lib.List[Unif.MixedSubstitution]) { + s.s = Lib.ListCpy(subst) } func (s *SubstAndFormAndTerms) SetForm(form FormAndTermsList) { s.f = form.Copy() } func (saf SubstAndFormAndTerms) IsEmpty() bool { - return saf.s.IsEmpty() && saf.f.IsEmpty() + return saf.s.Empty() && saf.f.IsEmpty() } func (s1 SubstAndFormAndTerms) Equals(s2 SubstAndFormAndTerms) bool { - return s1.GetSubst().Equals(s2.GetSubst()) && s1.GetForm().Equals(s2.GetForm()) + return Lib.ListEquals(s1.GetSubst(), s2.GetSubst()) && s1.GetForm().Equals(s2.GetForm()) } func (s SubstAndFormAndTerms) Copy() SubstAndFormAndTerms { if s.IsEmpty() { @@ -80,8 +81,8 @@ func (s SubstAndFormAndTerms) ToSubstAndForm() SubstAndForm { } func (s SubstAndFormAndTerms) ToString() string { res := "{ " - if !s.GetSubst().IsEmpty() { - res += s.GetSubst().ToString() + if !s.GetSubst().Empty() { + res += Lib.ListToString(s.GetSubst(), ", ", "[]") } res += " - " if !s.GetForm().IsEmpty() { @@ -92,11 +93,11 @@ func (s SubstAndFormAndTerms) ToString() string { return res } -func MakeSubstAndFormAndTerms(subst Unif.Substitutions, form FormAndTermsList) SubstAndFormAndTerms { - return SubstAndFormAndTerms{subst.Copy(), form.Copy()} +func MakeSubstAndFormAndTerms(subst Lib.List[Unif.MixedSubstitution], form FormAndTermsList) SubstAndFormAndTerms { + return SubstAndFormAndTerms{Lib.ListCpy(subst), form.Copy()} } func MakeEmptySubstAndFormAndTerms() SubstAndFormAndTerms { - return SubstAndFormAndTerms{Unif.MakeEmptySubstitution(), FormAndTermsList{}} + return SubstAndFormAndTerms{Lib.NewList[Unif.MixedSubstitution](), FormAndTermsList{}} } /* Check if a substitution is inside a list of SubstAndForm */ diff --git a/src/Core/substitutions_search.go b/src/Core/substitutions_search.go index 2b17a874..b241d6c5 100644 --- a/src/Core/substitutions_search.go +++ b/src/Core/substitutions_search.go @@ -46,18 +46,21 @@ import ( ) /* Return the list of metavariable from a substitution */ -func GetMetaFromSubst(subs Unif.Substitutions) Lib.Set[AST.Meta] { +func GetMetaFromSubst(subs Lib.List[Unif.MixedSubstitution]) Lib.Set[AST.Meta] { res := Lib.EmptySet[AST.Meta]() - for _, singleSubs := range subs { - meta, term := singleSubs.Get() - res = res.Add(meta) + for _, singleSubs := range subs.GetSlice() { + switch s := singleSubs.Substitution().(type) { + case Lib.Some[Unif.Substitution]: + meta, term := s.Val.Get() + res = res.Add(meta) - switch typedTerm := term.(type) { - case AST.Meta: - res = res.Add(typedTerm) - case AST.Fun: - res = res.Union(AST.GetMetasOfList(typedTerm.GetArgs())) + switch typedTerm := term.(type) { + case AST.Meta: + res = res.Add(typedTerm) + case AST.Fun: + res = res.Union(AST.GetMetasOfList(typedTerm.GetArgs())) + } } } @@ -65,7 +68,10 @@ func GetMetaFromSubst(subs Unif.Substitutions) Lib.Set[AST.Meta] { } /* Remove substitution without mm */ -func RemoveElementWithoutMM(subs Unif.Substitutions, mm Lib.Set[AST.Meta]) Unif.Substitutions { +func RemoveElementWithoutMM( + subs Lib.List[Unif.MixedSubstitution], + mm Lib.Set[AST.Meta], +) Lib.List[Unif.MixedSubstitution] { debug(Lib.MkLazy(func() string { return fmt.Sprintf( "MM : %v", @@ -74,8 +80,8 @@ func RemoveElementWithoutMM(subs Unif.Substitutions, mm Lib.Set[AST.Meta]) Unif. })) res := Unif.Substitutions{} + subst_to_reorganize := Unif.Substitutions{} - subsToReorganize := Unif.Substitutions{} relevantMetas := mm.Copy() hasChanged := true @@ -87,50 +93,59 @@ func RemoveElementWithoutMM(subs Unif.Substitutions, mm Lib.Set[AST.Meta]) Unif. Lib.ListToString(relevantMetas.Elements(), ",", "[]"), ) })) - for _, singleSubs := range subs { - meta, term := singleSubs.Get() - - switch typedTerm := term.(type) { - case AST.Meta: - switch { - case relevantMetas.Contains(meta) && - relevantMetas.Contains(typedTerm): - res.Set(meta, typedTerm) - - case relevantMetas.Contains(meta) && - relevantMetas.Contains(typedTerm): - subsToReorganize.Set(meta, typedTerm) - } + for _, singleSubs := range subs.GetSlice() { + switch single_subst := singleSubs.Substitution().(type) { + case Lib.Some[Unif.Substitution]: + meta, term := single_subst.Val.Get() + + switch typedTerm := term.(type) { + case AST.Meta: + switch { + case relevantMetas.Contains(meta) && + relevantMetas.Contains(typedTerm): + res.Set(meta, typedTerm) + + case relevantMetas.Contains(meta) && + relevantMetas.Contains(typedTerm): + subst_to_reorganize.Set(meta, typedTerm) + } - default: - if relevantMetas.Contains(meta) { - res.Set(meta, term) - for _, candidateMeta := range term.GetMetas().Elements().GetSlice() { - if !relevantMetas.Contains(candidateMeta) { - hasChanged = true + default: + if relevantMetas.Contains(meta) { + res.Set(meta, term) + for _, candidateMeta := range term.GetMetas().Elements().GetSlice() { + if !relevantMetas.Contains(candidateMeta) { + hasChanged = true + } } + relevantMetas = relevantMetas.Union(term.GetMetas()) } - relevantMetas = relevantMetas.Union(term.GetMetas()) } } } } debug( - Lib.MkLazy(func() string { return fmt.Sprintf("Subst intermédiaire res : %v", res.ToString()) }), + Lib.MkLazy(func() string { + return fmt.Sprintf( + "Intermediary subst res : %s", + res.ToString(), + ) + }), ) debug( Lib.MkLazy(func() string { return fmt.Sprintf( - "Subst intermédiaire subst_to_reorganize : %v", - subsToReorganize.ToString()) + "Intermediary subst subst_to_reorganize : %s", + subst_to_reorganize.ToString(), + ) }), ) - subsToReorganize = ReorganizeSubstitution(subsToReorganize) - Unif.EliminateMeta(&subsToReorganize) - Unif.Eliminate(&subsToReorganize) - ms, _ := Unif.MergeSubstitutions(res, subsToReorganize) + subst_to_reorganize = ReorganizeSubstitution(subst_to_reorganize) + Unif.EliminateMeta(&subst_to_reorganize) + Unif.Eliminate(&subst_to_reorganize) + ms, _ := Unif.MergeSubstitutions(res, subst_to_reorganize) debug( Lib.MkLazy(func() string { return fmt.Sprintf("Finale subst : %v", ms.ToString()) }), @@ -140,13 +155,25 @@ func RemoveElementWithoutMM(subs Unif.Substitutions, mm Lib.Set[AST.Meta]) Unif. Glob.PrintError("REWM", "MergeSubstitutions returns failure") } - return ms + result := Lib.NewList[Unif.MixedSubstitution]() + for _, unif := range ms { + result.Append(Unif.MkMixedFromSubst(unif)) + } + + for _, s := range subs.GetSlice() { + switch subst := s.TySubstitution().(type) { + case Lib.Some[Unif.TySubstitution]: + result.Append(Unif.MkMixedFromTy(subst.Val)) + } + } + return result } -/* * -* Take a substitution wich conatins elements like (meta_mother, meta_current), returning only relevante substitution like (meta_mother, meta_mother) -* (X, X2) (Y, X2) -> (X, Y) +/** + * Take a substitution wich conatins elements like (meta_mother, meta_current), returning only + * relevant substitutions like (meta_mother, meta_mother) + * e.g., (X, X2) (Y, X2) -> (X, Y) **/ func ReorganizeSubstitution(subs Unif.Substitutions) Unif.Substitutions { res := Unif.Substitutions{} @@ -172,16 +199,22 @@ func ReorganizeSubstitution(subs Unif.Substitutions) Unif.Substitutions { } /* Check if a substitution contains a metavirbale which is inside a given list of metavariable (check for the key, not the value) */ -func ContainsMetaMother(s Unif.Substitutions, mm Lib.Set[AST.Meta]) bool { - for _, subst := range s { - k, v := subst.Get() - if mm.Contains(k) { +func ContainsMetaMother(s Lib.List[Unif.MixedSubstitution], mm Lib.Set[AST.Meta]) bool { + for _, subst := range s.GetSlice() { + switch s := subst.Substitution().(type) { + case Lib.None[Unif.Substitution]: + // In this case, [s] is a TySubstitution and hence it always contains a meta from the top level return true - } else { - switch vtype := v.(type) { - case AST.Meta: - if mm.Contains(vtype) { - return true + case Lib.Some[Unif.Substitution]: + k, v := s.Val.Get() + if mm.Contains(k) { + return true + } else { + switch vtype := v.(type) { + case AST.Meta: + if mm.Contains(vtype) { + return true + } } } } @@ -218,7 +251,7 @@ func ApplySubstitutionOnTerm(old_symbol AST.Meta, new_symbol, t AST.Term) AST.Te /* Apply substitutions on a list of terms */ func ApplySubstitutionsOnTermList( - s Unif.Substitutions, + s Lib.List[Unif.MixedSubstitution], tl Lib.List[AST.Term], ) Lib.List[AST.Term] { res := Lib.MkList[AST.Term](tl.Len()) @@ -231,17 +264,23 @@ func ApplySubstitutionsOnTermList( return res } -func ApplySubstitutionsOnTerm(s Unif.Substitutions, t AST.Term) AST.Term { - if t != nil { - term_res := t.Copy() - for _, subst := range s { - old_symbol, new_symbol := subst.Get() - term_res = ApplySubstitutionOnTerm(old_symbol, new_symbol, term_res) +func ApplySubstitutionsOnTerm(substs Lib.List[Unif.MixedSubstitution], t AST.Term) AST.Term { + if t == nil { + return t + } + + for _, subst := range substs.GetSlice() { + switch s := subst.GetMixed().(type) { + case Lib.Left[Unif.TySubstitution, Unif.Substitution]: + meta, ty := s.Val.Get() + t = t.SubstTy(meta, ty) + case Lib.Right[Unif.TySubstitution, Unif.Substitution]: + meta, term := s.Val.Get() + t = t.ReplaceSubTermBy(meta, term) } - return term_res - } else { - return nil } + + return t } /* Apply substElement on a term list */ @@ -259,63 +298,29 @@ func ApplySubstitutionOnTermList( return res } -/* Apply a substitution on a formula */ -func ApplySubstitutionOnFormula(old_symbol AST.Meta, new_symbol AST.Term, f AST.Form) AST.Form { - var res AST.Form - - switch nf := f.(type) { - case AST.Pred: - res = AST.MakePred( - nf.GetIndex(), - nf.GetID(), - nf.GetTyArgs(), - ApplySubstitutionOnTermList(old_symbol, new_symbol, nf.GetArgs()), - ) - case AST.Not: - res = AST.MakeNot(f.GetIndex(), ApplySubstitutionOnFormula(old_symbol, new_symbol, nf.GetForm())) - case AST.And: - res_tmp := Lib.NewList[AST.Form]() - for _, val := range nf.GetChildFormulas().GetSlice() { - res_tmp.Append(ApplySubstitutionOnFormula(old_symbol, new_symbol, val)) - } - res = AST.MakeAnd(f.GetIndex(), res_tmp) - case AST.Or: - res_tmp := Lib.NewList[AST.Form]() - for _, val := range nf.GetChildFormulas().GetSlice() { - res_tmp.Append(ApplySubstitutionOnFormula(old_symbol, new_symbol, val)) - } - res = AST.MakeOr(f.GetIndex(), res_tmp) - case AST.Imp: - res = AST.MakeImp(f.GetIndex(), ApplySubstitutionOnFormula(old_symbol, new_symbol, nf.GetF1()), ApplySubstitutionOnFormula(old_symbol, new_symbol, nf.GetF2())) - case AST.Equ: - res = AST.MakeEqu(f.GetIndex(), ApplySubstitutionOnFormula(old_symbol, new_symbol, nf.GetF1()), ApplySubstitutionOnFormula(old_symbol, new_symbol, nf.GetF2())) - case AST.Ex: - res = AST.MakeEx(f.GetIndex(), nf.GetVarList(), ApplySubstitutionOnFormula(old_symbol, new_symbol, nf.GetForm())) - case AST.All: - res = AST.MakeAll(f.GetIndex(), nf.GetVarList(), ApplySubstitutionOnFormula(old_symbol, new_symbol, nf.GetForm())) - default: - res = f +/* Apply substitutions on Formula */ +func ApplySubstitutionsOnFormula(s Lib.List[Unif.MixedSubstitution], f AST.Form) AST.Form { + // FIXME: check that line, it shouldn't happen + if f == nil { + return f } - return res -} - -/* Apply substitutions on Formula */ -func ApplySubstitutionsOnFormula(s Unif.Substitutions, f AST.Form) AST.Form { - if f != nil { - form_res := f.Copy() - for _, subst := range s { - old_symbol, new_symbol := subst.Get() - form_res = ApplySubstitutionOnFormula(old_symbol, new_symbol, form_res) + for _, subst := range s.GetSlice() { + switch s := subst.GetMixed().(type) { + case Lib.Left[Unif.TySubstitution, Unif.Substitution]: + meta, ty := s.Val.Get() + f = f.SubstTy(meta, ty) + case Lib.Right[Unif.TySubstitution, Unif.Substitution]: + meta, term := s.Val.Get() + f = f.ReplaceMetaByTerm(meta, term) } - return form_res - } else { - return nil } + + return f } /* For each element of the substitution, apply it on the entire formula list */ -func ApplySubstitutionsOnFormulaList(s Unif.Substitutions, lf Lib.List[AST.Form]) Lib.List[AST.Form] { +func ApplySubstitutionsOnFormulaList(s Lib.List[Unif.MixedSubstitution], lf Lib.List[AST.Form]) Lib.List[AST.Form] { lf_res := Lib.NewList[AST.Form]() for _, f := range lf.GetSlice() { new_form := ApplySubstitutionsOnFormula(s, f) @@ -326,20 +331,12 @@ func ApplySubstitutionsOnFormulaList(s Unif.Substitutions, lf Lib.List[AST.Form] } /* Apply substitutions on FormAndTerm */ -func ApplySubstitutionsOnFormAndTerms(s Unif.Substitutions, fat FormAndTerms) FormAndTerms { - // if fat != FormAndTerms{} { - form_res := fat.GetForm() - tl_res := fat.GetTerms() - for _, subst := range s { - old_symbol, new_symbol := subst.Get() - form_res = ApplySubstitutionOnFormula(old_symbol, new_symbol, form_res) - //tl_res = ApplySubstitutionOnTermList(old_symbol, new_symbol, tl_res) - } - return MakeFormAndTerm(form_res, tl_res) +func ApplySubstitutionsOnFormAndTerms(s Lib.List[Unif.MixedSubstitution], fat FormAndTerms) FormAndTerms { + return MakeFormAndTerm(ApplySubstitutionsOnFormula(s, fat.GetForm()), fat.GetTerms()) } /* For each element of the substitution, apply it on the entire formAndTerms list */ -func ApplySubstitutionsOnFormAndTermsList(s Unif.Substitutions, lf FormAndTermsList) FormAndTermsList { +func ApplySubstitutionsOnFormAndTermsList(s Lib.List[Unif.MixedSubstitution], lf FormAndTermsList) FormAndTermsList { lf_res := MakeEmptyFormAndTermsList() for _, f := range lf { new_form := ApplySubstitutionsOnFormAndTerms(s, f) @@ -350,7 +347,7 @@ func ApplySubstitutionsOnFormAndTermsList(s Unif.Substitutions, lf FormAndTermsL } /* Apply a substitution on a metaGenerator list */ -func ApplySubstitutionOnMetaGenList(s Unif.Substitutions, lf []MetaGen) []MetaGen { +func ApplySubstitutionOnMetaGenList(s Lib.List[Unif.MixedSubstitution], lf []MetaGen) []MetaGen { lf_res := []MetaGen{} for _, f := range lf { new_form := ApplySubstitutionOnMetaGen(s, f) @@ -362,35 +359,35 @@ func ApplySubstitutionOnMetaGenList(s Unif.Substitutions, lf []MetaGen) []MetaGe } /* Apply a substitution on a metaGen form */ -func ApplySubstitutionOnMetaGen(s Unif.Substitutions, mg MetaGen) MetaGen { - form_res := mg.GetForm().GetForm() - terms_res := mg.GetForm().Terms - for _, subst := range s { - old_symbol, new_symbol := subst.Get() - form_res = ApplySubstitutionOnFormula(old_symbol, new_symbol, form_res) - terms_res = ApplySubstitutionOnTermList(old_symbol, new_symbol, terms_res) - } - return MakeMetaGen(MakeFormAndTerm(form_res, terms_res), mg.GetCounter()) +func ApplySubstitutionOnMetaGen(s Lib.List[Unif.MixedSubstitution], mg MetaGen) MetaGen { + return MakeMetaGen(MakeFormAndTerm( + ApplySubstitutionsOnFormula(s, mg.GetForm().GetForm()), + ApplySubstitutionsOnTermList(s, mg.f.GetTerms())), mg.GetCounter()) } /* Dispatch a list of substitution : containing mm or not */ -func DispatchSubst(subsList []Unif.Substitutions, mm Lib.Set[AST.Meta]) ([]Unif.Substitutions, []Unif.Substitutions, []Unif.Substitutions) { - var subsWithMM []Unif.Substitutions - var subsWithMMUncleared []Unif.Substitutions - var subsWithoutMM []Unif.Substitutions - - for _, subs := range subsList { +func DispatchSubst( + subsList Lib.List[Lib.List[Unif.MixedSubstitution]], + mm Lib.Set[AST.Meta], +) (Lib.List[Lib.List[Unif.MixedSubstitution]], + Lib.List[Lib.List[Unif.MixedSubstitution]], + Lib.List[Lib.List[Unif.MixedSubstitution]]) { + subsWithMM := Lib.NewList[Lib.List[Unif.MixedSubstitution]]() + subsWithMMUncleared := Lib.NewList[Lib.List[Unif.MixedSubstitution]]() + subsWithoutMM := Lib.NewList[Lib.List[Unif.MixedSubstitution]]() + + for _, subs := range subsList.GetSlice() { removedSubs := subs if Glob.IsDestructive() { removedSubs = RemoveElementWithoutMM(subs, mm) } - if !removedSubs.IsEmpty() { - subsWithMM = Unif.AppendIfNotContainsSubst(subsWithMM, removedSubs) - subsWithMMUncleared = Unif.AppendIfNotContainsSubst(subsWithMMUncleared, subs) + if !removedSubs.Empty() { + subsWithMM.Add(Lib.ListEquals, removedSubs) + subsWithMMUncleared.Add(Lib.ListEquals, subs) } else { - subsWithoutMM = Unif.AppendIfNotContainsSubst(subsWithoutMM, subs) + subsWithoutMM.Add(Lib.ListEquals, subs) } } diff --git a/src/Lib/either.go b/src/Lib/either.go new file mode 100644 index 00000000..531524c3 --- /dev/null +++ b/src/Lib/either.go @@ -0,0 +1,103 @@ +/** +* Copyright 2022 by the authors (see AUTHORS). +* +* Goéland is an automated theorem prover for first order logic. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +**/ + +package Lib + +import ( + "fmt" +) + +/* This file implements the Either type (sum type). */ + +type Either[A, B any] interface { + isEither() +} + +type Left[A, B any] struct { + Val A +} + +type Right[A, B any] struct { + Val B +} + +func (Left[A, B]) isEither() {} +func (Right[A, B]) isEither() {} + +func MkLeft[A, B any](x A) Either[A, B] { + return Left[A, B]{Val: x} +} + +func MkRight[A, B any](y B) Either[A, B] { + return Right[A, B]{Val: y} +} + +func EitherToString[A, B Stringable](u Either[A, B], left, right string) string { + switch x := u.(type) { + case Left[A, B]: + return fmt.Sprintf("%s(%s)", left, x.Val.ToString()) + case Right[A, B]: + return fmt.Sprintf("%s(%s)", right, x.Val.ToString()) + } + return "" +} + +func EitherEquals[A, B Comparable](u, v Either[A, B]) bool { + switch x := u.(type) { + case Left[A, B]: + switch y := v.(type) { + case Left[A, B]: + return x.Val.Equals(y.Val) + case Right[A, B]: + return false + } + case Right[A, B]: + switch y := v.(type) { + case Left[A, B]: + return false + case Right[A, B]: + return x.Val.Equals(y.Val) + } + } + + return false +} + +func EitherCpy[A Copyable[A], B Copyable[B]](u Either[A, B]) Either[A, B] { + switch x := u.(type) { + case Left[A, B]: + return MkLeft[A, B](x.Val.Copy()) + case Right[A, B]: + return MkRight[A, B](x.Val.Copy()) + } + return u +} diff --git a/src/Lib/list.go b/src/Lib/list.go index 8aa9a881..14a483e8 100644 --- a/src/Lib/list.go +++ b/src/Lib/list.go @@ -230,6 +230,16 @@ func (l List[T]) Any(pred Func[T, bool]) bool { return false } +func (l List[T]) Filter(pred Func[T, bool]) List[T] { + res := NewList[T]() + for _, el := range l.values { + if pred(el) { + res.Append(el) + } + } + return res +} + func ToStrictlyOrderedList[T StrictlyOrdered](l List[T]) StrictlyOrderedList[T] { return StrictlyOrderedList[T]{values: l} } diff --git a/src/Mods/assisted/assistant.go b/src/Mods/assisted/assistant.go index 1064567e..5383d608 100644 --- a/src/Mods/assisted/assistant.go +++ b/src/Mods/assisted/assistant.go @@ -38,6 +38,7 @@ import ( "github.com/GoelandProver/Goeland/Core" "github.com/GoelandProver/Goeland/Glob" + "github.com/GoelandProver/Goeland/Lib" "github.com/GoelandProver/Goeland/Search" "github.com/GoelandProver/Goeland/Unif" ) @@ -185,7 +186,8 @@ func selectStatus() int { func printFormListFromState(st *Search.State, id int) { fmt.Printf("\nState nº%d:\n", id) - printSubList("Applied subs", st.GetAppliedSubst().GetSubst()) + // FIXME: why is this all fmt.Printf? + fmt.Printf("Applied subs: %s", Lib.ListToString(st.GetAppliedSubst().GetSubst(), ", ", "(empty subst)")) printSubList("X - Atomic", st.GetAtomic()) printSubList("A - Alpha", st.GetAlpha()) printSubList("B - Beta", st.GetBeta()) @@ -211,15 +213,15 @@ func printSubList[T Glob.Stringable](title string, list []T) { func printGoelandChoice(st *Search.State) { found := false - allSubs := []Unif.Substitutions{} + allSubs := Lib.NewList[Lib.List[Unif.MixedSubstitution]]() withSubs := true for _, form := range st.GetAtomic() { canClose, subs := Search.ApplyClosureRules(form.GetForm(), st) if canClose { found = true - if len(subs) > 0 && !subs[0].IsEmpty() { - allSubs = append(allSubs, subs...) + if !subs.Empty() && !subs.At(0).Empty() { + allSubs.Append(subs.GetSlice()...) } else { withSubs = false } @@ -229,7 +231,7 @@ func printGoelandChoice(st *Search.State) { if found { str := " └ Goéland would apply the Closure rule" if withSubs { - str += " with the following substitution: " + allSubs[0].ToString() + str += " with the following substitution: " + Lib.ListToString(allSubs.At(0), ", ", "(empty subst)") } else { str += " without any subsitutions" } @@ -358,14 +360,17 @@ func selectFormula(forms Core.FormAndTermsList) int { func selectSubstitution(substs []Core.SubstAndForm) int { fmt.Printf("Found closure rule with substitution that is used elsewhere.\n") fmt.Printf("Here is the list of possible substitutions :\n") - uniqueSubs := []Unif.Substitutions{} + uniqueSubs := Lib.NewList[Lib.List[Unif.MixedSubstitution]]() for _, sub := range substs { - uniqueSubs = Unif.AppendIfNotContainsSubst(uniqueSubs, sub.GetSubst()) + uniqueSubs.Add( + Lib.ListEquals[Unif.MixedSubstitution], + sub.GetSubst(), + ) } - for i, elem := range uniqueSubs { - fmt.Printf("[%d] %v\n", i, elem.ToString()) + for i, elem := range uniqueSubs.GetSlice() { + fmt.Printf("[%d] %v\n", i, Lib.ListToString(elem, ", ", "(empty subst)")) } isSubstitutionValid := false @@ -373,8 +378,10 @@ func selectSubstitution(substs []Core.SubstAndForm) int { for !isSubstitutionValid { fmt.Printf("Select a substitution ~> ") fmt.Scanf("%d", &choice) - if choice < len(uniqueSubs) && choice >= 0 { - fmt.Printf("You selected the substitution %v.\n", uniqueSubs[choice].ToString()) + if choice < uniqueSubs.Len() && choice >= 0 { + fmt.Printf("You selected the substitution %v.\n", + Lib.ListToString(uniqueSubs.At(choice), ", ", "(empty subst)"), + ) isSubstitutionValid = true fmt.Println("-------------------------") } else { diff --git a/src/Mods/assisted/rules.go b/src/Mods/assisted/rules.go index 9e288dc6..cdce6820 100644 --- a/src/Mods/assisted/rules.go +++ b/src/Mods/assisted/rules.go @@ -81,7 +81,12 @@ func applyAtomicRule(state Search.State, fatherId uint64, c Search.Communication clos_res_after_apply_subst, subst_after_apply_subst := Search.ApplyClosureRules(f.GetForm(), &state) if clos_res_after_apply_subst { - boolSubsts, resSubsts := searchAlgo.ManageClosureRule(fatherId, &state, c, Unif.CopySubstList(subst_after_apply_subst), f.Copy(), nodeId, originalNodeId) + boolSubsts, resSubsts := searchAlgo.ManageClosureRule( + fatherId, + &state, + c, + subst_after_apply_subst.Copy(Lib.ListCpy[Unif.MixedSubstitution]), + f.Copy(), nodeId, originalNodeId) if !boolSubsts { finalBool = false } diff --git a/src/Mods/dmt/rewrite.go b/src/Mods/dmt/rewrite.go index 3fce7f14..c72375f3 100644 --- a/src/Mods/dmt/rewrite.go +++ b/src/Mods/dmt/rewrite.go @@ -60,7 +60,11 @@ func rewriteGeneric(tree Unif.DataStructure, atomic AST.Form, form AST.Form, pol var err error = nil if isUnified, unif := tree.Unify(form); isUnified { - rewritten, err = getRewrittenFormulas(rewritten, unif, atomic, polarity) + unif_substs := []Unif.MatchingSubstitutions{} + for _, substs := range unif { + unif_substs = append(unif_substs, substs.MatchingSubstitutions()) + } + rewritten, err = getRewrittenFormulas(rewritten, unif_substs, atomic, polarity) } else { rewritten = rewriteFailure(atomic) } @@ -86,7 +90,9 @@ func getRewrittenFormulas(rewritten []Core.IntSubstAndForm, unif []Unif.Matching func addRewrittenFormulas(rewritten []Core.IntSubstAndForm, unif Unif.MatchingSubstitutions, atomic AST.Form, equivalence Lib.List[AST.Form]) []Core.IntSubstAndForm { // Keep only useful substitutions - useful_subst := Core.RemoveElementWithoutMM(unif.GetSubst(), atomic.GetMetas()) + useful_subst := Unif.ToSubstitutions( + Core.RemoveElementWithoutMM(Unif.FromSubstitutions(unif.GetSubst()), atomic.GetMetas()), + ) meta_search := atomic.GetMetas() if !checkMetaAreFromSearch(meta_search, useful_subst) { Glob.PrintError("DMT", fmt.Sprintf("There is at least one meta in final subst which is not from search : %v - %v - %v", useful_subst.ToString(), atomic.ToString(), unif.GetForm().ToString())) @@ -121,12 +127,19 @@ func getAtomAndPolarity(atom AST.Form) (AST.Form, bool) { func rewriteFailure(atomic AST.Form) []Core.IntSubstAndForm { return []Core.IntSubstAndForm{ - Core.MakeIntSubstAndForm(-1, Core.MakeSubstAndForm(Unif.Failure(), Lib.MkListV(atomic))), + Core.MakeIntSubstAndForm( + -1, + Core.MakeSubstAndForm(Lib.MkListV(Unif.MkMixedFromSubst(Unif.Failure()[0])), Lib.MkListV(atomic)), + ), } } func addUnifToAtomics(atomics []Core.IntSubstAndForm, candidate AST.Form, unif Unif.MatchingSubstitutions) []Core.IntSubstAndForm { - substAndForm := Core.MakeSubstAndForm(unif.GetSubst().Copy(), Lib.MkListV(candidate)) + mixed := Lib.NewList[Unif.MixedSubstitution]() + for _, subst := range unif.GetSubst() { + mixed.Append(Unif.MkMixedFromSubst(subst)) + } + substAndForm := Core.MakeSubstAndForm(mixed, Lib.MkListV(candidate)) if isBotOrTop(candidate) { atomics = Core.InsertFirstIntSubstAndFormList(atomics, Core.MakeIntSubstAndForm(unif.GetForm().GetIndex(), substAndForm)) } else { diff --git a/src/Mods/dmt/rewritten.go b/src/Mods/dmt/rewritten.go index d21c7e8d..a68b16f3 100644 --- a/src/Mods/dmt/rewritten.go +++ b/src/Mods/dmt/rewritten.go @@ -39,7 +39,6 @@ package dmt import ( "github.com/GoelandProver/Goeland/AST" - "github.com/GoelandProver/Goeland/Core" "github.com/GoelandProver/Goeland/Glob" "github.com/GoelandProver/Goeland/Lib" "github.com/GoelandProver/Goeland/Unif" @@ -48,7 +47,7 @@ import ( func substitute(form AST.Form, subst Unif.Substitutions) AST.Form { for _, s := range subst { old_symbol, new_symbol := s.Get() - form = Core.ApplySubstitutionOnFormula(old_symbol, new_symbol, form) + form = form.ReplaceMetaByTerm(old_symbol, new_symbol) } return form } diff --git a/src/Mods/equality/bse/equality.go b/src/Mods/equality/bse/equality.go index b13b3020..d0c1b2f2 100644 --- a/src/Mods/equality/bse/equality.go +++ b/src/Mods/equality/bse/equality.go @@ -68,12 +68,22 @@ func TryEquality(atomics_for_dmt Core.FormAndTermsList, st Search.State, new_ato debug(Lib.MkLazy(func() string { return "EQ is applicable !" })) atomics_plus_dmt := append(st.GetAtomic(), atomics_for_dmt...) res_eq, subst_eq := EqualityReasoning(st.GetEqStruct(), st.GetTreePos(), st.GetTreeNeg(), atomics_plus_dmt.ExtractForms(), original_node_id) + + send_to_proof_search := Lib.NewList[Lib.List[Unif.MixedSubstitution]]() + for _, substs := range subst_eq { + local_list := Lib.NewList[Unif.MixedSubstitution]() + for _, subst := range substs { + local_list.Append(Unif.MkMixedFromSubst(subst)) + } + send_to_proof_search.Append(local_list) + } + if res_eq { Search.UsedSearch.ManageClosureRule( father_id, &st, cha, - subst_eq, + send_to_proof_search, Core.MakeFormAndTerm( AST.EmptyPredEq, Lib.NewList[AST.Term](), diff --git a/src/Mods/equality/bse/equality_rules_try_apply.go b/src/Mods/equality/bse/equality_rules_try_apply.go index 13f493fa..b24dda94 100644 --- a/src/Mods/equality/bse/equality_rules_try_apply.go +++ b/src/Mods/equality/bse/equality_rules_try_apply.go @@ -229,8 +229,7 @@ func checkUnifInTree(t AST.Term, tree Unif.DataStructure) (bool, Lib.List[AST.Te for _, subst := range ms { debug( Lib.MkLazy(func() string { - return fmt.Sprintf("Unif found with %v :%v", - subst.GetForm().ToString(), subst.GetSubst().ToString()) + return fmt.Sprintf("Unif found with: %s", subst.ToString()) }), ) result_list.Append(subst.GetForm().(Unif.TermForm).GetTerm()) diff --git a/src/Mods/equality/bse/equality_types.go b/src/Mods/equality/bse/equality_types.go index 775b1fae..d0ce8462 100644 --- a/src/Mods/equality/bse/equality_types.go +++ b/src/Mods/equality/bse/equality_types.go @@ -120,7 +120,7 @@ func (equs Equalities) removeHalf() Equalities { /* Retrieve equalities from a datastructure */ func retrieveEqualities(dt Unif.DataStructure) Equalities { res := Equalities{} - meta_ty := AST.MkTyMeta("META_TY_EQ") + meta_ty := AST.MkTyMeta("META_TY_EQ", -1) MetaEQ1 := AST.MakerMeta("METAEQ1", -1, meta_ty) MetaEQ2 := AST.MakerMeta("METAEQ2", -1, meta_ty) @@ -134,7 +134,7 @@ func retrieveEqualities(dt Unif.DataStructure) Equalities { _, eq_list := dt.Unify(eq_pred) for _, ms := range eq_list { - ms_ordered := orderSubstForRetrieve(ms.GetSubst(), MetaEQ1, MetaEQ2) + ms_ordered := orderSubstForRetrieve(ms.MatchingSubstitutions().GetSubst(), MetaEQ1, MetaEQ2) eq1_term, ok_t1 := ms_ordered.Get(MetaEQ1) if ok_t1 == -1 { Glob.PrintError("RI", "Meta_eq_1 not found in map") @@ -151,7 +151,7 @@ func retrieveEqualities(dt Unif.DataStructure) Equalities { /* Retrieve inequalities from a datastructure */ func retrieveInequalities(dt Unif.DataStructure) Inequalities { res := Inequalities{} - meta_ty := AST.MkTyMeta("META_TY_NEQ") + meta_ty := AST.MkTyMeta("META_TY_NEQ", -1) MetaNEQ1 := AST.MakerMeta("META_NEQ_1", -1, meta_ty) MetaNEQ2 := AST.MakerMeta("META_NEQ_2", -1, meta_ty) @@ -165,7 +165,7 @@ func retrieveInequalities(dt Unif.DataStructure) Inequalities { _, neq_list := dt.Unify(neq_pred) for _, ms := range neq_list { - ms_ordered := orderSubstForRetrieve(ms.GetSubst(), MetaNEQ1, MetaNEQ2) + ms_ordered := orderSubstForRetrieve(ms.MatchingSubstitutions().GetSubst(), MetaNEQ1, MetaNEQ2) neq1_term, ok_t1 := ms_ordered.Get(MetaNEQ1) if ok_t1 == -1 { Glob.PrintError("RI", "Meta_eq_1 not found in map") diff --git a/src/Search/child_management.go b/src/Search/child_management.go index a02c580c..91df332c 100644 --- a/src/Search/child_management.go +++ b/src/Search/child_management.go @@ -127,8 +127,10 @@ func (ds *destructiveSearch) childrenClosedByThemselves(args wcdArgs, proofChild // Remove all the metavariables that have been introduced in this node: the parent do not know them. substForFather := Core.RemoveElementWithoutMM(args.st.GetAppliedSubst().GetSubst(), args.st.GetMM()) - if !substForFather.IsEmpty() { - args.st.SetSubstsFound([]Core.SubstAndForm{Core.MakeSubstAndForm(substForFather, args.st.GetAppliedSubst().GetForm())}) + if !substForFather.Empty() { + args.st.SetSubstsFound( + []Core.SubstAndForm{Core.MakeSubstAndForm(substForFather, args.st.GetAppliedSubst().GetForm())}, + ) } else { args.st.SetSubstsFound([]Core.SubstAndForm{}) } @@ -159,8 +161,9 @@ func (ds *destructiveSearch) passSubstToParent(args wcdArgs, proofChildren [][]P debug( Lib.MkLazy(func() string { return fmt.Sprintf( - "All children agree on the substitution(s) : %v", - Unif.SubstListToString(Core.GetSubstListFromSubstAndFormList(substs))) + "All children agree on the substitution(s) : %s", + Unif.SubstsToString(Core.GetSubstListFromSubstAndFormList(substs)), + ) }), ) @@ -177,14 +180,15 @@ func (ds *destructiveSearch) passSubstToParent(args wcdArgs, proofChildren [][]P // Remove all the metas introduced by the current node to only retrieve relevant ones for the parent. resultingSubstsAndForms := []Core.SubstAndForm{} - resultingSubsts := []Unif.Substitutions{} + resultingSubsts := Lib.NewList[Lib.List[Unif.MixedSubstitution]]() for _, subst := range substs { debug( Lib.MkLazy(func() string { return fmt.Sprintf( "Check the susbt, remove useless element and merge with applied subst :%v", - subst.GetSubst().ToString()) + Lib.ListToString(subst.GetSubst(), ", ", ""), + ) }), ) err, merged := Core.MergeSubstAndForm(subst, args.st.GetAppliedSubst()) @@ -194,18 +198,18 @@ func (ds *destructiveSearch) passSubstToParent(args wcdArgs, proofChildren [][]P return err } - cleaned := Core.RemoveElementWithoutMM(merged.GetSubst().Copy(), args.st.GetMM()) + cleaned := Core.RemoveElementWithoutMM(merged.GetSubst(), args.st.GetMM()) substAndFormCleaned := Core.MakeSubstAndForm(cleaned, subst.GetForm()) // If the cleaned subst is empty, we don't need to do anything. // Otherwise, we have to check if the cleaned substitution is already in the resulting substs list // and, if applicable, add the formula to the list of substituted formulas. // It is useful for the nondestructive mode, to store with which formula the contradiction has been found. - if !cleaned.IsEmpty() { + if !cleaned.Empty() { // Check if the new substitution is already in the list, merge formulas added := false - for i := 0; !added && i < len(resultingSubsts); i++ { - if resultingSubstsAndForms[i].GetSubst().Equals(cleaned) { + for i := 0; !added && i < resultingSubsts.Len(); i++ { + if Lib.ListEquals(resultingSubstsAndForms[i].GetSubst(), cleaned) { added = true resultingSubstsAndForms[i] = resultingSubstsAndForms[i].AddFormulas(subst.GetForm()) } @@ -213,7 +217,7 @@ func (ds *destructiveSearch) passSubstToParent(args wcdArgs, proofChildren [][]P if !added { resultingSubstsAndForms = append(resultingSubstsAndForms, substAndFormCleaned.Copy()) - resultingSubsts = append(resultingSubsts, substAndFormCleaned.GetSubst()) + resultingSubsts.Append(substAndFormCleaned.GetSubst()) } newMetas = Glob.UnionIntList(newMetas, retrieveMetaFromSubst(cleaned)) @@ -278,7 +282,9 @@ func (ds *destructiveSearch) manageOpenedChild(args wcdArgs) { // If the completeness mode is active, then we need to deal with forbidden substitutions. if Glob.GetCompleteness() { - args.st.SetForbiddenSubsts(Unif.AddSubstToSubstitutionsList(args.st.GetForbiddenSubsts(), args.currentSubst.GetSubst())) + forbidden := args.st.GetForbiddenSubsts() + forbidden.Add(Lib.ListEquals[Unif.MixedSubstitution], args.currentSubst.GetSubst()) + args.st.SetForbiddenSubsts(forbidden) } if args.st.GetBTOnFormulas() && len(args.formsBT) > 0 { diff --git a/src/Search/children.go b/src/Search/children.go index 4e94c0b7..c83a2846 100644 --- a/src/Search/children.go +++ b/src/Search/children.go @@ -63,7 +63,7 @@ type Result struct { closed, need_answer bool subst_for_children Core.SubstAndForm subst_list_for_father []Core.SubstAndForm - forbidden []Unif.Substitutions + forbidden Lib.List[Lib.List[Unif.MixedSubstitution]] proof []ProofStruct node_id int original_node_id int @@ -85,8 +85,8 @@ func (r Result) getSubstForChildren() Core.SubstAndForm { func (r Result) getSubstListForFather() []Core.SubstAndForm { return Core.CopySubstAndFormList(r.subst_list_for_father) } -func (r Result) getForbiddenSubsts() []Unif.Substitutions { - return Unif.CopySubstList(r.forbidden) +func (r Result) getForbiddenSubsts() Lib.List[Lib.List[Unif.MixedSubstitution]] { + return r.forbidden.Copy(Lib.ListCpy[Unif.MixedSubstitution]) } func (r Result) getProof() []ProofStruct { return CopyProofStructList(r.proof) @@ -164,12 +164,19 @@ func sendSubToChildren(children []Communication, s Core.SubstAndForm) { debug( Lib.MkLazy(func() string { return fmt.Sprintf("children : %v/%v", i+1, len(children)) }), ) - v.result <- Result{Glob.GetGID(), true, true, s.Copy(), []Core.SubstAndForm{}, Unif.MakeEmptySubstitutionList(), nil, -1, -1, Core.MakeUnifier()} + v.result <- Result{ + Glob.GetGID(), + true, + true, + s.Copy(), + []Core.SubstAndForm{}, + Lib.NewList[Lib.List[Unif.MixedSubstitution]](), + nil, -1, -1, Core.MakeUnifier()} } } /* Send a substitution to a list of child */ -func sendForbiddenToChildren(children []Communication, s []Unif.Substitutions) { +func sendForbiddenToChildren(children []Communication, s Lib.List[Lib.List[Unif.MixedSubstitution]]) { debug( Lib.MkLazy(func() string { return fmt.Sprintf("Send forbidden to children : %v", len(children)) }), ) @@ -187,8 +194,8 @@ func (ds *destructiveSearch) sendSubToFather(c Communication, closed, need_answe debug( Lib.MkLazy(func() string { return fmt.Sprintf( - "Send subst to father : %v, closed : %v, need answer : %v", - Unif.SubstListToString(Core.GetSubstListFromSubstAndFormList(subst_for_father)), + "Send subst to father : %s, closed : %v, need answer : %v", + Unif.SubstsToString(Core.GetSubstListFromSubstAndFormList(subst_for_father)), closed, need_answer) }), ) @@ -219,7 +226,14 @@ func (ds *destructiveSearch) sendSubToFather(c Communication, closed, need_answe ) select { - case c.result <- Result{Glob.GetGID(), closed, need_answer, Core.MakeEmptySubstAndForm(), Core.CopySubstAndFormList(subst_for_father), Unif.MakeEmptySubstitutionList(), st.GetProof(), node_id, original_node_id, st.GetGlobUnifier()}: + case c.result <- Result{ + Glob.GetGID(), + closed, + need_answer, + Core.MakeEmptySubstAndForm(), + Core.CopySubstAndFormList(subst_for_father), + Lib.NewList[Lib.List[Unif.MixedSubstitution]](), + st.GetProof(), node_id, original_node_id, st.GetGlobUnifier()}: if need_answer { ds.waitFather(father_id, st, c, Core.FusionSubstAndFormListWithoutDouble(subst_for_father, given_substs), node_id, original_node_id, []int{}, meta_to_reintroduce) } else { diff --git a/src/Search/destructive.go b/src/Search/destructive.go index d9867946..963711aa 100644 --- a/src/Search/destructive.go +++ b/src/Search/destructive.go @@ -62,7 +62,7 @@ type BasicSearchAlgorithm interface { ProofSearch(uint64, State, Communication, Core.SubstAndForm, int, int, []int, bool) DoEndManageBeta(uint64, State, Communication, []Communication, int, int, []int, []int) manageRewriteRules(uint64, State, Communication, Core.FormAndTermsList, int, int, []int) - ManageClosureRule(uint64, *State, Communication, []Unif.Substitutions, Core.FormAndTerms, int, int) (bool, []Core.SubstAndForm) + ManageClosureRule(uint64, *State, Communication, Lib.List[Lib.List[Unif.MixedSubstitution]], Core.FormAndTerms, int, int) (bool, []Core.SubstAndForm) manageResult(c Communication) (Core.Unifier, []ProofStruct, bool) } @@ -142,7 +142,7 @@ func (ds *destructiveSearch) doOneStep(limit int, formula AST.Form) (bool, int) PrintSearchResult(result) } - if unif := unifier.GetUnifier(); !unif.IsEmpty() { + if unif := unifier.GetUnifier(); !unif.Empty() { finalProof = ApplySubstitutionOnProofList(unif, finalProof) } uninstanciatedMeta := RetrieveUninstantiatedMetaFromProof(finalProof) @@ -176,9 +176,9 @@ func (ds *destructiveSearch) chooseSubstitutionDestructive(subst_list []Core.Sub i := 0 saved_i := 0 - // Choix de la subst - celle qui ne contient pas de MM, ou la première + // Choose either a subst that does not contain any meta from the parents, or a random one for i < len(subst_list)-1 && !found { - if !Core.ContainsMetaMother((subst_list)[i].GetSubst(), mm) { + if !Core.ContainsMetaMother(subst_list[i].GetSubst(), mm) { subst_found = subst_list[i] saved_i = i found = true @@ -193,7 +193,7 @@ func (ds *destructiveSearch) chooseSubstitutionDestructive(subst_list []Core.Sub subst_found = subst_found.Copy() } - // Maj subst_list avec les subst restantes pour le BT + // Remember the substs for backtracking if len(subst_list) > 1 { subst_list[saved_i] = subst_list[len(subst_list)-1] subst_list = subst_list[:len(subst_list)-1] @@ -214,7 +214,15 @@ func (ds *destructiveSearch) searchContradictionAfterApplySusbt(father_id uint64 ) // Check if exists a contradiction after applying the substitution if res, subst := ApplyClosureRules(f.GetForm(), &st); res { - ds.ManageClosureRule(father_id, &st, cha, Unif.CopySubstList(subst), f.Copy(), node_id, original_node_id) + ds.ManageClosureRule( + father_id, + &st, + cha, + subst.Copy(Lib.ListCpy[Unif.MixedSubstitution]), + f.Copy(), + node_id, + original_node_id, + ) return true } } @@ -233,7 +241,12 @@ func (ds *destructiveSearch) searchContradiction(atomic AST.Form, father_id uint fAt := Core.MakeFormAndTerm(atomic, Lib.MkList[AST.Term](0)) if clos_res { - ds.ManageClosureRule(father_id, &st, cha, Unif.CopySubstList(subst), fAt, node_id, original_node_id) + ds.ManageClosureRule( + father_id, + &st, + cha, + subst.Copy(Lib.ListCpy[Unif.MixedSubstitution]), + fAt, node_id, original_node_id) return true } return false @@ -299,7 +312,8 @@ func (ds *destructiveSearch) ProofSearch(father_id uint64, st State, cha Communi Lib.MkLazy(func() string { return fmt.Sprintf( "Current substitutions list: %v", - Unif.SubstListToString(Core.GetSubstListFromSubstAndFormList(st.GetSubstsFound()))) + Unif.SubstsToString(Core.GetSubstListFromSubstAndFormList(st.GetSubstsFound())), + ) }), ) } @@ -313,7 +327,12 @@ func (ds *destructiveSearch) ProofSearch(father_id uint64, st State, cha Communi for _, f := range st.GetLF() { if Core.ShowKindOfRule(f.GetForm()) == Core.Atomic { if searchObviousClosureRule(f.GetForm()) { - ds.ManageClosureRule(father_id, &st, cha, []Unif.Substitutions{}, f, node_id, original_node_id) + ds.ManageClosureRule( + father_id, + &st, + cha, + Lib.NewList[Lib.List[Unif.MixedSubstitution]](), + f, node_id, original_node_id) return } step_atomics = append(step_atomics, f) @@ -427,7 +446,8 @@ func (ds *destructiveSearch) waitChildren(args wcdArgs) { Lib.MkLazy(func() string { return fmt.Sprintf( "Current substs : %v", - args.currentSubst.GetSubst().ToString()) + Lib.ListToString(args.currentSubst.GetSubst(), ", ", "[]"), + ) }), ) status, substs, proofs, unifiers := ds.selectChildren(args.c, &args.children, args.currentSubst, args.childOrdering) @@ -502,12 +522,12 @@ func (ds *destructiveSearch) waitFather(father_id uint64, st State, c Communicat ) // Check if the subst was already seen, returns eventually the subst with new formula(s) - if Unif.ContainsSubst(Core.GetSubstListFromSubstAndFormList(given_substs), answer_father.subst_for_children.GetSubst()) { + if Core.GetSubstListFromSubstAndFormList(given_substs).Contains(answer_father.subst_for_children.GetSubst(), Lib.ListEquals[Unif.MixedSubstitution]) { debug( Lib.MkLazy(func() string { return "This substitution was sent by this child" }), ) for _, subst_sent := range given_substs { - if subst_sent.GetSubst().Equals(answer_father.subst_for_children.GetSubst()) { + if Lib.ListEquals(subst_sent.GetSubst(), answer_father.subst_for_children.GetSubst()) { subst = answer_father.getSubstForChildren().AddFormulas(subst_sent.GetForm()) } } @@ -530,21 +550,23 @@ func (ds *destructiveSearch) waitFather(father_id uint64, st State, c Communicat x1 := x.MakeDataStruct(x2, false) st.SetTreeNeg(x1) - // Maj forbidden - if len(answer_father.forbidden) > 0 { + // Update forbidden + if answer_father.forbidden.Len() > 0 { debug( Lib.MkLazy(func() string { return fmt.Sprintf( - "Forbidden received : %v", - Unif.SubstListToString(answer_father.getForbiddenSubsts())) + "Forbidden received : %s", + Unif.SubstsToString(answer_father.getForbiddenSubsts()), + ) }), ) st.SetForbiddenSubsts(answer_father.getForbiddenSubsts()) debug( Lib.MkLazy(func() string { return fmt.Sprintf( - "New forbidden fo this state : %v", - Unif.SubstListToString(st.GetForbiddenSubsts())) + "New forbidden for this state: %s", + Unif.SubstsToString(st.GetForbiddenSubsts()), + ) }), ) } else { @@ -598,13 +620,14 @@ func (ds *destructiveSearch) waitFather(father_id uint64, st State, c Communicat debug( Lib.MkLazy(func() string { return fmt.Sprintf( - "Apply substitution on myself and wait : %v", - answer_father.getSubstForChildren().GetSubst().ToString()) + "Apply substitution on myself and wait : %s", + Lib.ListToString(answer_father.getSubstForChildren().GetSubst(), ", ", "[]"), + ) }), ) debug( Lib.MkLazy(func() string { - return fmt.Sprintf("Forbidden : %v", Unif.SubstListToString(st_copy.GetForbiddenSubsts())) + return fmt.Sprintf("Forbidden : %s", Unif.SubstsToString(st_copy.GetForbiddenSubsts())) }), ) go ds.ProofSearch(Glob.GetGID(), st_copy, c2, answer_father.getSubstForChildren(), node_id, original_node_id, new_meta_to_reintroduce, false) @@ -740,7 +763,8 @@ func (ds *destructiveSearch) selectChildren(father Communication, children *[]Co }), ) - if len(res.subst_list_for_father) == 1 && res.subst_list_for_father[0].GetSubst().Equals(current_subst.GetSubst()) { + if len(res.subst_list_for_father) == 1 && + Lib.ListEquals(res.subst_list_for_father[0].GetSubst(), current_subst.GetSubst()) { debug( Lib.MkLazy(func() string { return fmt.Sprintf( @@ -758,12 +782,18 @@ func (ds *destructiveSearch) selectChildren(father Communication, children *[]Co // Check if there is common substitutions for _, current_subst_from_children := range res.subst_list_for_father { for i := range result_subst { - if current_subst_from_children.GetSubst().Equals(result_subst[i].GetSubst()) { + if Lib.ListEquals( + current_subst_from_children.GetSubst(), + result_subst[i].GetSubst(), + ) { debug( Lib.MkLazy(func() string { return fmt.Sprintf( - "Subst in common found : %v !", - current_subst_from_children.GetSubst().ToString()) + "Subst in common found : %s !", + Lib.ListToString( + current_subst_from_children.GetSubst(), + ", ", "[]"), + ) }), ) common_substs = append(common_substs, result_subst[i].AddFormulas(current_subst_from_children.GetForm())) @@ -780,17 +810,20 @@ func (ds *destructiveSearch) selectChildren(father Communication, children *[]Co v.ToString()) }), ) - if !v.GetSubst().Equals(new_current_subst.GetSubst()) { + if !Lib.ListEquals(v.GetSubst(), new_current_subst.GetSubst()) { added := false debug( Lib.MkLazy(func() string { return fmt.Sprintf( - "Result_subst :%v", - Unif.SubstListToString(Core.GetSubstListFromSubstAndFormList(result_subst))) + "Result_subst :%s", + Unif.SubstsToString( + Core.GetSubstListFromSubstAndFormList(result_subst), + ), + ) }), ) for i := range result_subst { - if v.GetSubst().Equals(result_subst[i].GetSubst()) { + if Lib.ListEquals(v.GetSubst(), result_subst[i].GetSubst()) { added = true debug( Lib.MkLazy(func() string { return "Subst already in result_subst" }), @@ -811,9 +844,11 @@ func (ds *destructiveSearch) selectChildren(father Communication, children *[]Co debug( Lib.MkLazy(func() string { return fmt.Sprintf( - "New result susbt : %v", - Unif.SubstListToString( - Core.GetSubstListFromSubstAndFormList(result_subst))) + "New result susbt : %s", + Unif.SubstsToString( + Core.GetSubstListFromSubstAndFormList(result_subst), + ), + ) }), ) } @@ -869,7 +904,7 @@ func (ds *destructiveSearch) selectChildren(father Communication, children *[]Co if !new_current_subst.IsEmpty() { new_result_subst := []Core.SubstAndForm{} for _, s := range result_subst { - if !s.GetSubst().Equals(new_current_subst.GetSubst()) { + if !Lib.ListEquals(s.GetSubst(), new_current_subst.GetSubst()) { err, new_subst := Core.MergeSubstAndForm(s.Copy(), new_current_subst.Copy()) if err != nil { @@ -884,8 +919,9 @@ func (ds *destructiveSearch) selectChildren(father Communication, children *[]Co debug( Lib.MkLazy(func() string { return fmt.Sprintf( - "New subst at the end : %v", - Unif.SubstListToString(Core.GetSubstListFromSubstAndFormList(result_subst))) + "New subst at the end : %s", + Unif.SubstsToString(Core.GetSubstListFromSubstAndFormList(result_subst)), + ) }), ) default: @@ -978,8 +1014,10 @@ func (ds *destructiveSearch) tryRewrite(rewritten []Core.IntSubstAndForm, f Core newRewritten = Core.CopyIntSubstAndFormAndTermsList(newRewritten[1:]) // If we didn't rewrite as itself ? - if !choosenRewritten.GetSaf().GetSubst().Equals(Unif.Failure()) { - // Create a child with the current rewriting rule and make this process to wait for him, with a list of other subst to try + if Unif.UnifSucceeded(choosenRewritten.GetSaf().GetSubst()) { + // Create a child with the current rewriting rule and make this process to wait for him, + // with a list of other subst to try + // all atomics but not the chosen one state.SetLF(append(remainingAtomics.Copy(), choosenRewrittenForm.Copy())) state.SetBTOnFormulas(true) // I need to know that I can bt on form and my child needs to know it to to don't loop @@ -992,7 +1030,7 @@ func (ds *destructiveSearch) tryRewrite(rewritten []Core.IntSubstAndForm, f Core state.SetCurrentProofRuleName("Rewrite") state.SetCurrentProofIdDMT(choosenRewritten.GetId_rewrite()) - if choosenRewritten.GetSaf().GetSubst().IsEmpty() { + if choosenRewritten.GetSaf().GetSubst().Empty() { choosenRewritten = Core.MakeEmptyIntSubstAndFormAndTerms() } @@ -1017,24 +1055,32 @@ func (ds *destructiveSearch) tryRewrite(rewritten []Core.IntSubstAndForm, f Core } } -//ILL TODO Clean the following function and be careful with the Coq output. /** * clos_res and subst are the result of applyClosureRule. * Manage this result, dispatch the subst and recreate data structures. * Return if the branch is closed without variable from its father **/ -func (ds *destructiveSearch) ManageClosureRule(father_id uint64, st *State, c Communication, substs []Unif.Substitutions, f Core.FormAndTerms, node_id int, original_node_id int) (bool, []Core.SubstAndForm) { +func (ds *destructiveSearch) ManageClosureRule( + father_id uint64, + st *State, + c Communication, + substs Lib.List[Lib.List[Unif.MixedSubstitution]], + f Core.FormAndTerms, + node_id int, + original_node_id int, +) (bool, []Core.SubstAndForm) { mm := st.GetMM().Copy() subst := st.GetAppliedSubst().GetSubst() mm = mm.Union(Core.GetMetaFromSubst(subst)) - substs_with_mm, substs_with_mm_uncleared, substs_without_mm := Core.DispatchSubst(Unif.CopySubstList(substs), mm) + substs_with_mm, substs_with_mm_uncleared, substs_without_mm := + Core.DispatchSubst(substs.Copy(Lib.ListCpy[Unif.MixedSubstitution]), mm) unifier := st.GetGlobUnifier() appliedSubst := st.GetAppliedSubst().GetSubst() switch { - case len(substs) == 0: + case substs.Empty(): debug( Lib.MkLazy(func() string { return "Branch closed by ¬⊤ or ⊥ or a litteral and its opposite!" }), ) @@ -1061,24 +1107,27 @@ func (ds *destructiveSearch) ManageClosureRule(father_id uint64, st *State, c Co ds.sendSubToFather(c, true, false, Glob.GetGID(), *st, []Core.SubstAndForm{}, node_id, original_node_id, []int{}) } - case len(substs_without_mm) > 0: + case !substs_without_mm.Empty(): debug( Lib.MkLazy(func() string { return fmt.Sprintf( "Contradiction found (without mm) : %v", - Unif.SubstListToString(substs_without_mm)) + Unif.SubstsToString(substs_without_mm)) }), ) - if Glob.GetAssisted() && !substs_without_mm[0].IsEmpty() { + if Glob.GetAssisted() && !substs_without_mm.At(0).Empty() { fmt.Printf("The branch can be closed by using a substitution which has no impact elsewhere!\nApplying it automatically : ") - fmt.Printf("%v !\n", Unif.SubstListToString(substs_without_mm)) + fmt.Printf("%v !\n", Unif.SubstsToString(substs_without_mm)) } st.SetSubstsFound([]Core.SubstAndForm{st.GetAppliedSubst()}) // Proof - st.SetCurrentProofRule(fmt.Sprintf("⊙ / %v", substs_without_mm[0].ToString())) + st.SetCurrentProofRule(fmt.Sprintf( + "⊙ / %s", + Lib.ListToString(substs_without_mm.At(0), ", ", "(empty subst)"), + )) st.SetCurrentProofRuleName("CLOSURE") st.SetCurrentProofFormula(f.Copy()) st.SetCurrentProofNodeId(node_id) @@ -1086,8 +1135,8 @@ func (ds *destructiveSearch) ManageClosureRule(father_id uint64, st *State, c Co st.SetProof(append(st.GetProof(), st.GetCurrentProof())) // As no MM is involved, these substitutions can be unified with all the others having an empty subst. - for _, subst := range substs_without_mm { - merge, _ := Unif.MergeSubstitutions(appliedSubst, subst) + for _, subst := range substs_without_mm.GetSlice() { + merge, _ := Unif.MergeMixedSubstitutions(appliedSubst, subst) unifier.AddSubstitutions(appliedSubst, merge) } st.SetGlobUnifier(unifier) @@ -1095,12 +1144,12 @@ func (ds *destructiveSearch) ManageClosureRule(father_id uint64, st *State, c Co ds.sendSubToFather(c, true, false, Glob.GetGID(), *st, []Core.SubstAndForm{}, node_id, original_node_id, []int{}) } - case len(substs_with_mm) > 0: + case !substs_with_mm.Empty(): debug( Lib.MkLazy(func() string { return "Contradiction found (with mm) !" }), ) - // TODO : REMOVE vu qu fait dans wait father ? + // FIXME: should this be removed as it's done in WaitForFather? st.SetCurrentProofRule("⊙") st.SetCurrentProofRuleName("CLOSURE") st.SetCurrentProofFormula(f.Copy()) @@ -1109,10 +1158,13 @@ func (ds *destructiveSearch) ManageClosureRule(father_id uint64, st *State, c Co st.SetProof(append(st.GetProof(), st.GetCurrentProof())) meta_to_reintroduce := []int{} - for _, subst_for_father := range substs_with_mm { - // Check if subst_for_father is failure - if subst_for_father.Equals(Unif.Failure()) { - Glob.PrintError("MCR", fmt.Sprintf("Error : SubstForFather is failure between : %v and %v \n", subst_for_father.ToString(), st.GetAppliedSubst().ToString())) + for _, subst_for_father := range substs_with_mm.GetSlice() { + if !Unif.UnifSucceeded(subst_for_father) { + Glob.PrintError("MCR", fmt.Sprintf( + "Error : SubstForFather is failure between : %s and %s \n", + Lib.ListToString(subst_for_father, ", ", "(empty substs)"), + st.GetAppliedSubst().ToString()), + ) } debug( Lib.MkLazy(func() string { return fmt.Sprintf("Formula = : %v", f.ToString()) }), @@ -1155,17 +1207,19 @@ func (ds *destructiveSearch) ManageClosureRule(father_id uint64, st *State, c Co debug( Lib.MkLazy(func() string { return fmt.Sprintf( - "Send subst(s) with mm to father : %v", - Unif.SubstListToString( - Core.GetSubstListFromSubstAndFormList(st.GetSubstsFound()))) + "Send subst(s) with mm to father : %s", + Unif.SubstsToString( + Core.GetSubstListFromSubstAndFormList(st.GetSubstsFound()), + ), + ) }), ) sort.Ints(meta_to_reintroduce) // Add substs_with_mm found with the corresponding subst - for i, subst := range substs_with_mm { - mergeUncleared, _ := Unif.MergeSubstitutions(appliedSubst, substs_with_mm_uncleared[i]) - mergeCleared, _ := Unif.MergeSubstitutions(appliedSubst, subst) + for i, subst := range substs_with_mm.GetSlice() { + mergeUncleared, _ := Unif.MergeMixedSubstitutions(appliedSubst, substs_with_mm_uncleared.At(i)) + mergeCleared, _ := Unif.MergeMixedSubstitutions(appliedSubst, subst) unifier.AddSubstitutions(mergeCleared, mergeUncleared) } st.SetGlobUnifier(unifier) diff --git a/src/Search/exchanges.go b/src/Search/exchanges.go index 4e680f17..84663d2d 100644 --- a/src/Search/exchanges.go +++ b/src/Search/exchanges.go @@ -83,7 +83,13 @@ func ResetExchangesFile() { } } -func makeJsonExchanges(father_uint uint64, st State, ss_subst []Unif.Substitutions, subst_received Unif.Substitutions, calling_function string) exchanges_struct { +func makeJsonExchanges( + father_uint uint64, + st State, + ss_subst Lib.List[Lib.List[Unif.MixedSubstitution]], + subst_received Lib.List[Unif.MixedSubstitution], + calling_function string, +) exchanges_struct { // ID id_process := Glob.GetGID() id := int(id_process) @@ -109,16 +115,16 @@ func makeJsonExchanges(father_uint uint64, st State, ss_subst []Unif.Substitutio // Subt sr := "" - if len(st.GetAppliedSubst().GetSubst()) > 0 { - sr += st.GetAppliedSubst().GetSubst().ToString() + if !st.GetAppliedSubst().GetSubst().Empty() { + sr += Lib.ListToString(st.GetAppliedSubst().GetSubst(), ", ", "(empty subst)") } - if len(subst_received) > 0 { - sr += subst_received.ToString() + if !subst_received.Empty() { + sr += Lib.ListToString(subst_received, ", ", "(empty subst)") } ss := "" - if len(ss_subst) > 0 { - ss += Unif.SubstListToString(ss_subst) + if !ss_subst.Empty() { + ss += Unif.SubstsToString(ss_subst) } // fmt.Printf("Id = %v, version = %v, father = %v, forms = %v, mm = %v, mc = %v, ss = %v, sr = %v\n", id, version, father, forms, mm, mc, ss, sr) @@ -135,7 +141,9 @@ func WriteExchanges(father uint64, st State, sub_sent []Core.SubstAndForm, subst } else { file_exchanges.WriteString("[\n") } - json_content := makeJsonExchanges(father, st, Core.RemoveEmptySubstFromSubstList(Core.GetSubstListFromSubstAndFormList(sub_sent)), subst_received.GetSubst(), calling_function) + json_content := makeJsonExchanges(father, st, + Core.RemoveEmptySubstFromSubstList(Core.GetSubstListFromSubstAndFormList(sub_sent)), + subst_received.GetSubst(), calling_function) json_string, _ := json.MarshalIndent(json_content, "", " ") file_exchanges.Write(json_string) mutex_file_exchanges.Unlock() diff --git a/src/Search/incremental/rulesManager.go b/src/Search/incremental/rulesManager.go index 1a844cec..3daec84f 100644 --- a/src/Search/incremental/rulesManager.go +++ b/src/Search/incremental/rulesManager.go @@ -189,7 +189,7 @@ func (rm *RulesManager) trySubstitutionClosureRules() (applied Rule, subs SubLis negTree := new(Unif.Node).MakeDataStruct(negativeRules.GetFormList(), false) - substitutions := []Unif.MatchingSubstitutions{} + substitutions := []Unif.MixedSubstitutions{} for _, posRule := range positiveRules { success, currentSubst := negTree.Unify(posRule.GetForm()) @@ -200,7 +200,7 @@ func (rm *RulesManager) trySubstitutionClosureRules() (applied Rule, subs SubLis } for _, substitution := range substitutions { - subs = append(subs, NewFromOldSub(substitution)) + subs = append(subs, NewFromOldSub(substitution.MatchingSubstitutions())) } return applied, subs diff --git a/src/Search/incremental/search.go b/src/Search/incremental/search.go index a052eec6..defc4795 100644 --- a/src/Search/incremental/search.go +++ b/src/Search/incremental/search.go @@ -42,7 +42,7 @@ func (is *incrementalSearch) SetApplyRules(func(uint64, Search.State, Search.Com } // ManageClosureRule implements Search.SearchAlgorithm. -func (is *incrementalSearch) ManageClosureRule(uint64, *Search.State, Search.Communication, []Unif.Substitutions, Core.FormAndTerms, int, int) (bool, []Core.SubstAndForm) { +func (is *incrementalSearch) ManageClosureRule(uint64, *Search.State, Search.Communication, Lib.List[Lib.List[Unif.MixedSubstitution]], Core.FormAndTerms, int, int) (bool, []Core.SubstAndForm) { Glob.PrintError("NDS", "Incremental search not compatible with the equality plugin for now.") return false, []Core.SubstAndForm{} } diff --git a/src/Search/nonDestructiveSearch.go b/src/Search/nonDestructiveSearch.go index 9e1fb9a5..55c0b275 100644 --- a/src/Search/nonDestructiveSearch.go +++ b/src/Search/nonDestructiveSearch.go @@ -54,6 +54,17 @@ func NewNonDestructiveSearch() BasicSearchAlgorithm { return nil } +func getMetas(substs Lib.List[Unif.MixedSubstitution]) Lib.List[AST.Meta] { + metas := Lib.NewList[AST.Meta]() + for _, subst := range substs.GetSlice() { + switch s := subst.Substitution().(type) { + case Lib.Some[Unif.Substitution]: + metas.Append(s.Val.Key()) + } + } + return metas +} + func (nds *nonDestructiveSearch) setApplyRules(function func(uint64, State, Communication, Core.FormAndTermsList, int, int, []int)) { Glob.PrintError("NDS", "Non-destructive search not compatible with the assisted plugin for now.") } @@ -69,7 +80,7 @@ func (nds *nonDestructiveSearch) manageRewriteRules(fatherId uint64, state State /* Choose substitution - whitout meta in lastAppliedSubst */ func (nds *nonDestructiveSearch) chooseSubstitutionWithoutMetaLastApplyNonDestructive(sl []Core.SubstAndForm, ml Lib.List[AST.Meta]) (Core.SubstAndForm, []Core.SubstAndForm) { for i, v := range sl { - if !AST.IsIncludeInsideOF(v.GetSubst().GetMeta(), ml) { + if !AST.IsIncludeInsideOF(getMetas(v.GetSubst()), ml) { return v, Core.RemoveSubstFromSubstAndFormList(i, sl) } } @@ -79,7 +90,7 @@ func (nds *nonDestructiveSearch) chooseSubstitutionWithoutMetaLastApplyNonDestru /* Choose substitution - whith meta in lastAppliedSubst */ func (nds *nonDestructiveSearch) chooseSubstitutionWithtMetaLastApplyNonDestructive(sl []Core.SubstAndForm, last_applied_subst Core.SubstAndForm) (Core.SubstAndForm, []Core.SubstAndForm) { for i, v := range sl { - if !v.GetSubst().Equals(last_applied_subst.GetSubst()) { + if !Lib.ListEquals(v.GetSubst(), last_applied_subst.GetSubst()) { return v, Core.RemoveSubstFromSubstAndFormList(i, sl) } } @@ -88,12 +99,12 @@ func (nds *nonDestructiveSearch) chooseSubstitutionWithtMetaLastApplyNonDestruct /* Choose the best substitution among subst_found_at_this_step and subst_found */ func (nds *nonDestructiveSearch) chooseSubstitutionNonDestructive(substs_found_this_step []Core.SubstAndForm, st *State) Core.SubstAndForm { - res, sl := nds.chooseSubstitutionWithoutMetaLastApplyNonDestructive(substs_found_this_step, st.GetLastAppliedSubst().GetSubst().GetMeta()) + res, sl := nds.chooseSubstitutionWithoutMetaLastApplyNonDestructive(substs_found_this_step, getMetas(st.GetLastAppliedSubst().GetSubst())) if !res.IsEmpty() { // subst without meta in last applied meta found in substs_found_at_this_step st.SetSubstsFound(append(sl, st.GetSubstsFound()...)) return res } else { - res, sl = nds.chooseSubstitutionWithoutMetaLastApplyNonDestructive(st.GetSubstsFound(), st.GetLastAppliedSubst().GetSubst().GetMeta()) + res, sl = nds.chooseSubstitutionWithoutMetaLastApplyNonDestructive(st.GetSubstsFound(), getMetas(st.GetLastAppliedSubst().GetSubst())) if !res.IsEmpty() { // subst without meta in last applied meta found in substs_found st.SetSubstsFound(append(sl, substs_found_this_step...)) return res @@ -121,16 +132,19 @@ func (nds *nonDestructiveSearch) chooseSubstitutionNonDestructive(substs_found_t } /* Take a substitution, returns the id of the formula which introduce the metavariable */ -func (nds *nonDestructiveSearch) catchFormulaToInstantiate(subst_found Unif.Substitutions) int { +func (nds *nonDestructiveSearch) catchFormulaToInstantiate(subst_found Lib.List[Unif.MixedSubstitution]) int { meta_to_reintroduce := -1 - for _, subst := range subst_found { - meta, term := subst.Get() - if meta.GetFormula() < meta_to_reintroduce || meta_to_reintroduce == -1 { - meta_to_reintroduce = meta.GetFormula() - } - if term.IsMeta() { - if term.ToMeta().GetFormula() < meta_to_reintroduce || meta_to_reintroduce == -1 { - meta_to_reintroduce = term.ToMeta().GetFormula() + for _, subst := range subst_found.GetSlice() { + switch s := subst.Substitution().(type) { + case Lib.Some[Unif.Substitution]: + meta, term := s.Val.Get() + if meta.GetFormula() < meta_to_reintroduce || meta_to_reintroduce == -1 { + meta_to_reintroduce = meta.GetFormula() + } + if term.IsMeta() { + if term.ToMeta().GetFormula() < meta_to_reintroduce || meta_to_reintroduce == -1 { + meta_to_reintroduce = term.ToMeta().GetFormula() + } } } } @@ -142,7 +156,12 @@ func (nds *nonDestructiveSearch) catchFormulaToInstantiate(subst_found Unif.Subs **/ func (nds *nonDestructiveSearch) instantiate(fatherId uint64, state *State, c Communication, index int, s Core.SubstAndForm) { debug( - Lib.MkLazy(func() string { return fmt.Sprintf("Instantiate with subst : %v ", s.GetSubst().ToString()) }), + Lib.MkLazy(func() string { + return fmt.Sprintf( + "Instantiate with subst : %s", + Lib.ListToString(s.GetSubst(), ", ", "(empty subst)"), + ) + }), ) newMetaGenerator := state.GetMetaGen() reslf := Core.ReintroduceMeta(&newMetaGenerator, index, state.GetN()) @@ -190,12 +209,15 @@ func (nds *nonDestructiveSearch) instantiate(fatherId uint64, state *State, c Co } } - if !found { // Vérifier dans substapplied - for _, subst := range state.GetAppliedSubst().GetSubst() { - original_meta, original_term := subst.Get() - if !found && original_meta.GetName() == new_meta.GetName() && !found { - association_subst.Set(new_meta, original_term) - found = true + if !found { + for _, subst := range state.GetAppliedSubst().GetSubst().GetSlice() { + switch s := subst.Substitution().(type) { + case Lib.Some[Unif.Substitution]: + original_meta, original_term := s.Val.Get() + if !found && original_meta.GetName() == new_meta.GetName() && !found { + association_subst.Set(new_meta, original_term) + found = true + } } } } @@ -211,58 +233,50 @@ func (nds *nonDestructiveSearch) instantiate(fatherId uint64, state *State, c Co } } - new_subst, same_key := Unif.MergeSubstitutions(association_subst, state.GetAppliedSubst().GetSubst()) + mixed_assoc_subst := Lib.NewList[Unif.MixedSubstitution]() + for _, subst := range association_subst { + mixed_assoc_subst.Append(Unif.MkMixedFromSubst(subst)) + } + new_subst, same_key := Unif.MergeMixedSubstitutions(mixed_assoc_subst, state.GetAppliedSubst().GetSubst()) if same_key { Glob.PrintInfo("PS", "Same key in S2 and S1") } - if new_subst.Equals(Unif.Failure()) { + + if !Unif.UnifSucceeded(new_subst) { Glob.PrintError("PS", "MergeSubstitutions return failure") } - new_subst, same_key = Unif.MergeSubstitutions(new_subst, s.GetSubst()) + new_subst, same_key = Unif.MergeMixedSubstitutions(new_subst, s.GetSubst()) if same_key { Glob.PrintInfo("PS", "Same key in S2 and S1") } - if new_subst.Equals(Unif.Failure()) { + + if !Unif.UnifSucceeded(new_subst) { Glob.PrintError("PS", "MergeSubstitutions return failure") } - // Then associate with the substitution (if possible) - // for _, new_meta := range new_metas { - // found := false - // for original_meta, original_term := range s.GetSubst() { - // if !found && original_meta.GetName() == new_meta.GetName() && !found { - // new_subst[new_meta] = original_term - // found = true - // } else { // Test inverse pour le cas meta/meta - // if !found && original_term.IsMeta() && original_term.GetName() == new_meta.GetName() && !found { - // new_subst[new_meta] = original_term - // found = true - // } - // } - // } - // } - debug( Lib.MkLazy(func() string { return fmt.Sprintf( "Applied subst: %s", - state.GetAppliedSubst().GetSubst().ToString()) + Lib.ListToString(state.GetAppliedSubst().GetSubst(), ", ", "(empty subst)"), + ) }), ) debug( Lib.MkLazy(func() string { return fmt.Sprintf( - "Real substitution applied : %s", new_subst.ToString()) + "Real substitution applied : %s", Lib.ListToString(new_subst, ", ", "(empty subst)")) }), ) state.SetLF(Core.ApplySubstitutionsOnFormAndTermsList(new_subst, state.GetLF())) - ms, same_key := Unif.MergeSubstitutions(state.GetAppliedSubst().GetSubst(), new_subst) + ms, same_key := Unif.MergeMixedSubstitutions(state.GetAppliedSubst().GetSubst(), new_subst) if same_key { Glob.PrintError("PS", "Same key in S2 and S1") } - if ms.Equals(Unif.Failure()) { + + if !Unif.UnifSucceeded(ms) { Glob.PrintError("PS", "MergeSubstitutions return failure") } state.SetAppliedSubst(Core.MakeSubstAndForm(ms, s.GetForm())) @@ -296,14 +310,14 @@ func (nds *nonDestructiveSearch) manageSubstFoundNonDestructive(father_id uint64 st.SetSubstsFound(st.GetSubstsFound()[1:]) } - choosenSubstMetas := new_choosen_subst.GetSubst().GetMeta() + choosenSubstMetas := getMetas(new_choosen_subst.GetSubst()) debug(Lib.MkLazy(func() string { return fmt.Sprintf( "Choosen subst : %v - HasInCommon : %v", - new_choosen_subst.GetSubst().ToString(), + Lib.ListToString(new_choosen_subst.GetSubst(), ", ", "(empty subst)"), AST.HasMetaInCommonWith( choosenSubstMetas, - st.GetLastAppliedSubst().GetSubst().GetMeta(), + getMetas(st.GetLastAppliedSubst().GetSubst()), ), ) })) diff --git a/src/Search/proof.go b/src/Search/proof.go index 1fa3e56f..6d292ee7 100644 --- a/src/Search/proof.go +++ b/src/Search/proof.go @@ -404,7 +404,7 @@ func RetrieveUninstantiatedMetaFromProof(proofStruct []ProofStruct) Lib.Set[AST. } /* Apply subst on a proof tree */ -func ApplySubstitutionOnProofList(s Unif.Substitutions, proof_list []ProofStruct) []ProofStruct { +func ApplySubstitutionOnProofList(s Lib.List[Unif.MixedSubstitution], proof_list []ProofStruct) []ProofStruct { new_proof_list := []ProofStruct{} for _, p := range proof_list { @@ -412,7 +412,10 @@ func ApplySubstitutionOnProofList(s Unif.Substitutions, proof_list []ProofStruct new_result_formulas := []IntFormAndTermsList{} for _, f := range p.GetResultFormulas() { - new_result_formulas = append(new_result_formulas, MakeIntFormAndTermsList(f.GetI(), Core.ApplySubstitutionsOnFormAndTermsList(s, f.GetFL()))) + new_result_formulas = append( + new_result_formulas, + MakeIntFormAndTermsList(f.GetI(), Core.ApplySubstitutionsOnFormAndTermsList(s, f.GetFL())), + ) } p.SetResultFormulasProof(new_result_formulas) diff --git a/src/Search/rules.go b/src/Search/rules.go index 855aafcb..b9b490b3 100644 --- a/src/Search/rules.go +++ b/src/Search/rules.go @@ -59,17 +59,9 @@ var strToPrintMap map[string]string = map[string]string{ "EXISTS": "∃", } -/** -* ApplyClosureRules -* Search closure rules (not true or false), and call search conflict if no obvious closure found -* Datas : -* form : the formula for which we are looking for the contradiction -* state : a state, containing all the formula of the current step -* Result : -* a boolean, true if a contradiction was found, false otherwise -* a substitution, the substitution which make the contradiction (possibly empty) -**/ -func ApplyClosureRules(form AST.Form, state *State) (result bool, substitutions []Unif.Substitutions) { +func ApplyClosureRules(form AST.Form, state *State) (bool, Lib.List[Lib.List[Unif.MixedSubstitution]]) { + result := false + substitutions := Lib.NewList[Lib.List[Unif.MixedSubstitution]]() debug(Lib.MkLazy(func() string { return "Start ACR" })) if searchObviousClosureRule(form) { @@ -78,10 +70,14 @@ func ApplyClosureRules(form AST.Form, state *State) (result bool, substitutions f := form.Copy() - substFound, subst := searchInequalities(form) + substFound, substs := searchInequalities(form) if substFound { result = true - substitutions = append(substitutions, subst) + mixed_substs := Lib.NewList[Unif.MixedSubstitution]() + for _, subst := range substs { + mixed_substs.Append(Unif.MkMixedFromSubst(subst)) + } + substitutions.Append(mixed_substs) } substFound, matchSubsts := searchClosureRule(f, *state) @@ -92,10 +88,10 @@ func ApplyClosureRules(form AST.Form, state *State) (result bool, substitutions for _, subst := range matchSubsts { debug(Lib.MkLazy(func() string { return fmt.Sprintf("MSL : %v", subst.ToString()) })) - if subst.GetSubst().Equals(Unif.MakeEmptySubstitution()) { + if subst.IsSubstsEmpty() { result = true } else { - if !searchForbidden(state, subst) { + if !searchForbidden(state, subst.MatchingSubstitutions()) { result = true } } @@ -104,13 +100,13 @@ func ApplyClosureRules(form AST.Form, state *State) (result bool, substitutions debug( Lib.MkLazy(func() string { return fmt.Sprintf( - "Subst found between : %v and %v : %v", + "Subst found between : %s and %s : %s", form.ToString(), subst.GetForm().ToString(), - subst.GetSubst().ToString()) + subst.ToString()) }), ) - substitutions = Unif.AppendIfNotContainsSubst(substitutions, subst.GetSubst()) + substitutions.Add(Lib.ListEquals[Unif.MixedSubstitution], subst.GetSubsts()) } } } @@ -121,8 +117,15 @@ func ApplyClosureRules(form AST.Form, state *State) (result bool, substitutions func searchForbidden(state *State, s Unif.MatchingSubstitutions) bool { foundForbidden := false - for _, substForbidden := range state.GetForbiddenSubsts() { - forbiddenShared := Core.AreEqualsModuloaLaphaConversion(s.GetSubst(), substForbidden) + for _, substForbidden := range state.GetForbiddenSubsts().GetSlice() { + substs := Unif.Substitutions{} + for _, subst := range substForbidden.GetSlice() { + switch s := subst.Substitution().(type) { + case Lib.Some[Unif.Substitution]: + substs = append(substs, s.Val) + } + } + forbiddenShared := Core.AreEqualsModuloaLaphaConversion(s.GetSubst(), substs) if forbiddenShared { foundForbidden = true @@ -194,7 +197,7 @@ func searchInequalities(form AST.Form) (bool, Unif.Substitutions) { } /* Search a contradiction between a formula and another in the datastructure */ -func searchClosureRule(f AST.Form, st State) (bool, []Unif.MatchingSubstitutions) { +func searchClosureRule(f AST.Form, st State) (bool, []Unif.MixedSubstitutions) { switch nf := f.(type) { case AST.Pred: return st.GetTreeNeg().Unify(f) diff --git a/src/Search/search.go b/src/Search/search.go index cb5e019b..c55ab779 100644 --- a/src/Search/search.go +++ b/src/Search/search.go @@ -49,7 +49,7 @@ import ( type SearchAlgorithm interface { Search(AST.Form, int) bool SetApplyRules(func(uint64, State, Communication, Core.FormAndTermsList, int, int, []int)) - ManageClosureRule(uint64, *State, Communication, []Unif.Substitutions, Core.FormAndTerms, int, int) (bool, []Core.SubstAndForm) + ManageClosureRule(uint64, *State, Communication, Lib.List[Lib.List[Unif.MixedSubstitution]], Core.FormAndTerms, int, int) (bool, []Core.SubstAndForm) } var UsedSearch SearchAlgorithm @@ -118,10 +118,13 @@ func printStandardSolution(status string) { fmt.Printf("%s SZS status %v for %v\n", "%", status, Glob.GetProblemName()) } -func retrieveMetaFromSubst(s Unif.Substitutions) []int { +func retrieveMetaFromSubst(substs Lib.List[Unif.MixedSubstitution]) []int { res := []int{} - for _, s_element := range s { - res = Glob.AppendIfNotContainsInt(res, s_element.Key().GetFormula()) + for _, subst := range substs.GetSlice() { + switch s := subst.Substitution().(type) { + case Lib.Some[Unif.Substitution]: + res = Glob.AppendIfNotContainsInt(res, s.Val.Key().GetFormula()) + } } return res } diff --git a/src/Search/state.go b/src/Search/state.go index 0b9ee1fd..3a5bd354 100644 --- a/src/Search/state.go +++ b/src/Search/state.go @@ -64,7 +64,7 @@ type State struct { proof []ProofStruct current_proof ProofStruct bt_on_formulas bool - forbidden []Unif.Substitutions + forbidden Lib.List[Lib.List[Unif.MixedSubstitution]] unifier Core.Unifier eqStruct eqStruct.EqualityStruct } @@ -134,7 +134,7 @@ func (s State) GetCurrentProof() ProofStruct { func (s State) GetBTOnFormulas() bool { return s.bt_on_formulas } -func (s State) GetForbiddenSubsts() []Unif.Substitutions { +func (s State) GetForbiddenSubsts() Lib.List[Lib.List[Unif.MixedSubstitution]] { return s.forbidden } func (s State) GetGlobUnifier() Core.Unifier { @@ -245,8 +245,8 @@ func (st *State) SetCurrentProofNodeId(i int) { func (st *State) SetBTOnFormulas(b bool) { st.bt_on_formulas = b } -func (st *State) SetForbiddenSubsts(s []Unif.Substitutions) { - st.forbidden = Unif.CopySubstList(s) +func (st *State) SetForbiddenSubsts(s Lib.List[Lib.List[Unif.MixedSubstitution]]) { + st.forbidden = s.Copy(Lib.ListCpy[Unif.MixedSubstitution]) } func (s *State) SetGlobUnifier(u Core.Unifier) { s.unifier = u.Copy() @@ -285,7 +285,7 @@ func MakeState(limit int, tp, tn Unif.DataStructure, f AST.Form) State { []ProofStruct{}, current_proof, false, - []Unif.Substitutions{}, + Lib.NewList[Lib.List[Unif.MixedSubstitution]](), Core.MakeUnifier(), eqStruct.NewEqStruct()} } @@ -353,7 +353,7 @@ func (st State) Print() { debug(Lib.MkLazy(func() string { return "Subst_found: " })) debug( Lib.MkLazy(func() string { - return Unif.SubstListToString(Core.GetSubstListFromSubstAndFormList(st.GetSubstsFound())) + return Unif.SubstsToString(Core.GetSubstListFromSubstAndFormList(st.GetSubstsFound())) }), ) } @@ -363,9 +363,16 @@ func (st State) Print() { debug(Lib.MkLazy(func() string { return st.GetLastAppliedSubst().ToString() })) } - if len(st.forbidden) > 0 { + if st.forbidden.Len() > 0 { debug(Lib.MkLazy(func() string { return "Forbidden:" })) - debug(Lib.MkLazy(func() string { return Unif.SubstListToString(st.forbidden) })) + debug( + Lib.MkLazy(func() string { + return st.forbidden.ToString( + func(m Lib.List[Unif.MixedSubstitution]) string { + return Lib.ListToString(m, ", ", "[]") + }, " ; ", "[]") + }), + ) } debug( diff --git a/src/Unif/data_structure.go b/src/Unif/data_structure.go index 763ae197..c3d9f2a7 100644 --- a/src/Unif/data_structure.go +++ b/src/Unif/data_structure.go @@ -47,6 +47,6 @@ type DataStructure interface { IsEmpty() bool MakeDataStruct(Lib.List[AST.Form], bool) DataStructure InsertFormulaListToDataStructure(Lib.List[AST.Form]) DataStructure - Unify(AST.Form) (bool, []MatchingSubstitutions) + Unify(AST.Form) (bool, []MixedSubstitutions) Copy() DataStructure } diff --git a/src/Unif/matching.go b/src/Unif/matching.go index 3b7dae18..5989f2ec 100644 --- a/src/Unif/matching.go +++ b/src/Unif/matching.go @@ -54,10 +54,17 @@ func InitDebugger() { /*** Unify ***/ /* Helper function to avoid using MakeMachine() outside of this file. */ -func (n Node) Unify(formula AST.Form) (bool, []MatchingSubstitutions) { +func (n Node) Unify(formula AST.Form) (bool, []MixedSubstitutions) { machine := makeMachine() res := machine.unify(n, formula) - return !reflect.DeepEqual(machine.failure, res), res // return found, res + // As we have transformed type metas to terms, we get everything in a term substitution. + // But externally, we want to have a substitution of both (term) metas to terms and (type) metas to types. + // We use MixedSubstitution to properly manage things internally. + mixed_substs := []MixedSubstitutions{} + for _, subst := range res { + mixed_substs = append(mixed_substs, subst.toMixed()) + } + return !reflect.DeepEqual(machine.failure, res), mixed_substs } /* Tries to find the substitutions needed to unify the formulae with the one described by the sequence of instructions. */ @@ -67,11 +74,10 @@ func (m *Machine) unify(node Node, formula AST.Form) []MatchingSubstitutions { switch formula_type := formula.(type) { case AST.Pred: // Transform the predicate to a function to make the tool work properly - // FIXME: transform type arguments into terms to unify them m.terms = Lib.MkListV[AST.Term](AST.MakerFun( formula_type.GetID(), - formula_type.GetTyArgs(), - formula_type.GetArgs(), + Lib.NewList[AST.Ty](), + getFunctionalArguments(formula_type.GetTyArgs(), formula_type.GetArgs()), )) result = m.unifyAux(node) @@ -254,7 +260,7 @@ func (m *Machine) end(instrTerm AST.Term) Status { func (m *Machine) right() Status { if m.isUnlocked() { m.q += 1 - if m.q > m.terms.Len() { + if m.q >= m.terms.Len() { return Status(ERROR) } m.topLevelCount += 1 diff --git a/src/Unif/matching_substitutions.go b/src/Unif/matching_substitutions.go index 7a727207..b268d21a 100644 --- a/src/Unif/matching_substitutions.go +++ b/src/Unif/matching_substitutions.go @@ -40,9 +40,197 @@ import ( "fmt" "github.com/GoelandProver/Goeland/AST" + "github.com/GoelandProver/Goeland/Glob" "github.com/GoelandProver/Goeland/Lib" + "github.com/GoelandProver/Goeland/Typing" ) +type TySubstitution struct { + k AST.TyMeta + v AST.Ty +} + +func MkTySubstitution(k AST.TyMeta, v AST.Ty) TySubstitution { + return TySubstitution{k, v} +} + +func (s TySubstitution) ToString() string { + return fmt.Sprintf("%s |-> %s", s.k.ToString(), s.v.ToString()) +} + +func (s TySubstitution) Equals(oth any) bool { + if os, ok := oth.(TySubstitution); ok { + return os.k.Equals(s.k) && os.v.Equals(s.v) + } + return false +} + +func (s TySubstitution) Copy() TySubstitution { + return MkTySubstitution(s.k.Copy().(AST.TyMeta), s.v.Copy()) +} + +func (s TySubstitution) Get() (AST.TyMeta, AST.Ty) { + return s.k, s.v +} + +type MixedSubstitution struct { + s Lib.Either[TySubstitution, Substitution] +} + +func translateFromSubst(subst Substitution) MixedSubstitution { + if AST.IsTType(subst.k.GetTy()) { + return MixedSubstitution{Lib.MkLeft[TySubstitution, Substitution]( + MkTySubstitution( + AST.TyMetaFromMeta(subst.k), + AST.TermToTy(subst.v), + ), + )} + } else { + return MixedSubstitution{Lib.MkRight[TySubstitution, Substitution]( + MakeSubstitution( + subst.k, + translateTermRec(subst.v), + ))} + } +} + +func translateTermRec(term AST.Term) AST.Term { + switch trm := term.(type) { + case AST.Fun: + // Already converted: do nothing (either everything is converted or nothing) + if !trm.GetTyArgs().Empty() { + return term + } + + ty_args := Lib.NewList[AST.Ty]() + opt_ty := Typing.QueryGlobalEnv(trm.GetName()) + switch ty := opt_ty.(type) { + case Lib.Some[AST.Ty]: + switch t := ty.Val.(type) { + case AST.TyPi: + for i := 0; i < t.VarsLen(); i++ { + ty_args.Append(AST.TermToTy(trm.GetArgs().At(i))) + } + } + } + args := trm.GetArgs() + args = trm.GetArgs().Slice(ty_args.Len(), trm.GetArgs().Len()) + + return AST.MakerFun( + trm.GetID(), + ty_args, + Lib.ListMap(args, translateTermRec), + ) + } + return term +} + +func MkMixedFromSubst(subst Substitution) MixedSubstitution { + return MixedSubstitution{Lib.MkRight[TySubstitution, Substitution](subst)} +} + +func MkMixedFromTy(subst TySubstitution) MixedSubstitution { + return MixedSubstitution{Lib.MkLeft[TySubstitution, Substitution](subst)} +} + +func FromSubstitutions(substs Substitutions) Lib.List[MixedSubstitution] { + mixed_substs := Lib.MkList[MixedSubstitution](len(substs)) + for i, subst := range substs { + mixed_substs.Upd(i, MixedSubstitution{Lib.MkRight[TySubstitution, Substitution](subst)}) + } + return mixed_substs +} + +func ToSubstitutions(mixed_substs Lib.List[MixedSubstitution]) Substitutions { + substs := Substitutions{} + for _, subst := range mixed_substs.GetSlice() { + switch s := subst.Substitution().(type) { + case Lib.Some[Substitution]: + substs = append(substs, s.Val) + } + } + return substs +} + +func (m MixedSubstitution) ToString() string { + return Lib.EitherToString[TySubstitution, Substitution](m.s, "TySubst", "TrmSubst") +} + +func (m MixedSubstitution) Equals(oth any) bool { + if om, ok := oth.(MixedSubstitution); ok { + return Lib.EitherEquals[TySubstitution, Substitution](m.s, om.s) + } + return false +} + +func (m MixedSubstitution) Copy() MixedSubstitution { + return MixedSubstitution{Lib.EitherCpy[TySubstitution, Substitution](m.s)} +} + +func (m MixedSubstitution) Substitution() Lib.Option[Substitution] { + switch s := m.s.(type) { + case Lib.Right[TySubstitution, Substitution]: + return Lib.MkSome(s.Val) + } + return Lib.MkNone[Substitution]() +} + +func (m MixedSubstitution) TySubstitution() Lib.Option[TySubstitution] { + switch s := m.s.(type) { + case Lib.Left[TySubstitution, Substitution]: + return Lib.MkSome(s.Val) + } + return Lib.MkNone[TySubstitution]() +} + +func (m MixedSubstitution) GetMixed() Lib.Either[TySubstitution, Substitution] { + return m.s +} + +type MixedSubstitutions struct { + form AST.Form + substs []MixedSubstitution +} + +func (m MixedSubstitutions) GetForm() AST.Form { + return m.form.Copy() +} + +func (m MixedSubstitutions) GetSubsts() Lib.List[MixedSubstitution] { + return Lib.MkListV(m.substs...) +} + +func (m MixedSubstitutions) GetTrmSubsts() Substitutions { + out_substs := Substitutions{} + for _, subst := range m.substs { + switch s := subst.s.(type) { + case Lib.Right[TySubstitution, Substitution]: + out_substs = append(out_substs, s.Val) + } + } + return out_substs +} + +func (m MixedSubstitutions) GetTySubsts() Lib.List[TySubstitution] { + out_substs := Lib.NewList[TySubstitution]() + for _, subst := range m.substs { + switch s := subst.s.(type) { + case Lib.Left[TySubstitution, Substitution]: + out_substs.Append(s.Val) + } + } + return out_substs +} + +func (m MixedSubstitutions) ToString() string { + substs_list := Lib.MkListV(m.substs...) + return m.GetForm().ToString() + " {" + Lib.ListToString(substs_list, ", ", "") + "}" +} + +func (m MixedSubstitutions) IsSubstsEmpty() bool { + return len(m.substs) == 0 +} + type MatchingSubstitutions struct { form AST.Form subst Substitutions @@ -64,6 +252,68 @@ func (m MatchingSubstitutions) Print() { m.GetSubst().Print() } +func (m MatchingSubstitutions) toMixed() MixedSubstitutions { + substs := []MixedSubstitution{} + for _, subst := range m.subst { + substs = append(substs, translateFromSubst(subst)) + } + return MixedSubstitutions{m.form, substs} +} + func MakeMatchingSubstitutions(form AST.Form, subst Substitutions) MatchingSubstitutions { return MatchingSubstitutions{form.Copy(), subst.Copy()} } + +func (m MixedSubstitutions) MatchingSubstitutions() MatchingSubstitutions { + return MakeMatchingSubstitutions(m.form, m.GetTrmSubsts()) +} + +func translateToSubst(subst MixedSubstitution) Substitution { + switch s := subst.s.(type) { + case Lib.Left[TySubstitution, Substitution]: + return MakeSubstitution( + s.Val.k.ToTermMeta(), + AST.TyToTerm(s.Val.v), + ) + case Lib.Right[TySubstitution, Substitution]: + return s.Val + } + + Glob.Anomaly("unification internals", "Found neither a type substitution nor a substitution") + return MakeSubstitution(AST.MakeEmptyMeta(), nil) +} + +func MergeMixedSubstitutions(substs1, substs2 Lib.List[MixedSubstitution]) (Lib.List[MixedSubstitution], bool) { + translated_substs1 := Lib.ListMap(substs1, translateToSubst).GetSlice() + translated_substs2 := Lib.ListMap(substs2, translateToSubst).GetSlice() + + merged_tmp, _ := MergeSubstitutions(translated_substs1, translated_substs2) + + success := !merged_tmp.Equals(Failure()) + + merged := Lib.MkList[MixedSubstitution](len(merged_tmp)) + for i, subst := range merged_tmp { + merged.Upd(i, translateFromSubst(subst)) + } + return merged, success +} + +func SubstsToString(substs Lib.List[Lib.List[MixedSubstitution]]) string { + return substs.ToString( + func(m Lib.List[MixedSubstitution]) string { + return Lib.ListToString(m, ", ", "[]") + }, " ; ", "[]") +} + +func UnifSucceeded(unifs Lib.List[MixedSubstitution]) bool { + if unifs.Empty() { + return true + } + + succeeded := true + switch subst := unifs.At(0).Substitution().(type) { + case Lib.Some[Substitution]: + succeeded = !subst.Val.Equals(Failure()[0]) + } + return succeeded +} diff --git a/src/Unif/parsing.go b/src/Unif/parsing.go index 9674909d..69dd16be 100644 --- a/src/Unif/parsing.go +++ b/src/Unif/parsing.go @@ -61,7 +61,7 @@ func (t TermForm) RenameVariables() AST.Form { return t } func (t TermForm) ReplaceTermByTerm(AST.Term, AST.Term) (AST.Form, bool) { return t, false } -func (t TermForm) SubstTy(AST.TyBound, AST.Ty) AST.Form { +func (t TermForm) SubstTy(AST.TyGenVar, AST.Ty) AST.Form { return t } func (t TermForm) GetIndex() int { return t.index } @@ -109,6 +109,11 @@ func (t TermForm) ReplaceMetaByTerm(meta AST.Meta, term AST.Term) AST.Form { } func MakerTermForm(t AST.Term) TermForm { + switch trm := t.(type) { + case AST.Fun: + args := getFunctionalArguments(trm.GetTyArgs(), trm.GetArgs()) + t = AST.MakerFun(trm.GetID(), Lib.NewList[AST.Ty](), args) + } return makeTermForm(AST.MakerIndexFormula(), t.Copy()) } @@ -154,14 +159,39 @@ func ParseFormula(formula AST.Form) Sequence { } /* Parses a predicate to machine instructions */ +func getFunctionalArguments(ty_args Lib.List[AST.Ty], trm_args Lib.List[AST.Term]) Lib.List[AST.Term] { + args := Lib.ListMap(ty_args, AST.TyToTerm) + + for _, arg := range trm_args.GetSlice() { + switch term := arg.(type) { + case AST.Meta: + args.Append(arg) + case AST.Fun: + args.Append(AST.MakerFun( + term.GetID(), + Lib.NewList[AST.Ty](), + getFunctionalArguments(term.GetTyArgs(), term.GetArgs()), + )) + } + } + + return args +} + func parsePred(p AST.Pred, instructions *Sequence) { instructions.add(makeCheck(p.GetID())) - if p.GetArgs().Len() > 0 { + if !p.GetTyArgs().Empty() || !p.GetArgs().Empty() { instructions.add(Begin{}) instructions.add(Down{}) varCount := 0 postCount := 0 - parseTerms(p.GetArgs(), instructions, Lib.NewList[AST.Meta](), &varCount, &postCount) + parseTerms( + getFunctionalArguments(p.GetTyArgs(), p.GetArgs()), + instructions, + Lib.NewList[AST.Meta](), + &varCount, + &postCount, + ) instructions.add(End{}) } } @@ -210,7 +240,8 @@ func parseTerms( *postCount++ } instructions.add(Down{}) - subst = parseTerms(t.GetArgs(), instructions, subst, varCount, postCount) + subTerms := getFunctionalArguments(t.GetTyArgs(), t.GetArgs()) + subst = parseTerms(subTerms, instructions, subst, varCount, postCount) if rightDefined(terms, i) { *postCount-- instructions.add(Pop{*postCount}) diff --git a/src/Unif/substitutions_tree.go b/src/Unif/substitutions_tree.go index ab123186..5a9be9e7 100644 --- a/src/Unif/substitutions_tree.go +++ b/src/Unif/substitutions_tree.go @@ -63,7 +63,10 @@ func computeSubstitutions(subs []SubstPair, metasToSubs Substitutions, form AST. // Retrieve all the meta of from the tree formula switch typedForm := form.(type) { case AST.Pred: - metasFromTreeForm.Append(typedForm.GetMetaList().GetSlice()...) + trms := getFunctionalArguments(typedForm.GetTyArgs(), typedForm.GetArgs()) + for _, trm := range trms.GetSlice() { + metasFromTreeForm.Append(trm.GetMetaList().GetSlice()...) + } case TermForm: metasFromTreeForm.Append(typedForm.GetTerm().GetMetaList().GetSlice()...) default: From b82aee979b72aace1cc0190232001e918990e3b8 Mon Sep 17 00:00:00 2001 From: Johann Rosain Date: Sun, 27 Jul 2025 11:04:30 +0200 Subject: [PATCH 09/30] Fix equality of quantified formulas (forall, exists) --- src/AST/formsDef.go | 10 ++++++++-- src/Lib/int.go | 10 ++++------ src/Mods/gs3/proof.go | 6 ++++++ src/Mods/tptp/proof.go | 12 ++++++++---- src/main.go | 2 ++ 5 files changed, 28 insertions(+), 12 deletions(-) diff --git a/src/AST/formsDef.go b/src/AST/formsDef.go index b1733121..556ffd97 100644 --- a/src/AST/formsDef.go +++ b/src/AST/formsDef.go @@ -100,7 +100,10 @@ func MakerAll(vars Lib.List[TypedVar], forms Form) All { } func (a All) Equals(other any) bool { - return a.quantifier.Equals(other) + if typed, ok := other.(All); ok { + return a.quantifier.Equals(typed.quantifier) + } + return false } func (a All) GetSubFormulasRecur() Lib.List[Form] { @@ -152,7 +155,10 @@ func MakerEx(vars Lib.List[TypedVar], forms Form) Ex { } func (e Ex) Equals(other any) bool { - return e.quantifier.Equals(other) + if typed, ok := other.(Ex); ok { + return e.quantifier.Equals(typed.quantifier) + } + return false } func (e Ex) GetSubFormulasRecur() Lib.List[Form] { diff --git a/src/Lib/int.go b/src/Lib/int.go index 68e24475..a7e4ef5b 100644 --- a/src/Lib/int.go +++ b/src/Lib/int.go @@ -37,24 +37,22 @@ package Lib -type Int struct { - value int -} +type Int int func (s Int) Equals(oth any) bool { if str, ok := oth.(Int); ok { - return s.value == str.value + return s == str } return false } func (s Int) Less(oth any) bool { if str, ok := oth.(Int); ok { - return s.value < str.value + return s < str } return false } func MkInt(s int) Int { - return Int{s} + return Int(s) } diff --git a/src/Mods/gs3/proof.go b/src/Mods/gs3/proof.go index eebe9c80..bf35faa8 100644 --- a/src/Mods/gs3/proof.go +++ b/src/Mods/gs3/proof.go @@ -104,6 +104,12 @@ type GS3Proof struct { deltaHisto []Glob.Pair[AST.Term, Glob.Pair[AST.Form, int]] } +var debug func(Lib.Lazy[string]) + +func InitDebugger() { + debug = Glob.CreateDebugger("GS3") +} + var MakeGS3Proof = func(proof []Search.ProofStruct) *GS3Sequent { gs3Proof := GS3Proof{ rulesApplied: make([]Glob.Pair[Rule, Search.ProofStruct], 0), diff --git a/src/Mods/tptp/proof.go b/src/Mods/tptp/proof.go index f456ffd9..2bd79ca4 100644 --- a/src/Mods/tptp/proof.go +++ b/src/Mods/tptp/proof.go @@ -591,10 +591,14 @@ func performCutAxiomStep(axioms Lib.List[AST.Form], conjecture AST.Form) string /*** Utility Functions ***/ func get(f AST.Form, fl Lib.List[AST.Form]) int { - for i, h := range fl.GetSlice() { - if h.Equals(f) { - return i - } + switch index := Lib.ListIndexOf(f, fl).(type) { + case Lib.Some[int]: + return index.Val + case Lib.None[int]: + Glob.Anomaly( + "TPTP", + fmt.Sprintf("Formula %s not found in context", f.ToString()), + ) } return -1 } diff --git a/src/main.go b/src/main.go index d4042e94..70d2995d 100644 --- a/src/main.go +++ b/src/main.go @@ -55,6 +55,7 @@ import ( "github.com/GoelandProver/Goeland/Mods/assisted" "github.com/GoelandProver/Goeland/Mods/dmt" equality "github.com/GoelandProver/Goeland/Mods/equality/bse" + "github.com/GoelandProver/Goeland/Mods/gs3" "github.com/GoelandProver/Goeland/Parser" "github.com/GoelandProver/Goeland/Search" "github.com/GoelandProver/Goeland/Search/incremental" @@ -207,6 +208,7 @@ func initDebuggers() { // Typing.InitDebugger() Unif.InitDebugger() Engine.InitDebugger() + gs3.InitDebugger() } // FIXME: eventually, we would want to add an "interpretation" layer between elab and internal representation that does this From 205c7feaebd4bcd4f2dd4c58060dc7e74ba0e567 Mon Sep 17 00:00:00 2001 From: Johann Rosain Date: Sun, 27 Jul 2025 11:33:43 +0200 Subject: [PATCH 10/30] Add proper debugging facilities in typing rules --- src/Typing/env-and-context.go | 10 ++++++++++ src/Typing/init.go | 14 +++++++++++++- src/Typing/rules.go | 30 ++++++++++++++++++++++++++++++ src/main.go | 2 +- 4 files changed, 54 insertions(+), 2 deletions(-) diff --git a/src/Typing/env-and-context.go b/src/Typing/env-and-context.go index 2a61b6d6..9b7caa83 100644 --- a/src/Typing/env-and-context.go +++ b/src/Typing/env-and-context.go @@ -106,6 +106,16 @@ type Env struct { mut sync.Mutex } +func (env *Env) toString() string { + env.mut.Lock() + result := "Environment:" + for k, v := range env.con { + result += "\n- " + k + ": " + v.ToString() + } + env.mut.Unlock() + return result + "\n" +} + func safeGlobalOperation[T any](f func() T) T { global_env.mut.Lock() res := f() diff --git a/src/Typing/init.go b/src/Typing/init.go index 6411a329..ccbccbc0 100644 --- a/src/Typing/init.go +++ b/src/Typing/init.go @@ -37,13 +37,17 @@ package Typing import ( + "sync" + "github.com/GoelandProver/Goeland/AST" + "github.com/GoelandProver/Goeland/Glob" "github.com/GoelandProver/Goeland/Lib" - "sync" ) var global_env Env var ari_var string +var debug Glob.Debugger +var debug_low_level Glob.Debugger func Init() { global_env = Env{make(map[string]AST.Ty), sync.Mutex{}} @@ -52,6 +56,11 @@ func Init() { initTPTPNativeTypes() } +func InitDebugger() { + debug = Glob.CreateDebugger("typing") + debug_low_level = Glob.CreateDebugger("typing-low") +} + func initTPTPNativeTypes() { for _, ty := range AST.DefinedTPTPTypes().GetSlice() { AddToGlobalEnv(ty.Symbol(), AST.TType()) @@ -106,6 +115,9 @@ func initTPTPNativeTypes() { recordConversion("$to_int", AST.TInt()) recordConversion("$to_rat", AST.TRat()) recordConversion("$to_real", AST.TReal()) + + debug(Lib.MkLazy(func() string { return "TPTP native loaded in global environment" })) + debug_low_level(Lib.MkLazy(global_env.toString)) } func recordBinaryProp(name string) { diff --git a/src/Typing/rules.go b/src/Typing/rules.go index 098aab67..1b2332ef 100644 --- a/src/Typing/rules.go +++ b/src/Typing/rules.go @@ -47,10 +47,16 @@ import ( var label = "typing" func TypeCheck(form AST.Form) bool { + debug(Lib.MkLazy(func() string { return fmt.Sprintf("Launching type checking on %s", form.ToString()) })) + return typecheckForm(emptyCon(), form) } func typecheckForm(con Con, form AST.Form) bool { + debug(Lib.MkLazy(func() string { + return fmt.Sprintf("Trying to type-check: %s |- %s : o", con.toString(), form.ToString()) + })) + switch f := form.(type) { case AST.Bot, AST.Top: return true @@ -96,6 +102,10 @@ func typecheckForm(con Con, form AST.Form) bool { } func typecheckTerm(con Con, term AST.Term, ty AST.Ty) bool { + debug(Lib.MkLazy(func() string { + return fmt.Sprintf("Trying to type-check: %s |- %s : %s", con.toString(), term.ToString(), ty.ToString()) + })) + switch t := term.(type) { case AST.Var: if !con.contains(t.GetName(), ty) { @@ -135,6 +145,11 @@ func typecheckTerm(con Con, term AST.Term, ty AST.Ty) bool { } func typecheckType(con Con, ty AST.Ty) bool { + debug(Lib.MkLazy(func() string { + return fmt.Sprintf("Trying to type-check: %s |- %s : %s", + con.toString(), ty.ToString(), AST.TType().ToString()) + })) + switch nty := ty.(type) { case AST.TyBound: if !con.contains(nty.GetName(), AST.TType()) { @@ -206,7 +221,16 @@ func checkFunctional( oty := QueryEnvInstance(name, tys) switch ty := oty.(type) { case Lib.Some[AST.Ty]: + debug_low_level(Lib.MkLazy(func() string { + return fmt.Sprintf("%s has a functional scheme instantiated to %s", debug_str.Run(), ty.Val.ToString()) + })) + instantiated_ty := AST.GetArgsTy(ty.Val) + debug_low_level(Lib.MkLazy(func() string { + return fmt.Sprintf("Arguments will be typechecked against: [%s]", + Lib.ListToString(instantiated_ty, ", ", "")) + })) + terms_checker := buildTermCheckList( debug_str, ty.Val, @@ -232,6 +256,12 @@ func typecheckRec( typed_terms Lib.List[Lib.Pair[AST.Term, AST.Ty]], tys Lib.List[AST.Ty], ) bool { + + debug(Lib.MkLazy(func() string { + return fmt.Sprintf("Next typecheck: forms (%v), terms (%v), types (%v)", + !forms.Empty(), !typed_terms.Empty(), !tys.Empty()) + })) + calls := []func(chan bool){} for _, form := range forms.GetSlice() { diff --git a/src/main.go b/src/main.go index 70d2995d..1e72994f 100644 --- a/src/main.go +++ b/src/main.go @@ -205,7 +205,7 @@ func initDebuggers() { equality.InitDebugger() incremental.InitDebugger() Search.InitDebugger() - // Typing.InitDebugger() + Typing.InitDebugger() Unif.InitDebugger() Engine.InitDebugger() gs3.InitDebugger() From 0c627a363178fa2b501c1163151db0aa323ff85c Mon Sep 17 00:00:00 2001 From: Johann Rosain Date: Mon, 28 Jul 2025 09:30:46 +0200 Subject: [PATCH 11/30] Add some basic tests on the elaboration --- devtools/test-suite/basic/test-typing-elab-1.p | 7 +++++++ devtools/test-suite/basic/test-typing-elab-2.p | 7 +++++++ devtools/test-suite/basic/test-typing-elab-3.p | 4 ++++ src/Engine/tptp-defined-types.go | 2 +- 4 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 devtools/test-suite/basic/test-typing-elab-1.p create mode 100644 devtools/test-suite/basic/test-typing-elab-2.p create mode 100644 devtools/test-suite/basic/test-typing-elab-3.p diff --git a/devtools/test-suite/basic/test-typing-elab-1.p b/devtools/test-suite/basic/test-typing-elab-1.p new file mode 100644 index 00000000..1a650628 --- /dev/null +++ b/devtools/test-suite/basic/test-typing-elab-1.p @@ -0,0 +1,7 @@ +% should fail because $lesseq is a defined function for $int, $rat and $real but is not polymorphic +% for any type +% exit: 1 + +tff(ty_type, type, ty : $tType). + +tff(conj, conjecture, ! [A : ty] : $lesseq(A, A)). diff --git a/devtools/test-suite/basic/test-typing-elab-2.p b/devtools/test-suite/basic/test-typing-elab-2.p new file mode 100644 index 00000000..ad8ea066 --- /dev/null +++ b/devtools/test-suite/basic/test-typing-elab-2.p @@ -0,0 +1,7 @@ +% should fail because $quotient is a defined function for $int, $rat and $real but is not polymorphic +% for any type +% exit: 1 + +tff(ty_type, type, ty : $tType). + +tff(conj, conjecture, ! [A : ty] : $lesseq($quotient(A, A), 1)). diff --git a/devtools/test-suite/basic/test-typing-elab-3.p b/devtools/test-suite/basic/test-typing-elab-3.p new file mode 100644 index 00000000..fed2fe93 --- /dev/null +++ b/devtools/test-suite/basic/test-typing-elab-3.p @@ -0,0 +1,4 @@ +% quotient is defined specifically for integers +% result: NOT VALID + +tff(conj, conjecture, $lesseq($quotient(2, 2), 1)). diff --git a/src/Engine/tptp-defined-types.go b/src/Engine/tptp-defined-types.go index 8ddc3e90..041f8c0d 100644 --- a/src/Engine/tptp-defined-types.go +++ b/src/Engine/tptp-defined-types.go @@ -106,7 +106,7 @@ func initialContext() Context { mkDefined("$remainder_e", 2, Lib.MkSome(Lib.MkListV(tInt, tRat, tReal)), binPoly(tNumber)) mkDefined("$remainder_t", 2, Lib.MkSome(Lib.MkListV(tInt, tRat, tReal)), binPoly(tNumber)) mkDefined("$remainder_f", 2, Lib.MkSome(Lib.MkListV(tInt, tRat, tReal)), binPoly(tNumber)) - mkDefined("$quotient", 2, Lib.MkSome(Lib.MkListV(tRat, tReal)), Parser.MkTypeAll( + mkDefined("$quotient", 2, Lib.MkSome(Lib.MkListV(tInt, tRat, tReal)), Parser.MkTypeAll( []Lib.Pair[string, Parser.PAtomicType]{ Lib.MkPair("number", tType.(Parser.PAtomicType)), Lib.MkPair("rat_or_real", tType.(Parser.PAtomicType)), From 59cb149324478d0ee356bbcf465afdabccec7c86 Mon Sep 17 00:00:00 2001 From: Johann Rosain Date: Mon, 28 Jul 2025 12:49:03 +0200 Subject: [PATCH 12/30] Replace MappableString with a proper printing management --- devtools/test-suite/proofs/tf1_basic_thm-2.p | 2 +- devtools/test-suite/proofs/tf1_basic_thm.p | 2 +- src/AST/form-list.go | 9 - src/AST/formsDef.go | 240 +++--------- src/AST/formula.go | 3 +- src/AST/maker.go | 2 +- src/AST/mapped_strings.go | 172 --------- src/AST/modular-printing.go | 362 ++++++++++++++++++ src/AST/printers.go | 95 +++++ src/AST/quantifiers.go | 51 +-- src/AST/term.go | 28 +- src/AST/termsDef.go | 130 +------ src/AST/ty-syntax.go | 58 ++- src/AST/typed-vars.go | 30 +- src/Core/form_and_terms.go | 3 +- src/Mods/equality/bse/equality_problem.go | 2 +- .../equality/bse/equality_problem_list.go | 2 +- src/Mods/equality/eqStruct/term_pair.go | 2 +- src/Mods/lambdapi/context.go | 10 +- src/Mods/lambdapi/formDecorator.go | 262 ++++++------- src/Mods/lambdapi/output.go | 38 +- src/Mods/lambdapi/proof.go | 46 +-- src/Mods/lambdapi/utils.go | 54 ++- src/Mods/rocq/context.go | 8 +- src/Mods/rocq/output.go | 29 +- src/Mods/rocq/proof.go | 7 +- src/Mods/tptp/output.go | 32 +- src/Mods/tptp/proof.go | 61 +-- src/Search/proof.go | 2 +- src/Unif/parsing.go | 19 +- src/main.go | 3 +- src/options.go | 10 +- 32 files changed, 848 insertions(+), 926 deletions(-) delete mode 100644 src/AST/mapped_strings.go create mode 100644 src/AST/modular-printing.go create mode 100644 src/AST/printers.go diff --git a/devtools/test-suite/proofs/tf1_basic_thm-2.p b/devtools/test-suite/proofs/tf1_basic_thm-2.p index f4838a46..a814c1b8 100644 --- a/devtools/test-suite/proofs/tf1_basic_thm-2.p +++ b/devtools/test-suite/proofs/tf1_basic_thm-2.p @@ -1,4 +1,4 @@ -% args: -proof -no_id +% args: -proof % result: VALID tff(list_type,type, diff --git a/devtools/test-suite/proofs/tf1_basic_thm.p b/devtools/test-suite/proofs/tf1_basic_thm.p index c2ed4f90..5718a0f8 100644 --- a/devtools/test-suite/proofs/tf1_basic_thm.p +++ b/devtools/test-suite/proofs/tf1_basic_thm.p @@ -1,4 +1,4 @@ -% args: -proof -no_id +% args: -proof % result: VALID tff(list_type,type, diff --git a/src/AST/form-list.go b/src/AST/form-list.go index b5aad920..8c023ac8 100644 --- a/src/AST/form-list.go +++ b/src/AST/form-list.go @@ -48,15 +48,6 @@ func LsSubstByTerm(formulas Lib.List[Form], meta Meta, term Term) Lib.List[Form] return formulas } -// ex-name: ToMappableStringSlice -func LsToMappableStringSlice(formulas Lib.List[Form]) []MappableString { - forms := []MappableString{} - for _, form := range formulas.GetSlice() { - forms = append(forms, form.(MappableString)) - } - return forms -} - func LsFlatten(formulas Lib.List[Form]) Lib.List[Form] { result := Lib.NewList[Form]() diff --git a/src/AST/formsDef.go b/src/AST/formsDef.go index 556ffd97..412d633f 100644 --- a/src/AST/formsDef.go +++ b/src/AST/formsDef.go @@ -37,8 +37,7 @@ package AST import ( - "strings" - + "fmt" "github.com/GoelandProver/Goeland/Glob" "github.com/GoelandProver/Goeland/Lib" ) @@ -88,7 +87,7 @@ type All struct { } func MakeAllSimple(i int, vars Lib.List[TypedVar], forms Form, metas Lib.Set[Meta]) All { - return All{makeQuantifier(i, vars, forms, metas, AllQuant)} + return All{makeQuantifier(i, vars, forms, metas, ConnAll)} } func MakeAll(i int, vars Lib.List[TypedVar], forms Form) All { @@ -143,7 +142,7 @@ type Ex struct { } func MakeExSimple(i int, vars Lib.List[TypedVar], forms Form, metas Lib.Set[Meta]) Ex { - return Ex{makeQuantifier(i, vars, forms, metas, ExQuant)} + return Ex{makeQuantifier(i, vars, forms, metas, ConnEx)} } func MakeEx(i int, vars Lib.List[TypedVar], forms Form) Ex { @@ -194,7 +193,6 @@ func (e Ex) ReplaceMetaByTerm(meta Meta, term Term) Form { // Or type Or struct { - *MappedString index int forms Lib.List[Form] metas Lib.Cache[Lib.Set[Meta], Or] @@ -203,10 +201,7 @@ type Or struct { /** Constructors **/ func MakeOrSimple(i int, forms Lib.List[Form], metas Lib.Set[Meta]) Or { - fms := &MappedString{} - or := Or{fms, i, forms, Lib.MkCache(metas, Or.forceGetMetas)} - fms.MappableString = &or - return or + return Or{i, forms, Lib.MkCache(metas, Or.forceGetMetas)} } func MakeOr(i int, forms Lib.List[Form]) Or { @@ -249,31 +244,18 @@ func (o Or) Equals(f any) bool { } func (o Or) Copy() Form { - fms := &MappedString{} - or := Or{ - fms, + return Or{ o.index, Lib.ListCpy(o.forms), o.metas.Copy(Lib.Set[Meta].Copy), } - fms.MappableString = &or - return or } func (o Or) ToString() string { - return o.MappedString.ToString() -} - -func (o Or) ToMappedStringSurround(mapping MapString, displayTypes bool) string { - return "(%s)" -} - -func (o Or) ToMappedStringChild(mapping MapString, displayTypes bool) (separator, emptyValue string) { - return " " + mapping[OrConn] + " ", "" -} - -func (o Or) GetChildrenForMappedString() []MappableString { - return LsToMappableStringSlice(o.GetChildFormulas()) + return o.forms.ToString( + func(f Form) string { return printer.Str(printer.SurroundChild(f.ToString())) }, + printer.StrConn(ConnOr), "", + ) } func (o Or) ReplaceTermByTerm(old Term, new Term) (Form, bool) { @@ -315,7 +297,6 @@ func (o Or) ReplaceMetaByTerm(meta Meta, term Term) Form { // And type And struct { - *MappedString index int forms Lib.List[Form] metas Lib.Cache[Lib.Set[Meta], And] @@ -324,10 +305,7 @@ type And struct { /** Constructors **/ func MakeAndSimple(i int, forms Lib.List[Form], metas Lib.Set[Meta]) And { - fms := &MappedString{} - and := And{fms, i, forms, Lib.MkCache(metas, And.forceGetMetas)} - fms.MappableString = &and - return and + return And{i, forms, Lib.MkCache(metas, And.forceGetMetas)} } func MakeAndSimpleBinary(i int, forms Lib.List[Form], metas Lib.Set[Meta]) And { @@ -390,31 +368,18 @@ func (a And) Equals(other any) bool { } func (a And) Copy() Form { - fms := &MappedString{} - and := And{ - fms, + return And{ a.index, Lib.ListCpy(a.forms), a.metas.Copy(Lib.Set[Meta].Copy), } - fms.MappableString = &and - return and } func (a And) ToString() string { - return a.MappedString.ToString() -} - -func (a And) ToMappedStringSurround(mapping MapString, displayTypes bool) string { - return "(%s)" -} - -func (a And) ToMappedStringChild(mapping MapString, displayTypes bool) (separator, emptyValue string) { - return " " + mapping[AndConn] + " ", "" -} - -func (a And) GetChildrenForMappedString() []MappableString { - return LsToMappableStringSlice(a.GetChildFormulas()) + return a.forms.ToString( + func(f Form) string { return printer.Str(printer.SurroundChild(f.ToString())) }, + printer.StrConn(ConnAnd), "", + ) } func (a And) ReplaceTermByTerm(old Term, new Term) (Form, bool) { @@ -456,23 +421,18 @@ func (a And) ReplaceMetaByTerm(meta Meta, term Term) Form { // Equivalence type Equ struct { - *MappedString index int f1, f2 Form metas Lib.Cache[Lib.Set[Meta], Equ] } func MakeEquSimple(i int, firstForm, secondForm Form, metas Lib.Set[Meta]) Equ { - fms := &MappedString{} - equ := Equ{ - fms, + return Equ{ i, firstForm, secondForm, Lib.MkCache(metas, Equ.forceGetMetas), } - fms.MappableString = &equ - return equ } func MakeEqu(i int, firstForm, secondForm Form) Equ { @@ -483,32 +443,16 @@ func MakerEqu(firstForm, secondForm Form) Equ { return MakeEqu(MakerIndexFormula(), firstForm, secondForm) } -func (e Equ) ToMappedStringSurround(mapping MapString, displayTypes bool) string { - return "(%s)" -} - -func (e Equ) ToMappedStringChild(mapping MapString, displayTypes bool) (separator, emptyValue string) { - return " " + mapping[EquConn] + " ", "" -} - -func (e Equ) GetChildrenForMappedString() []MappableString { - return LsToMappableStringSlice(e.GetChildFormulas()) -} - func (e Equ) GetIndex() int { return e.index } func (e Equ) GetF1() Form { return e.f1.Copy() } func (e Equ) GetF2() Form { return e.f2.Copy() } func (e Equ) Copy() Form { - fms := &MappedString{} - equ := Equ{ - fms, + return Equ{ e.index, e.GetF1(), e.GetF2(), e.metas.Copy(Lib.Set[Meta].Copy), } - fms.MappableString = &equ - return equ } func (e Equ) forceGetMetas() Lib.Set[Meta] { @@ -522,7 +466,13 @@ func (e Equ) GetMetas() Lib.Set[Meta] { return e.metas.Get(e) } -func (e Equ) ToString() string { return e.ToMappedString(DefaultMapString, true) } +func (e Equ) ToString() string { + return fmt.Sprintf("%s %s %s", + printer.Str(printer.SurroundChild(e.f1.ToString())), + printer.StrConn(ConnEqu), + printer.Str(printer.SurroundChild(e.f2.ToString())), + ) +} func (e Equ) Equals(f any) bool { oth, isEqu := f.(Equ) @@ -583,23 +533,18 @@ func (e Equ) ReplaceMetaByTerm(meta Meta, term Term) Form { // Implication type Imp struct { - *MappedString index int f1, f2 Form metas Lib.Cache[Lib.Set[Meta], Imp] } func MakeImpSimple(i int, firstForm, secondForm Form, metas Lib.Set[Meta]) Imp { - fms := &MappedString{} - imp := Imp{ - fms, + return Imp{ i, firstForm, secondForm, Lib.MkCache(metas, Imp.forceGetMetas), } - fms.MappableString = &imp - return imp } func MakeImp(i int, firstForm, secondForm Form) Imp { @@ -610,32 +555,16 @@ func MakerImp(firstForm, secondForm Form) Imp { return MakeImp(MakerIndexFormula(), firstForm, secondForm) } -func (i Imp) ToMappedStringSurround(mapping MapString, displayTypes bool) string { - return "(%s)" -} - -func (i Imp) ToMappedStringChild(mapping MapString, displayTypes bool) (separator, emptyValue string) { - return " " + mapping[ImpConn] + " ", "" -} - -func (i Imp) GetChildrenForMappedString() []MappableString { - return LsToMappableStringSlice(i.GetChildFormulas()) -} - func (i Imp) GetIndex() int { return i.index } func (i Imp) GetF1() Form { return i.f1.Copy() } func (i Imp) GetF2() Form { return i.f2.Copy() } func (i Imp) Copy() Form { - fms := &MappedString{} - imp := Imp{ - fms, + return Imp{ i.index, i.GetF1(), i.GetF2(), i.metas.Copy(Lib.Set[Meta].Copy), } - fms.MappableString = &imp - return imp } func (i Imp) forceGetMetas() Lib.Set[Meta] { @@ -649,7 +578,13 @@ func (i Imp) GetMetas() Lib.Set[Meta] { return i.metas.Get(i) } -func (i Imp) ToString() string { return i.ToMappedString(DefaultMapString, true) } +func (i Imp) ToString() string { + return fmt.Sprintf("%s %s %s", + printer.Str(printer.SurroundChild(i.f1.ToString())), + printer.StrConn(ConnImp), + printer.Str(printer.SurroundChild(i.f2.ToString())), + ) +} func (i Imp) Equals(other any) bool { if typed, ok := other.(Imp); ok { @@ -713,7 +648,6 @@ func (i Imp) ReplaceMetaByTerm(meta Meta, term Term) Form { // Not type Not struct { - *MappedString index int f Form metas Lib.Cache[Lib.Set[Meta], Not] @@ -722,10 +656,7 @@ type Not struct { /** Constructors **/ func MakeNotSimple(i int, form Form, metas Lib.Set[Meta]) Not { - fms := &MappedString{} - not := Not{fms, i, form, Lib.MkCache(metas, Not.forceGetMetas)} - fms.MappableString = ¬ - return not + return Not{i, form, Lib.MkCache(metas, Not.forceGetMetas)} } func MakeNot(i int, form Form) Not { @@ -773,19 +704,10 @@ func (n Not) Copy() Form { } func (n Not) ToString() string { - return n.MappedString.ToString() -} - -func (n Not) ToMappedStringSurround(mapping MapString, displayTypes bool) string { - return mapping[NotConn] + "(%s)" -} - -func (n Not) ToMappedStringChild(mapping MapString, displayTypes bool) (separator, emptyValue string) { - return "", "" -} - -func (n Not) GetChildrenForMappedString() []MappableString { - return LsToMappableStringSlice(n.GetChildFormulas()) + return fmt.Sprintf("%s%s", + printer.StrConn(ConnNot), + printer.Str(printer.SurroundChild(n.f.ToString())), + ) } func (n Not) ReplaceTermByTerm(old Term, new Term) (Form, bool) { @@ -865,7 +787,6 @@ func getDeepFormWithoutNot(form Form, isEven bool) (Form, bool) { // Predicates type Pred struct { - *MappedString index int id Id tys Lib.List[Ty] @@ -880,17 +801,13 @@ func MakePredSimple( terms Lib.List[Term], metas Lib.Set[Meta], ) Pred { - fms := &MappedString{} - pred := Pred{ - fms, + return Pred{ index, id, tys, terms, Lib.MkCache(metas, Pred.forceGetMetas), } - fms.MappableString = &pred - return pred } func MakePred( @@ -928,41 +845,12 @@ func (p Pred) GetArgs() Lib.List[Term] { return p.args } func (p Pred) RenameVariables() Form { return p } func (p Pred) ToString() string { - return p.MappedString.ToString() -} - -func (p Pred) ToMappedStringSurround(mapping MapString, displayTypes bool) string { - if p.tys.Empty() && p.GetArgs().Empty() { - return p.GetID().ToMappedString(mapping, displayTypes) + "%s" - } - args := []string{} - - if !p.tys.Empty() { - if tv := Lib.ListToString(p.tys, ", ", mapping[PredEmpty]); tv != "" { - args = append(args, tv) - } - } - - args = append(args, "%s") - - if p.GetID().GetName() == "=" { - return "(" + strings.Join(args, " "+mapping[PredTypeVarSep]+" ") + ")" - } - - return p.GetID().ToMappedString(mapping, displayTypes) + "(" + strings.Join(args, " "+mapping[PredTypeVarSep]+" ") + ")" -} - -func (p Pred) ToMappedStringChild(mapping MapString, displayTypes bool) (separator, emptyValue string) { - if p.GetID().GetName() == "=" { - return " = ", mapping[PredEmpty] - } - - return ", ", mapping[PredEmpty] -} - -func (p Pred) GetChildrenForMappedString() []MappableString { - mappableStringList := Lib.ListMap(p.GetArgs(), Glob.To[MappableString]) - return mappableStringList.GetSlice() + return printer.OnFunctionalArgs( + p.id, + Lib.ListToString(p.tys, printer.StrConn(SepTyArgs), ""), + printer.StrConn(SepArgsTyArgs), + p.args, + ) } func (p Pred) Copy() Form { @@ -1110,33 +998,18 @@ func (p Pred) ReplaceMetaByTerm(meta Meta, term Term) Form { // True and False type Top struct { - *MappedString index int } func MakeTop(i int) Top { - fms := &MappedString{} - top := Top{fms, i} - fms.MappableString = &top - return top + return Top{i} } func MakerTop() Top { return MakeTop(MakerIndexFormula()) } -func (t Top) ToMappedStringSurround(mapping MapString, displayTypes bool) string { - return "%s" -} - -func (t Top) ToMappedStringChild(mapping MapString, displayTypes bool) (separator, emptyValue string) { - return "", mapping[TopType] -} - -func (t Top) GetChildrenForMappedString() []MappableString { - return LsToMappableStringSlice(t.GetChildFormulas()) -} - +func (Top) ToString() string { return printer.StrConn(ConnTop) } func (t Top) Copy() Form { return MakeTop(t.GetIndex()) } func (Top) Equals(f any) bool { _, isTop := f.(Top); return isTop } func (Top) GetMetas() Lib.Set[Meta] { return Lib.EmptySet[Meta]() } @@ -1153,33 +1026,18 @@ func (t Top) ReplaceMetaByTerm(meta Meta, term Term) Form { return t } /* Bot (always false) definition */ type Bot struct { - *MappedString index int } func MakeBot(i int) Bot { - fms := &MappedString{} - bot := Bot{fms, i} - fms.MappableString = &bot - return bot + return Bot{i} } func MakerBot() Bot { return MakeBot(MakerIndexFormula()) } -func (b Bot) ToMappedStringSurround(mapping MapString, displayTypes bool) string { - return "%s" -} - -func (b Bot) ToMappedStringChild(mapping MapString, displayTypes bool) (separator, emptyValue string) { - return "", mapping[BotType] -} - -func (b Bot) GetChildrenForMappedString() []MappableString { - return LsToMappableStringSlice(b.GetChildFormulas()) -} - +func (Bot) ToString() string { return printer.StrConn(ConnBot) } func (b Bot) Copy() Form { return MakeBot(b.GetIndex()) } func (Bot) Equals(f any) bool { _, isBot := f.(Bot); return isBot } func (Bot) GetMetas() Lib.Set[Meta] { return Lib.EmptySet[Meta]() } diff --git a/src/AST/formula.go b/src/AST/formula.go index dc14eff9..05ceb63b 100644 --- a/src/AST/formula.go +++ b/src/AST/formula.go @@ -51,7 +51,8 @@ type Form interface { GetChildFormulas() Lib.List[Form] Lib.Copyable[Form] - MappableString + Lib.Stringable + Lib.Comparable ReplaceTermByTerm(old Term, new Term) (Form, bool) SubstTy(old TyGenVar, new Ty) Form diff --git a/src/AST/maker.go b/src/AST/maker.go index c67aa8f4..427701e2 100644 --- a/src/AST/maker.go +++ b/src/AST/maker.go @@ -68,7 +68,7 @@ func Init() { Reset() Id_eq = MakerId("=") EmptyPredEq = MakerPred(Id_eq, Lib.NewList[Ty](), Lib.NewList[Term]()) - initDefaultMap() + initPrinters() initTPTPNativeTypes() } diff --git a/src/AST/mapped_strings.go b/src/AST/mapped_strings.go deleted file mode 100644 index 1496913e..00000000 --- a/src/AST/mapped_strings.go +++ /dev/null @@ -1,172 +0,0 @@ -/** -* Copyright 2022 by the authors (see AUTHORS). -* -* Goéland is an automated theorem prover for first order logic. -* -* This software is governed by the CeCILL license under French law and -* abiding by the rules of distribution of free software. You can use, -* modify and/ or redistribute the software under the terms of the CeCILL -* license as circulated by CEA, CNRS and INRIA at the following URL -* "http://www.cecill.info". -* -* As a counterpart to the access to the source code and rights to copy, -* modify and redistribute granted by the license, users are provided only -* with a limited warranty and the software's author, the holder of the -* economic rights, and the successive licensors have only limited -* liability. -* -* In this respect, the user's attention is drawn to the risks associated -* with loading, using, modifying and/or developing or reproducing the -* software by the user in light of its specific status of free software, -* that may mean that it is complicated to manipulate, and that also -* therefore means that it is reserved for developers and experienced -* professionals having in-depth computer knowledge. Users are therefore -* encouraged to load and test the software's suitability as regards their -* requirements in conditions enabling the security of their systems and/or -* data to be ensured and, more generally, to use and operate it in the -* same conditions as regards security. -* -* The fact that you are presently reading this means that you have had -* knowledge of the CeCILL license and that you accept its terms. -**/ - -/** -* This file provides things. -**/ - -package AST - -import ( - "fmt" - "strings" - - "github.com/GoelandProver/Goeland/Glob" - "github.com/GoelandProver/Goeland/Lib" -) - -type FormulaType int -type MapString map[FormulaType]string - -const ( - AndConn FormulaType = iota - OrConn - ImpConn - EquConn - NotConn - TopType - BotType - AllQuant - ExQuant - AllTypeQuant - QuantVarOpen - QuantVarClose - QuantVarSep - PredEmpty - PredTypeVarSep - TypeVarType -) - -var DefaultMapString = make(map[FormulaType]string) - -func initDefaultMap() { - if Glob.IsPrettyPrint() { - DefaultMapString[AndConn] = "∧" - DefaultMapString[OrConn] = "∨" - DefaultMapString[ImpConn] = "⇒" - DefaultMapString[EquConn] = "⇔" - DefaultMapString[NotConn] = "¬" - DefaultMapString[TopType] = "⊤" - DefaultMapString[BotType] = "⊥" - DefaultMapString[AllQuant] = "∀" - DefaultMapString[ExQuant] = "∃" - DefaultMapString[AllTypeQuant] = "∀" - DefaultMapString[PredEmpty] = "∅" - } else { - DefaultMapString[AndConn] = "&" - DefaultMapString[OrConn] = "|" - DefaultMapString[ImpConn] = "=>" - DefaultMapString[EquConn] = "<=>" - DefaultMapString[NotConn] = "~" - DefaultMapString[TopType] = "$true" - DefaultMapString[BotType] = "$false" - DefaultMapString[AllQuant] = "!" - DefaultMapString[ExQuant] = "?" - DefaultMapString[AllTypeQuant] = ">!" - DefaultMapString[PredEmpty] = "" - } - DefaultMapString[QuantVarOpen] = "[" - DefaultMapString[QuantVarClose] = "]" - DefaultMapString[QuantVarSep] = ":" - DefaultMapString[PredTypeVarSep] = ";" - DefaultMapString[TypeVarType] = "$tType" -} - -type MappableString interface { - Glob.Stringable - Lib.Comparable - - ToMappedString(MapString, bool) string - ToMappedStringSurround(MapString, bool) string - //Return the separator for each child as 1st return, and if there are no children, return the value as 2nd return - ToMappedStringChild(MapString, bool) (separator string, emptyValue string) - GetChildrenForMappedString() []MappableString -} - -type MappedString struct { - MappableString -} - -func (fms MappedString) ToString() string { - return fms.ToMappedString(DefaultMapString, true) -} - -func (fms MappedString) ToMappedString(mapping MapString, displayType bool) string { - surround := fms.ToMappedStringSurround(mapping, displayType) - separator, emptyValue := fms.ToMappedStringChild(mapping, displayType) - children := ListToMappedString(fms.GetChildrenForMappedString(), separator, emptyValue, mapping, displayType) - return fmt.Sprintf(surround, children) -} - -func ListToMappedString[T MappableString](sgbl []T, separator, emptyValue string, mapping MapString, displayTypes bool) string { - strArr := []string{} - - for _, element := range sgbl { - strArr = append(strArr, element.ToMappedString(mapping, displayTypes)) - } - - if len(strArr) == 0 && emptyValue != "" { - strArr = append(strArr, emptyValue) - } - - return strings.Join(strArr, separator) -} - -type SimpleStringMappable string - -func (ssm *SimpleStringMappable) ToString() string { - return string(*ssm) -} - -func (ssm *SimpleStringMappable) Equals(other any) bool { - if typed, ok := other.(*SimpleStringMappable); ok { - return string(*typed) == string(*ssm) - } - - return false -} - -func (ssm *SimpleStringMappable) ToMappedString(MapString, bool) string { - return string(*ssm) -} - -func (ssm *SimpleStringMappable) ToMappedStringSurround(MapString, bool) string { - return "" -} - -func (ssm *SimpleStringMappable) ToMappedStringChild(MapString, bool) (separator string, emptyValue string) { - return "", "" -} - -func (ssm *SimpleStringMappable) GetChildrenForMappedString() []MappableString { - return []MappableString{} -} diff --git a/src/AST/modular-printing.go b/src/AST/modular-printing.go new file mode 100644 index 00000000..a901bc16 --- /dev/null +++ b/src/AST/modular-printing.go @@ -0,0 +1,362 @@ +/** +* Copyright 2022 by the authors (see AUTHORS). +* +* Goéland is an automated theorem prover for first order logic. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +**/ + +/** + * This file provides: + * 1. an interface of modular printers + * 2. printers for multiple outputs (default one, TPTP, Rocq, etc) + * + * A modular printer is composed of two objects: + * - the PrinterAction object that defines a *function* to apply on e.g., ids, variables, everything, etc + * so that generic transformation of stuff can be applied. These actions can be composed (e.g., if you + * wish to avoid printing IDs and also sanitize your string, you can get a PrinterAction that does both + * by using noIdAction.Compose(sanitizeAction)). Note that the operations are not always commutative, + * it is your responsibility to ensure that stuff is composed in the right order. + * + * - the PrinterConnective object that defines all the connectives and a printer for them. A PrinterConnective + * can inherit from another one, and if a connective isn't defined for it, it will search for it in its parent + * connective. All PrinterConnective should inherit from the default one (where everything is defined) by default. + * + * If you wish to implement a new printer, simply provide a PrinterAction and a PrinterConnective to it. +**/ + +package AST + +import ( + "fmt" + "unicode" + "unicode/utf8" + + "github.com/GoelandProver/Goeland/Glob" + "github.com/GoelandProver/Goeland/Lib" +) + +var printer_debug Glob.Debugger + +type PrinterAction struct { + genericAction func(string) string // Always executed + actionOnId func(Id) string + actionOnBoundVar func(string, int) string + actionOnMeta func(string, int) string + actionOnType func(string) string + actionOnTypedVar func(Lib.Pair[string, Ty]) string +} + +func (p PrinterAction) Compose(oth PrinterAction) PrinterAction { + return PrinterAction{ + genericAction: func(s string) string { return oth.genericAction(p.genericAction(s)) }, + actionOnId: func(i Id) string { return oth.actionOnId(MakeId(i.index, p.actionOnId(i))) }, + actionOnBoundVar: func(name string, index int) string { + return oth.actionOnBoundVar(p.actionOnBoundVar(name, index), index) + }, + actionOnMeta: func(name string, index int) string { + return oth.actionOnMeta(p.actionOnMeta(name, index), index) + }, + actionOnType: func(name string) string { + return oth.actionOnType(p.actionOnType(name)) + }, + actionOnTypedVar: func(pair Lib.Pair[string, Ty]) string { + return oth.actionOnTypedVar(Lib.MkPair(p.actionOnTypedVar(pair), pair.Snd)) + }, + } +} + +func (p PrinterAction) Str(s string) string { + return p.genericAction(s) +} + +func (p PrinterAction) StrId(i Id) string { + return p.Str(p.actionOnId(i)) +} + +func (p PrinterAction) StrBound(name string, index int) string { + return p.Str(p.actionOnBoundVar(name, index)) +} + +func (p PrinterAction) StrMeta(name string, index int) string { + return p.Str(p.actionOnMeta(name, index)) +} + +func (p PrinterAction) StrTy(name string) string { + return p.Str(p.actionOnType(name)) +} + +func (p PrinterAction) StrTyVar(pair Lib.Pair[string, Ty]) string { + return p.Str(p.actionOnTypedVar(pair)) +} + +func PrinterIdentity(x string) string { return x } +func PrinterIdentityPair[T any](p Lib.Pair[string, T]) string { return p.Fst } +func PrinterIdentity2[T any](s string, _ T) string { return s } + +func MkPrinterAction( + genericAction func(string) string, + actionOnId func(Id) string, + actionOnBoundVar func(string, int) string, + actionOnMeta func(string, int) string, + actionOnType func(string) string, + actionOnTypedVar func(Lib.Pair[string, Ty]) string, +) PrinterAction { + return PrinterAction{genericAction, actionOnId, actionOnBoundVar, actionOnMeta, actionOnType, actionOnTypedVar} +} + +type Connective int + +type PrinterConnective struct { + name string + connectives map[Connective]string + inherit Lib.Option[PrinterConnective] +} + +func (p *PrinterConnective) StrConn(conn Connective) string { + var default_connective PrinterConnective + switch connective := p.inherit.(type) { + case Lib.None[PrinterConnective]: + default_connective = DefaultPrinterConnectives() + p.inherit = Lib.MkSome(default_connective) + case Lib.Some[PrinterConnective]: + default_connective = connective.Val + } + + if val, ok := p.connectives[conn]; ok { + printer_debug( + Lib.MkLazy(func() string { return fmt.Sprintf("Found connective %d in %s as %s", conn, p.name, val) })) + return val + } else { + if p.name == DefaultPrinterConnectives().name { + Glob.Anomaly( + "printer", + fmt.Sprintf("Connective %d not found in default connective", conn), + ) + } + } + + printer_debug(Lib.MkLazy(func() string { + return fmt.Sprintf("Connective %d not found in %s, trying in %s", conn, p.name, default_connective.name) + })) + return default_connective.StrConn(conn) +} + +func (p PrinterConnective) SurroundQuantified(s string) string { + return fmt.Sprintf("%s%s%s", p.StrConn(SurQuantStart), s, p.StrConn(SurQuantEnd)) +} + +func (p PrinterConnective) SurroundArgs(s string) string { + if len(s) == 0 { + return s + } + return fmt.Sprintf("%s%s%s", p.StrConn(SurFunctionalStart), s, p.StrConn(SurFunctionalEnd)) +} + +func (p PrinterConnective) SurroundChild(s string) string { + return fmt.Sprintf("%s%s%s", p.StrConn(SurComplexChildStart), s, p.StrConn(SurComplexChildEnd)) +} + +type Printer struct { + PrinterAction + *PrinterConnective +} + +func (p Printer) OnFunctionalArgs(i Id, tys, con string, args Lib.List[Term]) string { + // Hard-coding of the infix functionals. + // It'd maybe be useful to have an [Infix] generic action but I don't see how to do + // that for now. + infix := Lib.MkListV(Id_eq) + is_infix := Lib.ListMem(i, infix) + arguments := Lib.ListToString(args, p.StrConn(SepArgs), "") + + if is_infix { + if args.Len() != 2 { + Glob.Anomaly("Printer", fmt.Sprintf( + "invalid number of infix arguments: expected 2, got %d (in %s)", + args.Len(), + arguments, + )) + } + return fmt.Sprintf("%s %s %s", args.At(0).ToString(), i.ToString(), args.At(1).ToString()) + } else { + if len(tys) > 0 { + arguments = tys + con + arguments + } + return fmt.Sprintf("%s%s", i.ToString(), p.SurroundArgs(arguments)) + } +} + +func MkPrinterConnective(name string, connective_map map[Connective]string) PrinterConnective { + return PrinterConnective{ + name: name, + connectives: connective_map, + inherit: Lib.MkNone[PrinterConnective](), + } +} + +const ( + // Formula connectives + ConnAll Connective = iota + ConnEx + ConnAnd + ConnOr + ConnImp + ConnEqu + ConnNot + ConnTop + ConnBot + + // Type connectives + ConnPi + ConnMap + ConnProd + + SepVarsForm // separator between variables and a formula in quantifiers + SepArgs // separator of arguments in functionals + SepTyArgs // separator of type arguments in functionals + SepArgsTyArgs // separator between type arguments and arguments in functionals + SepTyVars // separator between typed variables (in quantifiers) + SepVarTy // separator between a var and its type (in quantifiers) + + SurQuantStart // Stuff that surrounds the variables of quantifiers + SurQuantEnd + SurFunctionalStart // Stuff that surrounds the arguments of functionals + SurFunctionalEnd + SurComplexChildStart // Surrounds "complex" child of formula/type (e.g. (A * B) > C) + SurComplexChildEnd +) + +func DefaultPrinterConnectives() PrinterConnective { + return MkPrinterConnective( + "DefaultPrinterConnective", + map[Connective]string{ + ConnAll: "!", + ConnEx: "?", + ConnAnd: " & ", + ConnOr: " | ", + ConnImp: "=>", + ConnEqu: "<=>", + ConnNot: "~", + ConnTop: "$true", + ConnBot: "$false", + + ConnPi: "!>", + ConnMap: ">", + ConnProd: "*", + + SepVarsForm: ": ", + SepArgs: ", ", + SepTyArgs: ", ", + SepArgsTyArgs: " ; ", + SepTyVars: ", ", + SepVarTy: ": ", + + SurQuantStart: "[", + SurQuantEnd: "]", + SurFunctionalStart: "(", + SurFunctionalEnd: ")", + SurComplexChildStart: "(", + SurComplexChildEnd: ")", + }, + ) +} + +var ( + printer Printer + PrettyPrinter Printer + PrintIDAction PrinterAction + + QuoteID PrinterAction +) + +func initPrinters() { + printer_debug = Glob.CreateDebugger("printer") + + default_connectives := DefaultPrinterConnectives() + printer = Printer{RemoveSuperfluousParenthesesAction(default_connectives), &default_connectives} + + prettyPrinterConnectives := MkPrinterConnective( + "PrettyPrinterConnective", + map[Connective]string{ + ConnAll: "∀", + ConnEx: "∃", + ConnAnd: " ∧ ", + ConnOr: " ∨ ", + ConnImp: "⇒", + ConnEqu: "⇔", + ConnNot: "¬", + ConnTop: "⊤", + ConnBot: "⊥", + + ConnPi: "Π", + ConnMap: "→", + ConnProd: "×", + }, + ) + + PrettyPrinter = Printer{ + RemoveSuperfluousParenthesesAction(prettyPrinterConnectives), + &prettyPrinterConnectives, + } + + PrintIDAction = PrinterAction{ + genericAction: PrinterIdentity, + actionOnId: func(i Id) string { return fmt.Sprintf("%s_%d", i.name, i.index) }, + actionOnBoundVar: PrinterIdentity2[int], + actionOnMeta: PrinterIdentity2[int], + actionOnType: PrinterIdentity, + actionOnTypedVar: PrinterIdentityPair[Ty], + } + + QuoteID = PrinterAction{ + genericAction: PrinterIdentity, + actionOnId: func(i Id) string { + r, _ := utf8.DecodeRuneInString(i.name) + if unicode.IsUpper(r) { + return fmt.Sprintf("'%s'", i.name) + } + return i.name + }, + actionOnBoundVar: PrinterIdentity2[int], + actionOnMeta: PrinterIdentity2[int], + actionOnType: PrinterIdentity, + actionOnTypedVar: PrinterIdentityPair[Ty], + } +} + +func ComposePrinter(p PrinterAction) { + printer.PrinterAction = printer.Compose(p) +} + +func GetPrinter() Printer { + return printer +} + +func SetPrinter(p Printer) { + printer = p +} diff --git a/src/AST/printers.go b/src/AST/printers.go new file mode 100644 index 00000000..dffbe26e --- /dev/null +++ b/src/AST/printers.go @@ -0,0 +1,95 @@ +/** +* Copyright 2022 by the authors (see AUTHORS). +* +* Goéland is an automated theorem prover for first order logic. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +**/ + +/** + * This file stores the different printers we have in Goeland. + **/ + +package AST + +import ( + "github.com/GoelandProver/Goeland/Lib" + "strings" +) + +func RemoveSuperfluousParenthesesAction(connectives PrinterConnective) PrinterAction { + return PrinterAction{ + genericAction: func(s string) string { + if len(s) == 0 { + return s + } + + complexChildStart := connectives.StrConn(SurComplexChildStart) + complexChildEnd := connectives.StrConn(SurComplexChildEnd) + if s[:len(complexChildStart)] == complexChildStart && + s[len(s)-len(complexChildEnd):] == complexChildEnd { + tentative_str := s[len(complexChildStart) : len(s)-len(complexChildEnd)] + is_open := 0 + for i, char := range tentative_str { + if len(complexChildStart) <= i && tentative_str[i-len(complexChildStart):i] == complexChildStart { + is_open += 1 + } + if len(complexChildEnd) <= i && tentative_str[i-len(complexChildEnd):i] == complexChildEnd { + is_open -= 1 + } + if char == ' ' && is_open == 0 { + return s + } + } + return tentative_str + } + + return s + }, + actionOnId: func(i Id) string { return i.name }, + actionOnBoundVar: func(s string, index int) string { return s }, + actionOnMeta: func(s string, index int) string { return s }, + actionOnType: func(s string) string { return s }, + actionOnTypedVar: func(p Lib.Pair[string, Ty]) string { return p.Fst }, + } +} + +func SanitizerAction(connectives PrinterConnective, forbidden_chars []string) PrinterAction { + return PrinterAction{ + genericAction: func(s string) string { + for _, c := range forbidden_chars { + s = strings.ReplaceAll(s, c, "_") + } + return s + }, + actionOnId: func(i Id) string { return i.name }, + actionOnBoundVar: func(s string, index int) string { return s }, + actionOnMeta: func(s string, index int) string { return s }, + actionOnType: func(s string) string { return s }, + actionOnTypedVar: func(p Lib.Pair[string, Ty]) string { return p.Fst }, + } +} diff --git a/src/AST/quantifiers.go b/src/AST/quantifiers.go index 5ceabff2..73b9723e 100644 --- a/src/AST/quantifiers.go +++ b/src/AST/quantifiers.go @@ -38,33 +38,26 @@ package AST import ( "fmt" - "strings" "github.com/GoelandProver/Goeland/Lib" ) type quantifier struct { - *MappedString metas Lib.Cache[Lib.Set[Meta], quantifier] index int varList Lib.List[TypedVar] subForm Form - symbol FormulaType + symbol Connective } -func makeQuantifier(i int, vars Lib.List[TypedVar], subForm Form, metas Lib.Set[Meta], symbol FormulaType) quantifier { - fms := &MappedString{} - qua := quantifier{ - fms, +func makeQuantifier(i int, vars Lib.List[TypedVar], subForm Form, metas Lib.Set[Meta], symbol Connective) quantifier { + return quantifier{ Lib.MkCache(metas, quantifier.forceGetMetas), i, vars, subForm, symbol, } - fms.MappableString = &qua - - return qua } func (q quantifier) GetIndex() int { @@ -88,33 +81,17 @@ func (q quantifier) GetMetas() Lib.Set[Meta] { } func (q quantifier) ToString() string { - return q.MappedString.ToString() -} - -func (q quantifier) ToMappedStringChild(mapping MapString, displayTypes bool) (separator, emptyValue string) { - return " ", "" -} - -var varSeparator = " " - -func ChangeVarSeparator(sep string) string { - old := varSeparator - varSeparator = sep - return old -} - -func (q quantifier) ToMappedStringSurround(mapping MapString, displayTypes bool) string { - varStrings := []string{} - - str := mapping[QuantVarOpen] - str += ListToMappedString(q.GetVarList().GetSlice(), varSeparator, "", mapping, false) - varStrings = append(varStrings, str+mapping[QuantVarClose]) - - return "(" + mapping[q.symbol] + " " + strings.Join(varStrings, " ") + mapping[QuantVarSep] + " (%s))" -} - -func (q quantifier) GetChildrenForMappedString() []MappableString { - return LsToMappableStringSlice(q.GetChildFormulas()) + return fmt.Sprintf( + "%s %s%s%s", + printer.StrConn(q.symbol), + printer.SurroundQuantified( + Lib.ListMap(q.varList, func(t TypedVar) Lib.Pair[string, Ty] { + return Lib.MkPair(t.name, t.ty) + }).ToString(printer.StrTyVar, printer.StrConn(SepTyVars), ""), + ), + printer.StrConn(SepVarsForm), + printer.Str(q.subForm.ToString()), + ) } func (q quantifier) GetChildFormulas() Lib.List[Form] { diff --git a/src/AST/term.go b/src/AST/term.go index 116efe92..bfe5f5f3 100644 --- a/src/AST/term.go +++ b/src/AST/term.go @@ -42,7 +42,8 @@ import ( /* Term */ type Term interface { - MappableString + Lib.Comparable + Lib.Stringable Lib.Copyable[Term] GetIndex() int GetName() string @@ -59,38 +60,23 @@ type Term interface { /*** Makers ***/ func MakeId(i int, s string) Id { - fms := &MappedString{} - id := Id{fms, i, s} - fms.MappableString = &id - return id + return Id{i, s} } func MakeQuotedId(i int, s string) Id { - fms := &MappedString{} - id := Id{fms, i, "" + s + "'"} - fms.MappableString = &id - return id + return Id{i, "" + s + "'"} } func MakeVar(i int, s string) Var { - fms := &MappedString{} - newVar := Var{fms, i, s} - fms.MappableString = &newVar - return newVar + return Var{i, s} } func MakeMeta(index, occurence int, s string, f int, ty Ty) Meta { - fms := &MappedString{} - meta := Meta{fms, index, occurence, s, f, ty} - fms.MappableString = &meta - return meta + return Meta{index, occurence, s, f, ty} } func MakeFun(p Id, ty_args Lib.List[Ty], args Lib.List[Term], metas Lib.Set[Meta]) Fun { - fms := &MappedString{} - fun := Fun{fms, p, ty_args, args, Lib.MkCache(metas, Fun.forceGetMetas)} - fms.MappableString = fun - return fun + return Fun{p, ty_args, args, Lib.MkCache(metas, Fun.forceGetMetas)} } /*** Functions **/ diff --git a/src/AST/termsDef.go b/src/AST/termsDef.go index 455fc44a..3e195eee 100644 --- a/src/AST/termsDef.go +++ b/src/AST/termsDef.go @@ -37,10 +37,7 @@ package AST import ( - "fmt" "strings" - "unicode" - "unicode/utf8" "github.com/GoelandProver/Goeland/Glob" "github.com/GoelandProver/Goeland/Lib" @@ -50,7 +47,6 @@ import ( // Predicates / functions symbols type Id struct { - *MappedString index int name string } @@ -63,39 +59,7 @@ func (i Id) Copy() Term { return MakeId(i.GetIndex(), i.GetName() func (Id) ToMeta() Meta { return MakeEmptyMeta() } func (Id) GetMetas() Lib.Set[Meta] { return Lib.EmptySet[Meta]() } func (Id) GetMetaList() Lib.List[Meta] { return Lib.NewList[Meta]() } - -var ToStringId = func(i Id) string { - return fmt.Sprintf("%s_%d", i.GetName(), i.GetIndex()) -} - -func (i Id) ToMappedStringSurround(mapping MapString, displayTypes bool) string { - return "%s" -} - -func (i Id) ToMappedStringChild(mapping MapString, displayTypes bool) (separator, emptyValue string) { - return "", ToStringId(i) -} - -func NoIdToString(i Id) string { - return fmt.Sprintf("%s", i.GetName()) -} - -func QuotedToString(i Id) string { - if i.GetName() == "Goeland_I" || strings.Contains(i.GetName(), "Sko_") { - return fmt.Sprintf("%s", i.GetName()) - } else { - r, _ := utf8.DecodeRuneInString(i.GetName()) - if unicode.IsUpper(r) { - return fmt.Sprintf("'%s'", i.GetName()) - } else { - return fmt.Sprintf("%s", i.GetName()) - } - } -} - -func (i Id) GetChildrenForMappedString() []MappableString { - return []MappableString{} -} +func (i Id) ToString() string { return printer.StrId(i) } func (i Id) Equals(t any) bool { if typed, ok := t.(Id); ok { @@ -147,55 +111,19 @@ func (i Id) Less(u any) bool { // n-ary functions type Fun struct { - *MappedString p Id tys Lib.List[Ty] args Lib.List[Term] metas Lib.Cache[Lib.Set[Meta], Fun] } -func (f Fun) ToMappedStringSurround(mapping MapString, displayTypes bool) string { - return f.ToMappedStringSurroundWithId(f.GetID().ToMappedString(mapping, displayTypes), mapping, displayTypes) -} - -func (f Fun) ToMappedStringChild(mapping MapString, displayTypes bool) (separator, emptyValue string) { - return ", ", mapping[PredEmpty] -} - -func (f Fun) ToMappedStringSurroundWithId(idString string, mapping MapString, displayTypes bool) string { - if f.tys.Empty() && f.GetArgs().Empty() { - return idString + "%s" - } - - args := []string{} - if !f.tys.Empty() { - if tv := Lib.ListToString(f.tys, ", ", mapping[PredEmpty]); tv != "" { - args = append(args, tv) - } - } - - args = append(args, "%s") - - str := idString + "(" + strings.Join(args, mapping[PredTypeVarSep]) + ")" - - return str -} - -func ToFlatternStringSurrountWithId(f Fun, idString string, mapping MapString, displayTypes bool) string { - if f.GetArgs().Len() == 0 { - return idString + "%s" - } - args := []string{} - args = append(args, "%s") - - str := idString + "_" + strings.Join(args, mapping[PredTypeVarSep]) - - return str -} - -func (f Fun) GetChildrenForMappedString() []MappableString { - mappableList := Lib.ListMap(f.GetArgs(), Glob.To[MappableString]) - return mappableList.GetSlice() +func (f Fun) ToString() string { + return printer.OnFunctionalArgs( + f.p, + Lib.ListToString(f.tys, printer.StrConn(SepTyArgs), ""), + printer.StrConn(SepArgsTyArgs), + f.args, + ) } func (f Fun) GetID() Id { return f.p.Copy().(Id) } @@ -332,11 +260,11 @@ func (f Fun) Less(u any) bool { // Bound variables type Var struct { - *MappedString index int name string } +func (v Var) ToString() string { return printer.StrBound(v.name, v.index) } func (v Var) GetIndex() int { return v.index } func (v Var) GetName() string { return v.name } func (v Var) IsMeta() bool { return false } @@ -366,26 +294,6 @@ func (v Var) ReplaceSubTermBy(original_term, new_term Term) Term { func (v Var) SubstTy(TyGenVar, Ty) Term { return v } -func (v Var) ToMappedString(map_ MapString, type_ bool) string { - return v.GetName() -} - -func (v Var) ToMappedStringSurround(mapping MapString, displayTypes bool) string { - return "%s" -} - -func (v Var) ToMappedStringChild(mapping MapString, displayTypes bool) (separator, emptyValue string) { - if displayTypes { - return "", fmt.Sprintf("%s_%d", v.GetName(), v.GetIndex()) - } else { - return "", v.GetName() - } -} - -func (v Var) GetChildrenForMappedString() []MappableString { - return []MappableString{} -} - func (v Var) Less(u any) bool { switch t := u.(type) { case Term: @@ -400,7 +308,6 @@ func (v Var) Less(u any) bool { // Meta/Free variables type Meta struct { - *MappedString index int occurence int name string @@ -408,7 +315,8 @@ type Meta struct { ty Ty } -func (m Meta) GetFormula() int { return m.formula } +func (m Meta) ToString() string { return printer.StrMeta(m.name, m.index) } +func (m Meta) GetFormula() int { return m.formula } func (m Meta) GetName() string { return m.name } func (m Meta) GetIndex() int { return m.index } @@ -420,22 +328,6 @@ func (m Meta) GetMetas() Lib.Set[Meta] { return Lib.Singleton(m) } func (m Meta) GetMetaList() Lib.List[Meta] { return Lib.MkListV(m) } func (m Meta) GetTy() Ty { return m.ty } -func (m Meta) ToMappedStringSurround(mapping MapString, displayTypes bool) string { - return "%s" -} - -func (m Meta) ToMappedStringChild(mapping MapString, displayTypes bool) (separator, emptyValue string) { - if displayTypes { - return "", fmt.Sprintf("%s_%d : %s", m.GetName(), m.GetIndex(), m.ty.ToString()) - } else { - return "", fmt.Sprintf("%s_%d", m.GetName(), m.GetIndex()) - } -} - -func (m Meta) GetChildrenForMappedString() []MappableString { - return []MappableString{} -} - func (m Meta) Equals(t any) bool { if typed, ok := t.(Meta); ok { return typed.GetIndex() == m.GetIndex() diff --git a/src/AST/ty-syntax.go b/src/AST/ty-syntax.go index 654a80c2..4c66ce75 100644 --- a/src/AST/ty-syntax.go +++ b/src/AST/ty-syntax.go @@ -53,10 +53,10 @@ type TyGenVar interface { } type Ty interface { + Lib.Stringable + Lib.Comparable + Lib.Copyable[Ty] isTy() - ToString() string - Equals(any) bool - Copy() Ty SubstTy(TyGenVar, Ty) Ty } @@ -65,8 +65,10 @@ type tyVar struct { repr string } -func (tyVar) isTy() {} -func (v tyVar) ToString() string { return v.repr } +func (tyVar) isTy() {} +func (v tyVar) ToString() string { + return printer.StrBound(v.repr, 0) +} func (v tyVar) Equals(oth any) bool { if ov, ok := oth.(tyVar); ok { return v.repr == ov.repr @@ -82,9 +84,11 @@ type TyBound struct { index int } -func (TyBound) isTy() {} -func (TyBound) isGenVar() {} -func (b TyBound) ToString() string { return b.name } +func (TyBound) isTy() {} +func (TyBound) isGenVar() {} +func (b TyBound) ToString() string { + return printer.StrBound(b.name, b.index) +} func (b TyBound) Equals(oth any) bool { if bv, ok := oth.(TyBound); ok { return b.name == bv.name @@ -107,9 +111,11 @@ type TyMeta struct { formula int // for compatibility with term metas } -func (TyMeta) isTy() {} -func (TyMeta) isGenVar() {} -func (m TyMeta) ToString() string { return fmt.Sprintf("%s_%d", m.name, m.index) } +func (TyMeta) isTy() {} +func (TyMeta) isGenVar() {} +func (m TyMeta) ToString() string { + return printer.StrMeta(m.name, m.index) +} func (m TyMeta) Equals(oth any) bool { if om, ok := oth.(TyMeta); ok { return m.name == om.name && m.index == om.index @@ -145,10 +151,13 @@ type TyConstr struct { func (TyConstr) isTy() {} func (c TyConstr) ToString() string { - if c.args.Len() == 0 { - return c.symbol + if c.args.Empty() { + return printer.StrTy(c.symbol) } - return c.symbol + "(" + Lib.ListToString(c.args, ", ", "") + ")" + return fmt.Sprintf("%s%s", + printer.StrTy(c.symbol), + printer.SurroundArgs(Lib.ListToString(c.args, printer.StrConn(SepArgs), "")), + ) } func (c TyConstr) Equals(oth any) bool { @@ -185,7 +194,10 @@ type TyProd struct { func (TyProd) isTy() {} func (p TyProd) ToString() string { - return "(" + Lib.ListToString(p.args, " * ", "") + ")" + return p.args.ToString( + func(ty Ty) string { return printer.Str(printer.SurroundChild(ty.ToString())) }, + printer.StrConn(ConnProd), "", + ) } func (p TyProd) GetTys() Lib.List[Ty] { @@ -215,7 +227,11 @@ type TyFunc struct { func (TyFunc) isTy() {} func (f TyFunc) ToString() string { - return f.in.ToString() + " > " + f.out.ToString() + return fmt.Sprintf("%s %s %s", + printer.Str(printer.SurroundChild(f.in.ToString())), + printer.StrConn(ConnImp), + printer.Str(printer.SurroundChild(f.out.ToString())), + ) } func (f TyFunc) Equals(oth any) bool { if of, ok := oth.(TyFunc); ok { @@ -239,7 +255,15 @@ type TyPi struct { func (TyPi) isTy() {} func (p TyPi) ToString() string { - return "!> [" + p.vars.ToString(func(s string) string { return s }, ", ", "") + "] : (" + p.ty.ToString() + ")" + return fmt.Sprintf( + "%s %s%s%s", + printer.StrConn(ConnPi), + printer.SurroundQuantified( + p.vars.ToString(PrinterIdentity, printer.StrConn(SepTyVars), ""), + ), + printer.StrConn(SepVarsForm), + printer.Str(p.ty.ToString()), + ) } func (p TyPi) Equals(oth any) bool { if op, ok := oth.(TyPi); ok { diff --git a/src/AST/typed-vars.go b/src/AST/typed-vars.go index d3e42e6c..05254f77 100644 --- a/src/AST/typed-vars.go +++ b/src/AST/typed-vars.go @@ -37,7 +37,7 @@ package AST import ( - "fmt" + "github.com/GoelandProver/Goeland/Lib" ) type TypedVar struct { @@ -59,7 +59,7 @@ func (v TypedVar) Equals(oth any) bool { } func (v TypedVar) ToString() string { - return fmt.Sprintf("%s : %s", v.name, v.ty.ToString()) + return printer.StrTyVar(Lib.MkPair(v.name, v.ty)) } func (v TypedVar) GetName() string { @@ -105,29 +105,3 @@ func MakerTypedVar(name string, ty Ty) TypedVar { return vr } } - -// ----------------------------------------------------------------------------- -// Mappable string interface - -func (v TypedVar) GetChildrenForMappedString() []MappableString { - return []MappableString{} -} - -func (v TypedVar) ToMappedString(map_ MapString, type_ bool) string { - if type_ { - return fmt.Sprintf("%s : %s", v.name, v.ty.ToString()) - } - return v.name -} - -func (v TypedVar) ToMappedStringChild(mapping MapString, displayTypes bool) (separator, emptyValue string) { - if displayTypes { - return "", fmt.Sprintf("%s : %s", v.name, v.ty.ToString()) - } else { - return "", v.name - } -} - -func (TypedVar) ToMappedStringSurround(_ MapString, _ bool) string { - return "%s" -} diff --git a/src/Core/form_and_terms.go b/src/Core/form_and_terms.go index fc05cc52..0a9e3234 100644 --- a/src/Core/form_and_terms.go +++ b/src/Core/form_and_terms.go @@ -38,7 +38,6 @@ package Core import ( "github.com/GoelandProver/Goeland/AST" - "github.com/GoelandProver/Goeland/Glob" "github.com/GoelandProver/Goeland/Lib" ) @@ -81,7 +80,7 @@ func (fat FormAndTerms) Equals(fat2 FormAndTerms) bool { } func (fat FormAndTerms) ToString() string { - return fat.GetForm().ToMappedString(AST.DefaultMapString, Glob.GetTypeProof()) + return fat.GetForm().ToString() } func (fat FormAndTerms) SubstituteBy( diff --git a/src/Mods/equality/bse/equality_problem.go b/src/Mods/equality/bse/equality_problem.go index 3ce89bc1..e40d29da 100644 --- a/src/Mods/equality/bse/equality_problem.go +++ b/src/Mods/equality/bse/equality_problem.go @@ -85,7 +85,7 @@ func (ep EqualityProblem) AxiomsToTPTPString() string { } func (ep EqualityProblem) ToTPTPString() string { - return ep.GetS().ToMappedString(AST.DefaultMapString, false) + " = " + ep.GetT().ToMappedString(AST.DefaultMapString, false) + return ep.GetS().ToString() + " = " + ep.GetT().ToString() } /* Apply a substitution on an equality problem */ diff --git a/src/Mods/equality/bse/equality_problem_list.go b/src/Mods/equality/bse/equality_problem_list.go index 4491dff3..fce98743 100644 --- a/src/Mods/equality/bse/equality_problem_list.go +++ b/src/Mods/equality/bse/equality_problem_list.go @@ -150,7 +150,7 @@ func (epml EqualityProblemMultiList) GetMetasToTPTPString() string { if metas.Cardinal() > 0 { result = "? [" for _, meta := range metas.Elements().GetSlice() { - result += meta.ToMappedString(AST.DefaultMapString, false) + ", " + result += meta.ToString() + ", " } result = result[:len(result)-2] + "] : " } diff --git a/src/Mods/equality/eqStruct/term_pair.go b/src/Mods/equality/eqStruct/term_pair.go index 8009e621..0b79f0bb 100644 --- a/src/Mods/equality/eqStruct/term_pair.go +++ b/src/Mods/equality/eqStruct/term_pair.go @@ -94,7 +94,7 @@ func (tp TermPair) ToString() string { return tp.GetT1().ToString() + " ≈ " + tp.GetT2().ToString() } func (tp TermPair) ToTPTPString() string { - return tp.GetT1().ToMappedString(AST.DefaultMapString, false) + " = " + tp.GetT2().ToMappedString(AST.DefaultMapString, false) + return tp.GetT1().ToString() + " = " + tp.GetT2().ToString() } func MakeTermPair(t1, t2 AST.Term) TermPair { return TermPair{t1.Copy(), t2.Copy()} diff --git a/src/Mods/lambdapi/context.go b/src/Mods/lambdapi/context.go index 953fb17f..50102369 100644 --- a/src/Mods/lambdapi/context.go +++ b/src/Mods/lambdapi/context.go @@ -197,7 +197,7 @@ func getContextFromFormula(root AST.Form) []string { result = append(result, getContextFromFormula(nf.GetForm())...) case AST.Pred: if !nf.GetID().Equals(AST.Id_eq) { - result = append(result, mapDefault(fmt.Sprintf("symbol %s;", nf.GetID().ToMappedString(lambdaPiMapConnectors, false)))) + result = append(result, mapDefault(fmt.Sprintf("symbol %s;", nf.GetID().ToString()))) } for _, term := range nf.GetArgs().GetSlice() { result = append(result, clean(result, getContextFromTerm(term))...) @@ -231,9 +231,9 @@ func getIdsFromFormula(root AST.Form) []Glob.Pair[string, string] { case AST.Not: result = getIdsFromFormula(nf.GetForm()) case AST.Pred: - result = append(result, Glob.MakePair(nf.GetID().GetName(), nf.GetID().ToMappedString(lambdaPiMapConnectors, false))) + result = append(result, Glob.MakePair(nf.GetID().GetName(), nf.GetID().ToString())) for _, f := range nf.GetArgs().GetSlice() { - result = append(result, Glob.MakePair(f.GetName(), f.ToMappedString(lambdaPiMapConnectors, false))) + result = append(result, Glob.MakePair(f.GetName(), f.ToString())) } } return result @@ -243,7 +243,7 @@ func getContextFromTerm(trm AST.Term) []string { result := []string{} if fun, isFun := trm.(AST.Fun); isFun { - result = append(result, mapDefault(fmt.Sprintf("symbol %s;", fun.GetID().ToMappedString(lambdaPiMapConnectors, false)))) + result = append(result, mapDefault(fmt.Sprintf("symbol %s;", fun.GetID().ToString()))) for _, term := range fun.GetArgs().GetSlice() { result = append(result, clean(result, getContextFromTerm(term))...) } @@ -272,7 +272,7 @@ func clean(set, add []string) []string { func contextualizeMetas(metaList Lib.List[AST.Meta]) string { result := []string{} for _, meta := range metaList.GetSlice() { - result = append(result, meta.ToMappedString(lambdaPiMapConnectors, false)) + result = append(result, meta.ToString()) } return "symbol " + strings.Join(result, " ") + " : τ (ι);" } diff --git a/src/Mods/lambdapi/formDecorator.go b/src/Mods/lambdapi/formDecorator.go index 267effde..e7847d3a 100644 --- a/src/Mods/lambdapi/formDecorator.go +++ b/src/Mods/lambdapi/formDecorator.go @@ -32,137 +32,137 @@ package lambdapi import ( - "fmt" + _ "fmt" - "github.com/GoelandProver/Goeland/AST" - "github.com/GoelandProver/Goeland/Lib" + _ "github.com/GoelandProver/Goeland/AST" + _ "github.com/GoelandProver/Goeland/Lib" ) -type DecoratedAll struct { - AST.All -} - -func MakeDecoratedAll(all AST.All) DecoratedAll { - if typed, ok := all.Copy().(AST.All); ok { - all = typed - } - decorated := DecoratedAll{all} - decorated.MappedString.MappableString = decorated - return decorated -} - -func (da DecoratedAll) ToMappedStringSurround(mapping AST.MapString, displayTypes bool) string { - return QuantifierToMappedString(mapping[AST.AllQuant], da.GetVarList()) -} - -func QuantifierToMappedString(quant string, varList Lib.List[AST.TypedVar]) string { - if varList.Len() == 0 { - return "%s" - } else { - result := "(" + quant + " (" + toLambdaIntroString(varList.At(0), "") + ", %s))" - result = fmt.Sprintf(result, QuantifierToMappedString(quant, varList.Slice(1, varList.Len()))) - return result - } -} - -type DecoratedEx struct { - AST.Ex -} - -func MakeDecoratedEx(ex AST.Ex) DecoratedEx { - if typed, ok := ex.Copy().(AST.Ex); ok { - ex = typed - } - decorated := DecoratedEx{ex} - decorated.MappedString.MappableString = decorated - return decorated -} - -func (de DecoratedEx) ToMappedStringSurround(mapping AST.MapString, displayTypes bool) string { - return QuantifierToMappedString(mapping[AST.ExQuant], de.GetVarList()) -} - -type DecoratedVar struct { - AST.Var -} - -func MakeDecoratedVar(newVar AST.Var) DecoratedVar { - if typed, ok := newVar.Copy().(AST.Var); ok { - newVar = typed - } - decorated := DecoratedVar{newVar} - decorated.MappedString.MappableString = decorated - return decorated -} - -func (da DecoratedVar) ToMappedStringChild(mapping AST.MapString, displayTypes bool) (separator, emptyValue string) { - emptyValue = getFromContext(da.Var) - return "", emptyValue -} - -type DecoratedPred struct { - AST.Pred -} - -func MakeDecoratedPred(newPred AST.Pred) DecoratedPred { - if typed, ok := newPred.Copy().(AST.Pred); ok { - newPred = typed - } - decorated := DecoratedPred{newPred} - decorated.MappedString.MappableString = decorated - return decorated -} - -func (dp DecoratedPred) ToMappedStringChild(mapping AST.MapString, displayTypes bool) (separator, emptyValue string) { - _, emptyValue = dp.Pred.ToMappedStringChild(mapping, displayTypes) - return " ", emptyValue -} - -type DecoratedFun struct { - AST.Fun -} - -func MakeDecoratedFun(newFun AST.Fun) DecoratedFun { - if typed, ok := newFun.Copy().(AST.Fun); ok { - newFun = typed - } - decorated := DecoratedFun{newFun} - decorated.MappedString.MappableString = decorated - return decorated -} - -func (df DecoratedFun) ToMappedStringChild(mapping AST.MapString, displayTypes bool) (separator, emptyValue string) { - return " ", mapping[AST.PredEmpty] -} - -func (df DecoratedFun) ToMappedStringSurround(mapping AST.MapString, displayTypes bool) string { - result := df.Fun.ToMappedStringSurround(mapping, displayTypes) - - possible, exists := context.GetExists(df.Fun) - if exists { - if result[:6] == "skolem" { - result = string(possible) + "%s" - } else { - result = df.Fun.ToMappedStringSurroundWithId(string(possible), mapping, displayTypes) - } - } - - return result -} - -func decorateForm(form AST.MappableString) AST.MappableString { - switch typed := form.(type) { - case AST.All: - return MakeDecoratedAll(typed) - case AST.Ex: - return MakeDecoratedEx(typed) - case AST.Var: - return MakeDecoratedVar(typed) - case AST.Pred: - return MakeDecoratedPred(typed) - case AST.Fun: - return MakeDecoratedFun(typed) - default: - return typed - } -} +// type DecoratedAll struct { +// AST.All +// } + +// func MakeDecoratedAll(all AST.All) DecoratedAll { +// if typed, ok := all.Copy().(AST.All); ok { +// all = typed +// } +// decorated := DecoratedAll{all} +// decorated.MappedString.MappableString = decorated +// return decorated +// } + +// func (da DecoratedAll) ToMappedStringSurround(mapping AST.MapString, displayTypes bool) string { +// return QuantifierToMappedString(mapping[AST.AllQuant], da.GetVarList()) +// } + +// func QuantifierToMappedString(quant string, varList Lib.List[AST.TypedVar]) string { +// if varList.Len() == 0 { +// return "%s" +// } else { +// result := "(" + quant + " (" + toLambdaIntroString(varList.At(0), "") + ", %s))" +// result = fmt.Sprintf(result, QuantifierToMappedString(quant, varList.Slice(1, varList.Len()))) +// return result +// } +// } + +// type DecoratedEx struct { +// AST.Ex +// } + +// func MakeDecoratedEx(ex AST.Ex) DecoratedEx { +// if typed, ok := ex.Copy().(AST.Ex); ok { +// ex = typed +// } +// decorated := DecoratedEx{ex} +// decorated.MappedString.MappableString = decorated +// return decorated +// } + +// func (de DecoratedEx) ToMappedStringSurround(mapping AST.MapString, displayTypes bool) string { +// return QuantifierToMappedString(mapping[AST.ExQuant], de.GetVarList()) +// } + +// type DecoratedVar struct { +// AST.Var +// } + +// func MakeDecoratedVar(newVar AST.Var) DecoratedVar { +// if typed, ok := newVar.Copy().(AST.Var); ok { +// newVar = typed +// } +// decorated := DecoratedVar{newVar} +// decorated.MappedString.MappableString = decorated +// return decorated +// } + +// func (da DecoratedVar) ToMappedStringChild(mapping AST.MapString, displayTypes bool) (separator, emptyValue string) { +// emptyValue = getFromContext(da.Var) +// return "", emptyValue +// } + +// type DecoratedPred struct { +// AST.Pred +// } + +// func MakeDecoratedPred(newPred AST.Pred) DecoratedPred { +// if typed, ok := newPred.Copy().(AST.Pred); ok { +// newPred = typed +// } +// decorated := DecoratedPred{newPred} +// decorated.MappedString.MappableString = decorated +// return decorated +// } + +// func (dp DecoratedPred) ToMappedStringChild(mapping AST.MapString, displayTypes bool) (separator, emptyValue string) { +// _, emptyValue = dp.Pred.ToMappedStringChild(mapping, displayTypes) +// return " ", emptyValue +// } + +// type DecoratedFun struct { +// AST.Fun +// } + +// func MakeDecoratedFun(newFun AST.Fun) DecoratedFun { +// if typed, ok := newFun.Copy().(AST.Fun); ok { +// newFun = typed +// } +// decorated := DecoratedFun{newFun} +// decorated.MappedString.MappableString = decorated +// return decorated +// } + +// func (df DecoratedFun) ToMappedStringChild(mapping AST.MapString, displayTypes bool) (separator, emptyValue string) { +// return " ", mapping[AST.PredEmpty] +// } + +// func (df DecoratedFun) ToMappedStringSurround(mapping AST.MapString, displayTypes bool) string { +// result := df.Fun.ToMappedStringSurround(mapping, displayTypes) + +// possible, exists := context.GetExists(df.Fun) +// if exists { +// if result[:6] == "skolem" { +// result = string(possible) + "%s" +// } else { +// result = df.Fun.ToMappedStringSurroundWithId(string(possible), mapping, displayTypes) +// } +// } + +// return result +// } + +// func decorateForm(form AST.MappableString) AST.MappableString { +// switch typed := form.(type) { +// case AST.All: +// return MakeDecoratedAll(typed) +// case AST.Ex: +// return MakeDecoratedEx(typed) +// case AST.Var: +// return MakeDecoratedVar(typed) +// case AST.Pred: +// return MakeDecoratedPred(typed) +// case AST.Fun: +// return MakeDecoratedFun(typed) +// default: +// return typed +// } +// } diff --git a/src/Mods/lambdapi/output.go b/src/Mods/lambdapi/output.go index cd5de4d0..a40a73e8 100644 --- a/src/Mods/lambdapi/output.go +++ b/src/Mods/lambdapi/output.go @@ -43,24 +43,24 @@ import ( var contextEnabled bool = false -var lambdaPiMapConnectors = map[AST.FormulaType]string{ - AST.AndConn: "∧", - AST.OrConn: "∨", - AST.ImpConn: "⇒", - AST.EquConn: "⇔", - AST.NotConn: "¬", - AST.TopType: "⊤", - AST.BotType: "⊥", - AST.AllQuant: "∀α", - AST.ExQuant: "∃α", - AST.AllTypeQuant: "∀", - AST.QuantVarOpen: "(", - AST.QuantVarClose: ")", - AST.QuantVarSep: " ", - AST.PredEmpty: "", - AST.PredTypeVarSep: ") (", - AST.TypeVarType: "Type", -} +// var lambdaPiMapConnectors = map[AST.FormulaType]string{ +// AST.AndConn: "∧", +// AST.OrConn: "∨", +// AST.ImpConn: "⇒", +// AST.EquConn: "⇔", +// AST.NotConn: "¬", +// AST.TopType: "⊤", +// AST.BotType: "⊥", +// AST.AllQuant: "∀α", +// AST.ExQuant: "∃α", +// AST.AllTypeQuant: "∀", +// AST.QuantVarOpen: "(", +// AST.QuantVarClose: ")", +// AST.QuantVarSep: " ", +// AST.PredEmpty: "", +// AST.PredTypeVarSep: ") (", +// AST.TypeVarType: "Type", +// } var LambdapiOutputProofStruct = &Search.OutputProofStruct{ProofOutput: MakeLambdapiOutput, Name: "Lambdapi", Extension: ".lp"} @@ -79,6 +79,8 @@ func MakeLambdapiOutput(prf []Search.ProofStruct, meta Lib.List[AST.Meta]) strin return "" } + // FIXME: set the AST printer to (to be defined soon) LPPrinter + // Transform tableaux's proof in GS3 proof return MakeLambdaPiProof(gs3.MakeGS3Proof(prf), meta) } diff --git a/src/Mods/lambdapi/proof.go b/src/Mods/lambdapi/proof.go index bdeeff51..9ff8cb05 100644 --- a/src/Mods/lambdapi/proof.go +++ b/src/Mods/lambdapi/proof.go @@ -49,7 +49,7 @@ func makeLambdaPiProofFromGS3(proof *gs3.GS3Sequent) string { formula := proof.GetTargetForm() - formulaStr := toCorrectString(formula) + formulaStr := formula.ToString() resultingString += fmt.Sprintf("λ (%s : ϵ %s),\n", addToContext(formula), formulaStr) proofStr := makeProofStep(proof) resultingString += proofStr @@ -103,7 +103,7 @@ func makeProofStep(proof *gs3.GS3Sequent) string { Glob.PrintError("LP", "Trying to do a weakening rule but it's not implemented yet") } - return "//" + toCorrectString(proof.GetTargetForm()) + "\n" + resultingString + return "//" + proof.GetTargetForm().ToString() + "\n" + resultingString } func closureAxiom(proof *gs3.GS3Sequent) string { @@ -113,7 +113,7 @@ func closureAxiom(proof *gs3.GS3Sequent) string { switch target.(type) { case AST.Pred: - result = fmt.Sprintf("GS3axiom (%s) (%s) (%s)\n", toCorrectString(target), getFromContext(target), getFromContext(notTarget)) + result = fmt.Sprintf("GS3axiom (%s) (%s) (%s)\n", target.ToString(), getFromContext(target), getFromContext(notTarget)) case AST.Top: result = fmt.Sprintf("GS3ntop (%s)\n", getFromContext(notTarget)) case AST.Bot: @@ -134,7 +134,7 @@ func allRules(rule string, target AST.Form, composingForms Lib.List[AST.Form], n result := rule + "\n" for _, composingForm := range composingForms.GetSlice() { - result += "(" + toCorrectString(composingForm) + ")\n" + result += "(" + composingForm.ToString() + ")\n" } result += getRecursionUnivStr(nexts, children) @@ -156,18 +156,19 @@ func allRulesQuantUniv( quant := "" typeStr := "" - switch target.(type) { - case AST.All: - quant = lambdaPiMapConnectors[AST.AllQuant] - case AST.Not: - quant = lambdaPiMapConnectors[AST.ExQuant] - } + // FIXME get printer + // switch target.(type) { + // case AST.Ex: + // quant = AST.ConnAll + // case AST.Not: + // quant = AST.ConnEx + // } typeStr = mapDefault(typeStr) result := rule + "\n" result += "(" + typeStr + ")\n" - result += "(%s, " + toCorrectString(composingForms.At(0)) + ")\n" + result += "(%s, " + composingForms.At(0).ToString() + ")\n" varStrs := []string{} for _, singleVar := range vars.GetSlice() { @@ -175,7 +176,7 @@ func allRulesQuantUniv( } result = fmt.Sprintf(result, strings.Join(varStrs, ", "+quant+" ")) - result += "(" + toCorrectString(termGen) + ")\n" + result += "(" + termGen.ToString() + ")\n" result += getRecursionUnivStr(nexts, children) @@ -188,7 +189,7 @@ func getRecursionUnivStr(nexts []*gs3.GS3Sequent, children []Lib.List[AST.Form]) for i, next := range nexts { result += "(\n" for _, childForm := range children[i].GetSlice() { - result += toLambdaString(childForm, toCorrectString(childForm)) + ",\n" + result += toLambdaString(childForm, childForm.ToString()) + ",\n" } proofStr := makeProofStep(next) result += proofStr @@ -208,18 +209,19 @@ func allRulesQuantExist( ) string { quant := "" typeStr := "" - switch target.(type) { - case AST.Ex: - quant = lambdaPiMapConnectors[AST.ExQuant] - case AST.Not: - quant = lambdaPiMapConnectors[AST.AllQuant] - } + // FIXME get printer + // switch target.(type) { + // case AST.Ex: + // quant = AST.ConnAll + // case AST.Not: + // quant = AST.ConnEx + // } typeStr = mapDefault(typeStr) result := rule + "\n" result += "(" + typeStr + ")\n" - result += "(%s, " + toCorrectString(composingForms.At(0)) + ")\n" + result += "(%s, " + composingForms.At(0).ToString() + ")\n" varStrs := []string{} for _, singleVar := range vars.GetSlice() { @@ -243,7 +245,7 @@ func getRecursionExistStr(nexts []*gs3.GS3Sequent, children []Lib.List[AST.Form] } result += toLambdaIntroString(termGen, typesStr) + ",\n" for _, childForm := range children[i].GetSlice() { - result += toLambdaString(childForm, toCorrectString(childForm)) + ",\n" + result += toLambdaString(childForm, childForm.ToString()) + ",\n" } proofStr := makeProofStep(next) result += proofStr @@ -371,7 +373,7 @@ func makeTheorem(axioms Lib.List[AST.Form], conjecture AST.Form) string { axioms = Lib.ListCpy(axioms) axioms.Append(AST.MakerNot(conjecture)) formattedProblem := makeImpChain(axioms) - return "symbol goeland_" + problemName + " : \nϵ " + toCorrectString(formattedProblem) + " → ϵ ⊥ ≔ \n" + return "symbol goeland_" + problemName + " : \nϵ " + formattedProblem.ToString() + " → ϵ ⊥ ≔ \n" } // If [F1, F2, F3] is a formlist, then this function returns F1 -> (F2 -> F3). diff --git a/src/Mods/lambdapi/utils.go b/src/Mods/lambdapi/utils.go index 803f16d5..5e6421c8 100644 --- a/src/Mods/lambdapi/utils.go +++ b/src/Mods/lambdapi/utils.go @@ -33,9 +33,7 @@ package lambdapi import ( "fmt" - "strings" - "github.com/GoelandProver/Goeland/AST" "github.com/GoelandProver/Goeland/Glob" ) @@ -46,9 +44,9 @@ func getIncreasedCounter() int { return varCounter - 1 } -var context Glob.Map[AST.MappableString, Glob.String] = *Glob.NewMap[AST.MappableString, Glob.String]() +var context Glob.Map[Glob.Basic, Glob.String] = *Glob.NewMap[Glob.Basic, Glob.String]() -func addToContext(key AST.MappableString) string { +func addToContext(key Glob.Basic) string { if _, ok := context.GetExists(key); !ok { context.Set(key, Glob.String(fmt.Sprintf("v%v", getIncreasedCounter()))) } @@ -56,40 +54,40 @@ func addToContext(key AST.MappableString) string { return string(context.Get(key)) } -func getFromContext(key AST.MappableString) string { +func getFromContext(key Glob.Basic) string { return string(context.Get(key)) } -func toLambdaString(element AST.MappableString, str string) string { +func toLambdaString(element Glob.Basic, str string) string { return fmt.Sprintf("λ (%s : ϵ (%s))", addToContext(element), str) } -func toLambdaIntroString(element AST.MappableString, typeStr string) string { +func toLambdaIntroString(element Glob.Basic, typeStr string) string { return fmt.Sprintf("λ (%s : τ (%s))", addToContext(element), mapDefault(typeStr)) } -func toCorrectString(element AST.MappableString) string { - isNotSkolem := len(element.ToString()) <= 5 || element.ToString()[:6] != "skolem" - element = decorateForm(element) - surround := element.ToMappedStringSurround(lambdaPiMapConnectors, false) - separator, emptyValue := element.ToMappedStringChild(lambdaPiMapConnectors, false) - children := "" - if isNotSkolem { - children = ListToMappedString(element.GetChildrenForMappedString(), separator, emptyValue) - } - return fmt.Sprintf(surround, children) -} +// func toCorrectString(element AST.MappableString) string { +// isNotSkolem := len(element.ToString()) <= 5 || element.ToString()[:6] != "skolem" +// element = decorateForm(element) +// surround := element.ToMappedStringSurround(lambdaPiMapConnectors, false) +// separator, emptyValue := element.ToMappedStringChild(lambdaPiMapConnectors, false) +// children := "" +// if isNotSkolem { +// children = ListToMappedString(element.GetChildrenForMappedString(), separator, emptyValue) +// } +// return fmt.Sprintf(surround, children) +// } -func ListToMappedString[T AST.MappableString](children []T, separator, emptyValue string) string { - strArr := []string{} +// func ListToMappedString[T AST.MappableString](children []T, separator, emptyValue string) string { +// strArr := []string{} - for _, element := range children { - strArr = append(strArr, toCorrectString(element)) - } +// for _, element := range children { +// strArr = append(strArr, toCorrectString(element)) +// } - if len(strArr) == 0 && emptyValue != "" { - strArr = append(strArr, emptyValue) - } +// if len(strArr) == 0 && emptyValue != "" { +// strArr = append(strArr, emptyValue) +// } - return strings.Join(strArr, separator) -} +// return strings.Join(strArr, separator) +// } diff --git a/src/Mods/rocq/context.go b/src/Mods/rocq/context.go index 3ec82ed9..e389b712 100644 --- a/src/Mods/rocq/context.go +++ b/src/Mods/rocq/context.go @@ -117,8 +117,7 @@ func getContextFromFormula(root AST.Form) []string { result = clean(result, getContextFromFormula(nf.GetForm())) case AST.Pred: if !nf.GetID().Equals(AST.Id_eq) { - result = append(result, mapDefault( - fmt.Sprintf("Parameter %s.", nf.GetID().ToMappedString(rocqMapConnectors(), false)))) + result = append(result, fmt.Sprintf("Parameter %s.", nf.GetID().ToString())) } for _, term := range nf.GetArgs().GetSlice() { result = append(result, clean(result, getContextFromTerm(term))...) @@ -131,8 +130,7 @@ func getContextFromTerm(trm AST.Term) []string { result := []string{} if fun, isFun := trm.(AST.Fun); isFun { result = append(result, - mapDefault(fmt.Sprintf( - "Parameter %s.", fun.GetID().ToMappedString(rocqMapConnectors(), false)))) + fmt.Sprintf("Parameter %s.", fun.GetID().ToString())) for _, term := range fun.GetArgs().GetSlice() { result = append(result, clean(result, getContextFromTerm(term))...) } @@ -161,7 +159,7 @@ func clean(set, add []string) []string { func contextualizeMetas(metaList Lib.List[AST.Meta]) string { result := []string{} for _, meta := range metaList.GetSlice() { - result = append(result, meta.ToMappedString(rocqMapConnectors(), false)) + result = append(result, meta.ToString()) } return "Parameters " + strings.Join(result, " ") + " : goeland_U." } diff --git a/src/Mods/rocq/output.go b/src/Mods/rocq/output.go index 1efaaff6..f48566f7 100644 --- a/src/Mods/rocq/output.go +++ b/src/Mods/rocq/output.go @@ -37,8 +37,6 @@ package rocq import ( - "strings" - "github.com/GoelandProver/Goeland/AST" "github.com/GoelandProver/Goeland/Glob" "github.com/GoelandProver/Goeland/Lib" @@ -65,6 +63,8 @@ func MakeRocqOutput(prf []Search.ProofStruct, meta Lib.List[AST.Meta]) string { return "" } + // FIXME: set the AST printer to (to be defined soon) CoqPrinter + // Transform tableaux's proof in GS3 proof return MakeRocqProof(gs3.MakeGS3Proof(prf), meta) } @@ -75,31 +75,6 @@ var MakeRocqProof = func(proof *gs3.GS3Sequent, meta Lib.List[AST.Meta]) string return contextString + "\n" + proofString } -// Replace defined symbols by Rocq's defined symbols. -func mapDefault(str string) string { - return strings.ReplaceAll(strings.ReplaceAll(str, "$i", "goeland_U"), "$o", "Prop") -} -func rocqMapConnectors() map[AST.FormulaType]string { - return map[AST.FormulaType]string{ - AST.AndConn: "/\\", - AST.OrConn: "\\/", - AST.ImpConn: "->", - AST.EquConn: "<->", - AST.NotConn: "~", - AST.TopType: "True", - AST.BotType: "False", - AST.AllQuant: "forall", - AST.ExQuant: "exists", - AST.AllTypeQuant: "forall", - AST.QuantVarOpen: "(", - AST.QuantVarClose: ")", - AST.QuantVarSep: ",", - AST.PredEmpty: "", - AST.PredTypeVarSep: ",", - AST.TypeVarType: "Type", - } -} - // Context flag utility function func GetContextEnabled() bool { return contextEnabled diff --git a/src/Mods/rocq/proof.go b/src/Mods/rocq/proof.go index 0d1d1bb0..507feb59 100644 --- a/src/Mods/rocq/proof.go +++ b/src/Mods/rocq/proof.go @@ -252,8 +252,7 @@ func makeTheorem(axioms Lib.List[AST.Form], conjecture AST.Form) string { axiomsWithConj := Lib.ListCpy(axioms) axiomsWithConj.Append(AST.MakerNot(AST.MakerNot(conjecture))) formattedProblem := makeImpChain(axiomsWithConj) - return "Theorem goeland_proof_of_" + problemName + " : " + - mapDefault(formattedProblem.ToMappedString(rocqMapConnectors(), Glob.GetTypeProof())) + ".\n" + return "Theorem goeland_proof_of_" + problemName + " : " + formattedProblem.ToString() + ".\n" } // If [F1, F2, F3] is a formlist, then this function returns F1 -> (F2 -> F3). @@ -322,7 +321,7 @@ func getRealConstantName(constantsCreated []AST.Term, term AST.Term) string { if fun, isFun := term.(AST.Fun); isFun { res := "" if isGroundTerm(fun.GetID()) { - res = fun.GetID().ToMappedString(rocqMapConnectors(), Glob.GetTypeProof()) + res = fun.GetID().ToString() subterms := make([]string, 0) for _, t := range fun.GetArgs().GetSlice() { subterms = append(subterms, getRealConstantName(constantsCreated, t)) @@ -346,7 +345,7 @@ func findInConstants(constantsCreated []AST.Term, term AST.Term) string { return getConstantName(term.(AST.Fun).GetID()) } if isGroundTerm(term) { - return "(" + term.ToMappedString(rocqMapConnectors(), Glob.GetTypeProof()) + ")" + return "(" + term.ToString() + ")" } return "goeland_I" } diff --git a/src/Mods/tptp/output.go b/src/Mods/tptp/output.go index ee48f084..f27acd44 100644 --- a/src/Mods/tptp/output.go +++ b/src/Mods/tptp/output.go @@ -37,8 +37,6 @@ package tptp import ( - "strings" - "github.com/GoelandProver/Goeland/AST" "github.com/GoelandProver/Goeland/Glob" "github.com/GoelandProver/Goeland/Lib" @@ -61,7 +59,10 @@ func MakeTptpOutput(prf []Search.ProofStruct, meta Lib.List[AST.Meta]) string { return "" } + // FIXME: set AST's printer to be the one of TPTP + if Glob.IsSCTPTPOutput() { + // FIXME: the one of TSTP here prefix_const = "Sko_" } @@ -70,33 +71,6 @@ func MakeTptpOutput(prf []Search.ProofStruct, meta Lib.List[AST.Meta]) string { } var MakeTptpProof = func(proof *gs3.GS3Sequent, meta Lib.List[AST.Meta]) string { - old := AST.ChangeVarSeparator(", ") proofString := makeTptpProofFromGS3(proof) - AST.ChangeVarSeparator(old) return proofString } - -// Replace defined symbols by TSTP's defined symbols. -func mapDefault(str string) string { - return strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(str, " : $i", ""), " : $o", ""), " : , ", " : ") -} -func tptpMapConnectors() map[AST.FormulaType]string { - return map[AST.FormulaType]string{ - AST.AndConn: "&", - AST.OrConn: "|", - AST.ImpConn: "=>", - AST.EquConn: "<=>", - AST.NotConn: "~", - AST.TopType: "$true", - AST.BotType: "$false", - AST.AllQuant: "!", - AST.ExQuant: "?", - AST.AllTypeQuant: "!", - AST.QuantVarOpen: "[", - AST.QuantVarClose: "] : ", - AST.QuantVarSep: ",", - AST.PredEmpty: "", - AST.PredTypeVarSep: ",", - AST.TypeVarType: "Type", - } -} diff --git a/src/Mods/tptp/proof.go b/src/Mods/tptp/proof.go index 2bd79ca4..6d28f59c 100644 --- a/src/Mods/tptp/proof.go +++ b/src/Mods/tptp/proof.go @@ -141,7 +141,7 @@ func makeStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], new_current_ if isPredEqual(proof.GetTargetForm()) { resultingString = fmt.Sprintf("fof("+prefix_step+"%d, plain, [%s] --> [], inference(%s, [status(thm)], [%s])).", proof.GetId(), - mapDefault(AST.ListToMappedString(hypotheses.GetSlice(), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), + Lib.ListToString(hypotheses, ", ", ""), "congruence", "") } else { @@ -149,7 +149,7 @@ func makeStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], new_current_ resultingString = fmt.Sprintf("fof("+prefix_step+"%d, plain, [%s] --> [], inference(%s, [status(thm), %d], [%s])).", proof.GetId(), - mapDefault(AST.ListToMappedString(hypotheses.GetSlice(), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), + Lib.ListToString(hypotheses, ", ", ""), "leftHyp", targetPos, "") @@ -192,7 +192,7 @@ func makeStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], new_current_ // Weakening rule case gs3.W: if proof.TermGenerated() != nil { - resultingString = fmt.Sprintf("leftWeaken %s", findInConstants(proof.TermGenerated()).ToMappedString(tptpMapConnectors(), Glob.GetTypeProof())) + resultingString = fmt.Sprintf("leftWeaken %s", findInConstants(proof.TermGenerated()).ToString()) } else { resultingString, childrenHypotheses, next_child_weakened_id = weakenStep(proof, hypotheses, target, "leftWeaken") } @@ -216,7 +216,7 @@ func alphaStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], target int, resultingString := fmt.Sprintf("fof(%s%d, plain, [%s] --> [], inference(%s, [status(thm), %d], [%s])).", prefix_step, proof.GetId(), - mapDefault(AST.ListToMappedString(hypotheses.GetSlice(), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), + Lib.ListToString(hypotheses, ", ", ""), format, target, Glob.IntListToString(children_id, prefix_step)) @@ -242,7 +242,7 @@ func betaStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], target int, resultingString := fmt.Sprintf("fof(%s%d, plain, [%s] --> [], inference(%s, [status(thm), %d], [%s])).", prefix_step, proof.GetId(), - mapDefault(AST.ListToMappedString(hypotheses.GetSlice(), ", ", "", tptpMapConnectors(), false)), + Lib.ListToString(hypotheses, ", ", ""), format, target, Glob.IntListToString(children_id, prefix_step)) @@ -265,10 +265,10 @@ func deltaStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], target int, resultingString := fmt.Sprintf("fof(%s%d, plain, [%s] --> [], inference(%s, [status(thm), %d, '%s'], [%s])).", prefix_step, proof.GetId(), - mapDefault(AST.ListToMappedString(hypotheses.GetSlice(), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), + Lib.ListToString(hypotheses, ", ", ""), format, target, - new_term.ToMappedString(tptpMapConnectors(), Glob.GetTypeProof()), + new_term.ToString(), Glob.IntListToString(children_id, prefix_step)) newHypotheses := Lib.ListCpy(hypotheses) @@ -290,10 +290,10 @@ func gammaStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], target int, resultingString := fmt.Sprintf("fof(%s%d, plain, [%s] --> [], inference(%s, [status(thm), %d, $fot(%s)], [%s])).", prefix_step, proof.GetId(), - mapDefault(AST.ListToMappedString(hypotheses.GetSlice(), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), + Lib.ListToString(hypotheses, ", ", ""), format, target, - findInConstants(proof.TermGenerated()).ToMappedString(tptpMapConnectors(), Glob.GetTypeProof()), + findInConstants(proof.TermGenerated()).ToString(), Glob.IntListToString(children_id, prefix_step)) newHypotheses := Lib.ListCpy(hypotheses) @@ -312,7 +312,7 @@ func weakenStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], target int resultingString := fmt.Sprintf("fof(%s%d, plain, [%s] --> [], inference(%s, [status(thm), %d], [%s%d])).", prefix_step, proof.GetId(), - mapDefault(AST.ListToMappedString(hypotheses.GetSlice(), ", ", "", tptpMapConnectors(), false)), + Lib.ListToString(hypotheses, ", ", ""), format, target, prefix_step, @@ -355,7 +355,7 @@ func EquStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], target int) ( resultingString = fmt.Sprintf("fof(%s%d, plain, [%s] --> [], inference(%s, [status(thm), %d], [%s])).", prefix_step, proof.GetId(), - mapDefault(AST.ListToMappedString(hypotheses.GetSlice(), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), + Lib.ListToString(hypotheses, ", ", ""), "leftIff", target, s1_id) + resultingString @@ -367,7 +367,7 @@ func EquStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], target int) ( newHyp = Lib.ListAdd(newHyp, []AST.Form{A_imp_B, B_imp_A}...) resultingString = fmt.Sprintf("fof(%s, plain, [%s] --> [], inference(%s, [status(thm), %d], [%s, %s])).\n\n", s1_id, - mapDefault(AST.ListToMappedString(newHyp.GetSlice(), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), + Lib.ListToString(newHyp, ", ", ""), "leftImp2", get(A_imp_B, newHyp), s2_id, @@ -379,7 +379,7 @@ func EquStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], target int) ( newHypS2 = Lib.ListAdd(newHypS2, notA.Copy()) resultingString = fmt.Sprintf("fof(%s, plain, [%s] --> [], inference(%s, [status(thm), %d], [%s%d, %s])).\n\n", s2_id, - mapDefault(AST.ListToMappedString(newHypS2.GetSlice(), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), + Lib.ListToString(newHypS2, ", ", ""), "leftImp2", get(B_imp_A, newHypS2), prefix_step, @@ -393,7 +393,7 @@ func EquStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], target int) ( targetPosS2 := findIndexPos(A, newHypS2Closure, get(A, newHypS2Closure)) resultingString = fmt.Sprintf("fof(%s, plain, [%s] --> [], inference(%s, [status(thm), %d], [%s])).\n\n", s2_closure_id, - mapDefault(AST.ListToMappedString(newHypS2Closure.GetSlice(), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), + Lib.ListToString(newHypS2Closure, ", ", ""), "leftHyp", targetPosS2, "") + resultingString @@ -404,7 +404,7 @@ func EquStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], target int) ( newHypS3 = Lib.ListAdd(newHypS3, B) resultingString = fmt.Sprintf("fof(%s, plain, [%s] --> [], inference(%s, [status(thm), %d], [%s, %s%d])).\n\n", s3_id, - mapDefault(AST.ListToMappedString(newHypS3.GetSlice(), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), + Lib.ListToString(newHypS3, ", ", ""), "leftImp2", get(B_imp_A, newHypS3), s3_closure_id, @@ -418,7 +418,7 @@ func EquStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], target int) ( targetPosS3 := findIndexPos(B, newHypS3Closure, get(B, newHypS3Closure)) resultingString = fmt.Sprintf("fof(%s, plain, [%s] --> [], inference(%s, [status(thm), %d], [%s])).\n\n", s3_closure_id, - mapDefault(AST.ListToMappedString(newHypS3Closure.GetSlice(), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), + Lib.ListToString(newHypS3Closure, ", ", ""), "leftHyp", targetPosS3, "") + resultingString @@ -453,7 +453,7 @@ func NotEquStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], target int resultingString = fmt.Sprintf("fof(%s%d, plain, [%s] --> [], inference(%s, [status(thm), %d], [%s, %s])).", prefix_step, proof.GetId(), - mapDefault(AST.ListToMappedString(hypotheses.GetSlice(), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), + Lib.ListToString(hypotheses, ", ", ""), "leftNotIff", target, s1_id, @@ -464,7 +464,7 @@ func NotEquStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], target int newHyp1 = Lib.ListAdd(newHyp1, not_A_imp_B.Copy()) resultingString = fmt.Sprintf("fof(%s, plain, [%s] --> [], inference(%s, [status(thm), %d], [%s%d])).\n\n", s1_id, - mapDefault(AST.ListToMappedString(newHyp1.GetSlice(), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), + Lib.ListToString(newHyp1, ", ", ""), "leftNotImplies", get(not_A_imp_B, newHyp1), prefix_step, @@ -476,7 +476,7 @@ func NotEquStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], target int newHyp2 = Lib.ListAdd(newHyp2, not_B_imp_A.Copy()) resultingString = fmt.Sprintf("fof(%s, plain, [%s] --> [], inference(%s, [status(thm), %d], [%s%d])).\n\n", s2_id, - mapDefault(AST.ListToMappedString(newHyp2.GetSlice(), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), + Lib.ListToString(newHyp2, ", ", ""), "leftNotImplies", get(not_B_imp_A, newHyp2), prefix_step, @@ -508,10 +508,11 @@ func makeTheorem(axioms Lib.List[AST.Form], conjecture AST.Form) string { problemName := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(Glob.GetProblemName(), ".", "_"), "=", "_"), "+", "_") for _, ax := range axioms.GetSlice() { - resulting_string = resulting_string + "fof(" + fmt.Sprintf("ax%d", ax.GetIndex()) + ", axiom, " + mapDefault(ax.ToMappedString(tptpMapConnectors(), Glob.GetTypeProof())) + ").\n\n" + resulting_string = resulting_string + "fof(" + fmt.Sprintf("ax%d", ax.GetIndex()) + ", axiom, " + + ax.ToString() + ").\n\n" } - resulting_string = resulting_string + "fof(c_" + problemName + ", conjecture, " + mapDefault(conjecture.ToMappedString(tptpMapConnectors(), Glob.GetTypeProof())) + ").\n\n" + resulting_string = resulting_string + "fof(c_" + problemName + ", conjecture, " + conjecture.ToString() + ").\n\n" return resulting_string } @@ -524,9 +525,9 @@ func performFirstStep(axioms Lib.List[AST.Form], conjecture AST.Form, hypothesis // Cut initial formula, |- ~c, c step cutFormNot := fmt.Sprintf("fof("+prefix_step+"%d, plain, [%s] --> [%s, %s], inference(%s, [status(thm), %d], [%s])).", cutFormNotId, - mapDefault(AST.ListToMappedString(axioms.GetSlice(), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), - mapDefault(conjecture.ToMappedString(tptpMapConnectors(), false)), - mapDefault(AST.MakerNot(conjecture).ToMappedString(tptpMapConnectors(), Glob.GetTypeProof())), + Lib.ListToString(axioms, ", ", ""), + conjecture.ToString(), + AST.MakerNot(conjecture).ToString(), "rightNot", 1, prefix_step+strconv.Itoa(cutFormHypId)) @@ -534,8 +535,8 @@ func performFirstStep(axioms Lib.List[AST.Form], conjecture AST.Form, hypothesis // Cut initial formula, c |- c step cutFormHyp := fmt.Sprintf("fof("+prefix_step+"%d, plain, [%s] --> [%s], inference(%s, [status(thm), %d], [%s])).", cutFormHypId, - mapDefault(AST.ListToMappedString(append(axioms.GetSlice(), conjecture), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), - mapDefault(conjecture.ToMappedString(tptpMapConnectors(), Glob.GetTypeProof())), + Lib.ListToString(Lib.MkListV(append(axioms.GetSlice(), conjecture)...), ", ", ""), + conjecture.ToString(), "hyp", axioms.Len(), // 0, @@ -545,8 +546,8 @@ func performFirstStep(axioms Lib.List[AST.Form], conjecture AST.Form, hypothesis // indexHyp, _ := hypothesis.GetIndexOf(AST.MakerNot(conjecture)) startForm := fmt.Sprintf("fof(f%d, plain, [%s] --> [%s], inference(cut, [status(thm), %d], [%s%d, %s%d])).\n\n", nextId, - mapDefault(AST.ListToMappedString(axioms.GetSlice(), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), - mapDefault(conjecture.ToMappedString(tptpMapConnectors(), Glob.GetTypeProof())), + Lib.ListToString(axioms, ", ", ""), + conjecture.ToString(), 1, //indexHyp, prefix_step, @@ -575,8 +576,8 @@ func performCutAxiomStep(axioms Lib.List[AST.Form], conjecture AST.Form) string prefix_axiom_cut, i, // AST.ListToMappedString(axioms.GetElements(0, i), ", ", "", tptpMapConnectors(), GetTypeProof()), - mapDefault(AST.ListToMappedString(axioms.Get(0, i), ", ", "", tptpMapConnectors(), Glob.GetTypeProof())), - mapDefault(conjecture.ToMappedString(tptpMapConnectors(), Glob.GetTypeProof())), + Lib.ListToString(Lib.MkListV(axioms.Get(0, i)...), ", ", ""), + conjecture.ToString(), 0, //i, "ax", diff --git a/src/Search/proof.go b/src/Search/proof.go index 6d292ee7..e7bcecad 100644 --- a/src/Search/proof.go +++ b/src/Search/proof.go @@ -286,7 +286,7 @@ func IntFormAndTermsListToIntIntStringPairList(fl []IntFormAndTermsList) []IntIn func ProofStructListToJsonProofStructList(ps []ProofStruct) []JsonProofStruct { res := []JsonProofStruct{} for _, p := range ps { - new_json_element := JsonProofStruct{p.GetFormula().GetForm().ToMappedString(AST.DefaultMapString, Glob.GetTypeProof()), p.GetIdDMT(), p.Node_id, p.Rule, p.Rule_name, IntFormAndTermsListToIntIntStringPairList(p.Result_formulas), proofStructChildrenToJsonProofStructChildren(p.Children)} + new_json_element := JsonProofStruct{p.GetFormula().GetForm().ToString(), p.GetIdDMT(), p.Node_id, p.Rule, p.Rule_name, IntFormAndTermsListToIntIntStringPairList(p.Result_formulas), proofStructChildrenToJsonProofStructChildren(p.Children)} res = append(res, new_json_element) } return res diff --git a/src/Unif/parsing.go b/src/Unif/parsing.go index 69dd16be..c8a80fc6 100644 --- a/src/Unif/parsing.go +++ b/src/Unif/parsing.go @@ -38,23 +38,11 @@ import ( ) type TermForm struct { - *AST.MappedString index int t AST.Term } -func (t TermForm) ToMappedStringSurround(mapping AST.MapString, displayTypes bool) string { - return "%s" -} - -func (t TermForm) ToMappedStringChild(mapping AST.MapString, displayTypes bool) (separator, emptyValue string) { - return "", t.t.ToMappedString(mapping, displayTypes) -} - -func (t TermForm) GetChildrenForMappedString() []AST.MappableString { - return AST.LsToMappableStringSlice(t.GetChildFormulas()) -} - +func (t TermForm) ToString() string { return t.ToString() } func (t TermForm) GetTerm() AST.Term { return t.t.Copy() } func (t TermForm) Copy() AST.Form { return makeTermForm(t.GetIndex(), t.GetTerm()) } func (t TermForm) RenameVariables() AST.Form { return t } @@ -118,10 +106,7 @@ func MakerTermForm(t AST.Term) TermForm { } func makeTermForm(i int, t AST.Term) TermForm { - fms := &AST.MappedString{} - tf := TermForm{fms, i, t.Copy()} - fms.MappableString = &tf - return tf + return TermForm{i, t.Copy()} } /* Parses a formulae to a sequence of instructions. */ diff --git a/src/main.go b/src/main.go index 1e72994f..0b82d896 100644 --- a/src/main.go +++ b/src/main.go @@ -190,9 +190,10 @@ func initEverything() { Glob.InitLogs() // Always init debuggers before options initDebuggers() + // Always init AST before options (for printers) + AST.Init() initOpts() runtime.GOMAXPROCS(Glob.GetCoreLimit()) - AST.Init() Typing.Init() } diff --git a/src/options.go b/src/options.go index 0fa84bf0..48cdf630 100644 --- a/src/options.go +++ b/src/options.go @@ -206,7 +206,7 @@ func buildOptions() { "pretty", false, "Should only be used with the -proof parameter. Enables UTF-8 characters in prints for a pretty proof", - func(bool) { Glob.DisplayPretty() }, + func(bool) { AST.SetPrinter(AST.PrettyPrinter) }, func(bool) {}) (&option[bool]{}).init( "dmt", @@ -390,16 +390,16 @@ func buildOptions() { }, func(bool) {}) (&option[bool]{}).init( - "no_id", + "print-id", false, - "Disables the id in the ToString", - func(bool) { AST.ToStringId = AST.NoIdToString }, + "Enables id printing", + func(bool) { AST.ComposePrinter(AST.PrintIDAction) }, func(bool) {}) (&option[bool]{}).init( "quoted_pred", false, "Print predicates between quotes if they start by a capital letter (TPTP compliance)", - func(bool) { AST.ToStringId = AST.QuotedToString }, + func(bool) { AST.ComposePrinter(AST.QuoteID) }, func(bool) {}) (&option[bool]{}).init( "quiet", From e534bf1f2788aa7b385289f5663c21f337348889 Mon Sep 17 00:00:00 2001 From: Johann Rosain Date: Tue, 29 Jul 2025 13:32:32 +0200 Subject: [PATCH 13/30] Define printer for Rocq output --- src/AST/ty-syntax.go | 21 +++++++++++- src/Mods/rocq/context.go | 34 +++++++++++++------ src/Mods/rocq/output.go | 71 ++++++++++++++++++++++++++++++++++++---- src/Mods/rocq/proof.go | 20 +++++++---- 4 files changed, 122 insertions(+), 24 deletions(-) diff --git a/src/AST/ty-syntax.go b/src/AST/ty-syntax.go index 4c66ce75..f24bc75b 100644 --- a/src/AST/ty-syntax.go +++ b/src/AST/ty-syntax.go @@ -229,7 +229,7 @@ func (TyFunc) isTy() {} func (f TyFunc) ToString() string { return fmt.Sprintf("%s %s %s", printer.Str(printer.SurroundChild(f.in.ToString())), - printer.StrConn(ConnImp), + printer.StrConn(ConnMap), printer.Str(printer.SurroundChild(f.out.ToString())), ) } @@ -489,3 +489,22 @@ func TermToTy(trm Term) Ty { ) return nil } + +func mkDefaultFunctionalType(number_of_arguments int, out_type Ty) Ty { + if number_of_arguments == 0 { + return out_type + } + tys := Lib.MkList[Ty](number_of_arguments) + for i := 0; i < number_of_arguments; i++ { + tys.Upd(i, TIndividual()) + } + return MkTyFunc(MkTyProd(tys), out_type) +} + +func MkDefaultPredType(number_of_arguments int) Ty { + return mkDefaultFunctionalType(number_of_arguments, TProp()) +} + +func MkDefaultFunctionType(number_of_arguments int) Ty { + return mkDefaultFunctionalType(number_of_arguments, TIndividual()) +} diff --git a/src/Mods/rocq/context.go b/src/Mods/rocq/context.go index e389b712..15d16e86 100644 --- a/src/Mods/rocq/context.go +++ b/src/Mods/rocq/context.go @@ -44,6 +44,8 @@ import ( "github.com/GoelandProver/Goeland/Glob" "github.com/GoelandProver/Goeland/Lib" "github.com/GoelandProver/Goeland/Mods/dmt" + "github.com/GoelandProver/Goeland/Typing" + "slices" ) func makeContextIfNeeded(root AST.Form, metaList Lib.List[AST.Meta]) string { @@ -117,7 +119,16 @@ func getContextFromFormula(root AST.Form) []string { result = clean(result, getContextFromFormula(nf.GetForm())) case AST.Pred: if !nf.GetID().Equals(AST.Id_eq) { - result = append(result, fmt.Sprintf("Parameter %s.", nf.GetID().ToString())) + oty := Typing.QueryGlobalEnv(nf.GetID().GetName()) + var ty AST.Ty + switch rty := oty.(type) { + case Lib.Some[AST.Ty]: + ty = rty.Val + case Lib.None[AST.Ty]: + ty = AST.MkDefaultPredType(nf.GetArgs().Len()) + } + + result = append(result, fmt.Sprintf("Parameter %s : %s.", nf.GetID().ToString(), ty.ToString())) } for _, term := range nf.GetArgs().GetSlice() { result = append(result, clean(result, getContextFromTerm(term))...) @@ -129,8 +140,17 @@ func getContextFromFormula(root AST.Form) []string { func getContextFromTerm(trm AST.Term) []string { result := []string{} if fun, isFun := trm.(AST.Fun); isFun { + oty := Typing.QueryGlobalEnv(fun.GetName()) + var ty AST.Ty + switch rty := oty.(type) { + case Lib.Some[AST.Ty]: + ty = rty.Val + case Lib.None[AST.Ty]: + ty = AST.MkDefaultFunctionType(fun.GetArgs().Len()) + } + result = append(result, - fmt.Sprintf("Parameter %s.", fun.GetID().ToString())) + fmt.Sprintf("Parameter %s : %s.", fun.GetID().ToString(), ty.ToString())) for _, term := range fun.GetArgs().GetSlice() { result = append(result, clean(result, getContextFromTerm(term))...) } @@ -142,13 +162,7 @@ func getContextFromTerm(trm AST.Term) []string { func clean(set, add []string) []string { result := []string{} for _, str := range add { - found := false - for _, s := range set { - if s == str { - found = true - break - } - } + found := slices.Contains(set, str) if !found { result = append(result, str) } @@ -164,7 +178,7 @@ func contextualizeMetas(metaList Lib.List[AST.Meta]) string { return "Parameters " + strings.Join(result, " ") + " : goeland_U." } -var lemmas = `Require Export Classical. +var lemmas = `From Stdlib Require Import Classical. Lemma goeland_notnot : forall P : Prop, P -> (~ P -> False). diff --git a/src/Mods/rocq/output.go b/src/Mods/rocq/output.go index f48566f7..a03afa3b 100644 --- a/src/Mods/rocq/output.go +++ b/src/Mods/rocq/output.go @@ -37,6 +37,9 @@ package rocq import ( + "fmt" + "strings" + "github.com/GoelandProver/Goeland/AST" "github.com/GoelandProver/Goeland/Glob" "github.com/GoelandProver/Goeland/Lib" @@ -51,24 +54,78 @@ var RocqOutputProofStruct = &Search.OutputProofStruct{ProofOutput: MakeRocqOutpu // ---------------------------------------------------------------------------- // Plugin initialisation and main function to call. -// Section: init -// Functions: MakeRocqOutput -// Main functions of the rocq module. -// TODO: -// * Write the context for TFF problems - func MakeRocqOutput(prf []Search.ProofStruct, meta Lib.List[AST.Meta]) string { if len(prf) == 0 { Glob.PrintError("Rocq", "Nothing to output") return "" } - // FIXME: set the AST printer to (to be defined soon) CoqPrinter + // Setup Rocq printer + connectives := RocqPrinterConnectives() + printer := AST.Printer{PrinterAction: RocqPrinterAction(), PrinterConnective: &connectives} + AST.SetPrinter(printer) // Transform tableaux's proof in GS3 proof return MakeRocqProof(gs3.MakeGS3Proof(prf), meta) } +func RocqPrinterConnectives() AST.PrinterConnective { + return AST.MkPrinterConnective( + "RocqPrinterConnective", + map[AST.Connective]string{ + AST.ConnAll: "forall", + AST.ConnEx: "exists", + AST.ConnAnd: " /\\ ", + AST.ConnOr: " \\/ ", + AST.ConnImp: "->", + AST.ConnEqu: "<->", + AST.ConnTop: "True", + AST.ConnBot: "False", + + AST.ConnPi: "forall", + AST.ConnMap: "->", + + AST.SepVarsForm: ", ", + AST.SepTyArgs: ", ", + AST.SepArgsTyArgs: ", ", + AST.SepTyVars: " ", + AST.SepVarTy: "", + + AST.SurQuantStart: "", + AST.SurQuantEnd: "", + }, + ) +} + +func RocqPrinterAction() AST.PrinterAction { + connectives := RocqPrinterConnectives() + + sanitize_type := func(ty_str string) string { + replace := map[string]string{ + "$i": "goeland_U", + "$o": "Prop", + "$tType": "Type", + // FIXME: define a replacement for every defined stuff + } + for k, v := range replace { + ty_str = strings.ReplaceAll(ty_str, k, v) + } + return ty_str + } + rocq_action := AST.MkPrinterAction( + AST.PrinterIdentity, + func(i AST.Id) string { return i.GetName() }, + AST.PrinterIdentity2[int], + func(metaName string, index int) string { return fmt.Sprintf("%s_%d", metaName, index) }, + sanitize_type, + func(typed_var Lib.Pair[string, AST.Ty]) string { + return fmt.Sprintf("(%s : %s)", typed_var.Fst, sanitize_type(typed_var.Snd.ToString())) + }, + ) + rocq_action = rocq_action.Compose(AST.SanitizerAction(connectives, []string{"@"})) + return rocq_action.Compose(AST.RemoveSuperfluousParenthesesAction(connectives)) +} + var MakeRocqProof = func(proof *gs3.GS3Sequent, meta Lib.List[AST.Meta]) string { contextString := makeContextIfNeeded(proof.GetTargetForm(), meta) proofString := makeRocqProofFromGS3(proof) diff --git a/src/Mods/rocq/proof.go b/src/Mods/rocq/proof.go index 507feb59..b9e5de1d 100644 --- a/src/Mods/rocq/proof.go +++ b/src/Mods/rocq/proof.go @@ -108,11 +108,16 @@ func makeStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], constantsCre case Lib.Some[int]: actualTarget = t.Val case Lib.None[int]: - Glob.Anomaly("rocq", fmt.Sprintf( - "Index of %s not found in %s", - proof.GetTargetForm().ToString(), - Lib.ListToString(hypotheses, ", ", "[]"), - )) + // If the target formula is an equality, it _does not_ target any formula of the context, + // it simply tells us to close by congruence. Hence, we don't raise an anomaly if the + // target form is an equality. + if !isPredEqual(proof.GetTargetForm()) { + Glob.Anomaly("rocq", fmt.Sprintf( + "Index of %s not found in { %s }", + proof.GetTargetForm().ToString(), + Lib.ListToString(hypotheses, " ;; ", ""), + )) + } } switch proof.Rule() { @@ -248,7 +253,10 @@ func processMainFormula(form AST.Form) (Lib.List[AST.Form], AST.Form) { // Prints the theorem's name & properly formats the first formula. func makeTheorem(axioms Lib.List[AST.Form], conjecture AST.Form) string { - problemName := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(Glob.GetProblemName(), ".", "_"), "=", "_"), "+", "_") + problemName := Glob.GetProblemName() + for _, s := range []string{".", "=", "+", "-"} { + problemName = strings.ReplaceAll(problemName, s, "_") + } axiomsWithConj := Lib.ListCpy(axioms) axiomsWithConj.Append(AST.MakerNot(AST.MakerNot(conjecture))) formattedProblem := makeImpChain(axiomsWithConj) From 1b5a8e81ab772d52aae18dd396134a065771b956 Mon Sep 17 00:00:00 2001 From: Johann Rosain Date: Tue, 29 Jul 2025 15:11:33 +0200 Subject: [PATCH 14/30] Add systematic rocq compilation when running test suite --- devtools/run-test-suite.py | 122 ++++++++++++++---- devtools/test-suite/bugs/bug_52-1.p | 3 + devtools/test-suite/bugs/bug_52-3.p | 4 + devtools/test-suite/bugs_no_chk/bug_52-2.p | 13 ++ .../{basic => no_chk}/Axioms/SYN000+0.ax | 0 .../{basic => no_chk}/Axioms/SYN000_0.ax | 0 .../{basic => no_chk}/fol_syntax_chk.p | 0 .../{basic => no_chk}/tf0_syntax_chk.p | 0 devtools/test-suite/proofs/example_sctptp.out | 30 ++--- devtools/test-suite/proofs/example_sctptp.p | 4 +- devtools/test-suite/proofs/example_tptp.out | 30 ++--- devtools/test-suite/proofs/example_tptp.p | 2 +- devtools/test-suite/proofs/flatten-1.out | 10 +- devtools/test-suite/proofs/flatten-2.out | 10 +- .../test-suite/proofs/tf1_basic_thm-2.out | 38 +++--- devtools/test-suite/proofs/tf1_basic_thm.out | 22 ++-- shell.nix | 1 + src/Core/Sko/interface.go | 2 +- src/Core/skolemisation.go | 2 + 19 files changed, 192 insertions(+), 101 deletions(-) create mode 100644 devtools/test-suite/bugs/bug_52-1.p create mode 100644 devtools/test-suite/bugs/bug_52-3.p create mode 100644 devtools/test-suite/bugs_no_chk/bug_52-2.p rename devtools/test-suite/{basic => no_chk}/Axioms/SYN000+0.ax (100%) rename devtools/test-suite/{basic => no_chk}/Axioms/SYN000_0.ax (100%) rename devtools/test-suite/{basic => no_chk}/fol_syntax_chk.p (100%) rename devtools/test-suite/{basic => no_chk}/tf0_syntax_chk.p (100%) diff --git a/devtools/run-test-suite.py b/devtools/run-test-suite.py index 2b377173..a280e565 100644 --- a/devtools/run-test-suite.py +++ b/devtools/run-test-suite.py @@ -5,6 +5,7 @@ import sys import re import difflib +import shutil from subprocess import PIPE, run class Parser: @@ -12,6 +13,7 @@ class Parser: RES = "% result: " ENV = "% env: " EXIT_CODE = "% exit: " + no_rocq_check = False def __init__(self, filename): self.filename = filename @@ -20,6 +22,10 @@ def __init__(self, filename): self.parseEnv() self.parseExitCode() + args_avoid_chk = ["-proof", "-otptp", "-osctptp"] + if "no_chk" in filename or self.expectedExitCode != "" or any(arg in self.arguments for arg in args_avoid_chk) or self.expectedResult == "NOT VALID": + self.no_rocq_check = True + def parseGen(self, pat): with open(self.filename) as f: for line in f.readlines(): @@ -43,23 +49,103 @@ def parseExitCode(self): self.expectedExitCode = self.parseGen(self.EXIT_CODE).strip() def getCommandLine(self): - return self.env + " ../src/_build/goeland " + self.arguments + " " + self.filename + arguments = self.arguments + if not self.no_rocq_check: + arguments += " -context -orocq" + return self.env + " ../src/_build/goeland " + arguments + " " + self.filename + + def getArgsForPrinting(self): + rocq_chk_str = "" + if self.no_rocq_check: + rocq_chk_str = " (no Rocq check)" + return self.arguments + rocq_chk_str def sanitize(s): return s.encode('utf-8', errors='ignore').decode(errors='ignore') -def runProver(command): - print(f"Launching: {command}") +def runProver(f, command): + print(f"{f}\t{parser.getArgsForPrinting()}") result = run(command, stdout=PIPE, stderr=PIPE, universal_newlines=True, shell=True, encoding='utf-8') return (sanitize(result.stdout), sanitize(result.stderr), result.returncode) +def getRelevantOutput(output): + relevantLines = [] + ok = -1 + for line in output.split("\n"): + if re.search("% SZS output start", line): + ok = 1 + elif re.search("% SZS output end", line): + ok = -1 + elif ok == 0: + if len(line.strip()) > 0: + relevantLines.append(line.strip()) + else: + ok -= 1 + + return relevantLines + +def isExecutable(prog) : + return shutil.which(prog) is not None + +def getRocqCompiler() : + if isExecutable("rocq"): + return "rocq compile" + elif isExecutable("coqc"): + return "coqc" + else: + raise Exception("No Rocq executable found on the system") + +def makeRocqCheck(f, output): + rocq = getRocqCompiler() + rocq_lines = getRelevantOutput(output) + compile_success = False + filename = os.getcwd() + "/" + os.path.basename(f)[:-2].replace("-", "_") + with open(f"{filename}.v", "w") as tmp: + tmp.write("\n".join(rocq_lines)) + + result = run(f"{rocq} {filename}.v", stdout=PIPE, stderr=PIPE, universal_newlines=True, shell=True, encoding='utf-8') + compile_success = result.returncode == 0 + + try: + os.remove(f"{filename}.glob") + except FileNotFoundError: + pass + + if not compile_success: + print(f"ROCQ compile has failed.") + print(f"Reason: {result.stderr}") + exit(1) + else: + try: + os.remove(f"{filename}.v") + os.remove(f"{filename}.vo") + os.remove(f"{filename}.vok") + os.remove(f"{filename}.vos") + except FileNotFoundError: + pass + def runWithExpected(f, parser): - output, err, exit_code = runProver(parser.getCommandLine()) + """ + Runs Goéland on [f] using the parsed command line, then checks if the output corresponds to the expected one. + This function manages: + - error codes (e.g., it can detect whether Goéland exits with error code i + - results (e.g., VALID, NOT VALID). + + If Goéland runs into an unexpected error, we report it. Moreover, if the kind of expected return is a VALID + result, we run Rocq to check that the proof is indeed valid (except for files in the no-chk folder). + """ + output, err, exit_code = runProver(f, parser.getCommandLine()) if err != "": print(f"Runtime error: {err}") exit(1) + if parser.expectedExitCode != '': + if int(parser.expectedExitCode) != exit_code: + print(f"Error: expected exit code '{parser.expectedExitCode}', got: '{exit_code}'") + exit(1) + else: return + search = re.compile(".*% RES : (.*)$") for line in output.split("\n"): res = search.match(line) @@ -69,37 +155,21 @@ def runWithExpected(f, parser): print(f"Error: expected '{parser.expectedResult}', got: '{actual}'") exit(1) else: + if parser.no_rocq_check: return + makeRocqCheck(f, output) return - if parser.expectedExitCode != '': - if int(parser.expectedExitCode) != exit_code: - print(f"Error: expected exit code '{parser.expectedExitCode}', got: '{exit_code}'") - exit(1) - else: return - print(f"Unknown error: got\n{output}") exit(1) def compareOutputs(f, parser): - output, err, _ = runProver(parser.getCommandLine()) + output, err, exit_code = runProver(f, parser.getCommandLine()) - if err != "": + if err != "" or exit_code != 0: print(f"Runtime error: {err}") exit(1) - relevantLines = [] - ok = -1 - for line in output.split("\n"): - if re.search("% SZS output start", line): - ok = 1 - elif re.search("% SZS output end", line): - ok = -1 - elif ok == 0: - if len(line.strip()) > 0: - relevantLines.append(line.strip()) - else: - ok -= 1 - + relevantLines = getRelevantOutput(output) relevantExpectedLines = [] with open(os.path.splitext(f)[0] + ".out") as f: @@ -119,7 +189,7 @@ def compareOutputs(f, parser): if __name__ == "__main__": outputTest = ["-proof", "-otptp", "-osctptp"] - for f in glob.glob("test-suite/**/*.p"): + for f in sorted(glob.glob("test-suite/**/*.p")): parser = Parser(f) if any(out in parser.arguments for out in outputTest) : diff --git a/devtools/test-suite/bugs/bug_52-1.p b/devtools/test-suite/bugs/bug_52-1.p new file mode 100644 index 00000000..0c3cd848 --- /dev/null +++ b/devtools/test-suite/bugs/bug_52-1.p @@ -0,0 +1,3 @@ +% result: VALID + +fof(rocq_output_test,conjecture,! [X]: (p(X) | ~p(X))). diff --git a/devtools/test-suite/bugs/bug_52-3.p b/devtools/test-suite/bugs/bug_52-3.p new file mode 100644 index 00000000..4026b2be --- /dev/null +++ b/devtools/test-suite/bugs/bug_52-3.p @@ -0,0 +1,4 @@ +% tests for the presence of metavariables +% result: VALID + +fof(rocq_output_test,conjecture,? [X]: (p(X) | ~p(X))). diff --git a/devtools/test-suite/bugs_no_chk/bug_52-2.p b/devtools/test-suite/bugs_no_chk/bug_52-2.p new file mode 100644 index 00000000..f054cf22 --- /dev/null +++ b/devtools/test-suite/bugs_no_chk/bug_52-2.p @@ -0,0 +1,13 @@ +% TODO: move this file to bugs once we enable typed GS3 proofs +% result: VALID + +tff(nat_type,type,nat : $tType). +tff(zero_nat,type,zero : nat). +tff(succ_nat,type,succ : nat > nat). +tff(list_type,type,list : $tType > $tType). +tff(nil_list,type,nil : !> [A]: list(A)). +tff(cons_list,type,cons : !> [A]: ((A * list(A)) > list(A))). +tff(p_type,type,p : !> [A : $tType]: (list(A) > $o)). + +tff(rocq_output_test,conjecture,! [A: $tType, X : A]: + ((succ(zero) = succ(zero)) | (p(A,cons(A,X,nil(A))) | ~p(A,cons(A,X,nil(A)))))). diff --git a/devtools/test-suite/basic/Axioms/SYN000+0.ax b/devtools/test-suite/no_chk/Axioms/SYN000+0.ax similarity index 100% rename from devtools/test-suite/basic/Axioms/SYN000+0.ax rename to devtools/test-suite/no_chk/Axioms/SYN000+0.ax diff --git a/devtools/test-suite/basic/Axioms/SYN000_0.ax b/devtools/test-suite/no_chk/Axioms/SYN000_0.ax similarity index 100% rename from devtools/test-suite/basic/Axioms/SYN000_0.ax rename to devtools/test-suite/no_chk/Axioms/SYN000_0.ax diff --git a/devtools/test-suite/basic/fol_syntax_chk.p b/devtools/test-suite/no_chk/fol_syntax_chk.p similarity index 100% rename from devtools/test-suite/basic/fol_syntax_chk.p rename to devtools/test-suite/no_chk/fol_syntax_chk.p diff --git a/devtools/test-suite/basic/tf0_syntax_chk.p b/devtools/test-suite/no_chk/tf0_syntax_chk.p similarity index 100% rename from devtools/test-suite/basic/tf0_syntax_chk.p rename to devtools/test-suite/no_chk/tf0_syntax_chk.p diff --git a/devtools/test-suite/proofs/example_sctptp.out b/devtools/test-suite/proofs/example_sctptp.out index 18621ff5..b99a1dfc 100644 --- a/devtools/test-suite/proofs/example_sctptp.out +++ b/devtools/test-suite/proofs/example_sctptp.out @@ -1,29 +1,29 @@ -fof(c_example_sctptp_p, conjecture, ((! [X4] : (p(X4))) <=> ~((? [Y6] : (~(p(Y6))))))). +fof(c_example_sctptp_p, conjecture, (! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))). -fof(f8, plain, [~(((! [X4] : (p(X4))) <=> ~((? [Y6] : (~(p(Y6))))))), ~((! [X4] : (p(X4)))), ~((? [Y6] : (~(p(Y6))))), ~((~((? [Y6] : (~(p(Y6))))) => (! [X4] : (p(X4))))), ~(p(Sko_0)), ~(~(p(Sko_0))), p(Sko_0)] --> [], inference(leftHyp, [status(thm), 6], [])). +fof(f8, plain, [~((! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))), ~(! [X4]: p(X4)), ~(? [Y6]: ~p(Y6)), ~(~(? [Y6]: ~p(Y6)) => (! [X4]: p(X4))), ~p(Sko_0), ~~p(Sko_0), p(Sko_0)] --> [], inference(leftHyp, [status(thm), 6], [])). -fof(f7, plain, [~(((! [X4] : (p(X4))) <=> ~((? [Y6] : (~(p(Y6))))))), ~((! [X4] : (p(X4)))), ~((? [Y6] : (~(p(Y6))))), ~((~((? [Y6] : (~(p(Y6))))) => (! [X4] : (p(X4))))), ~(p(Sko_0)), ~(~(p(Sko_0)))] --> [], inference(leftNotNot, [status(thm), 5], [f8])). +fof(f7, plain, [~((! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))), ~(! [X4]: p(X4)), ~(? [Y6]: ~p(Y6)), ~(~(? [Y6]: ~p(Y6)) => (! [X4]: p(X4))), ~p(Sko_0), ~~p(Sko_0)] --> [], inference(leftNotNot, [status(thm), 5], [f8])). -fof(f6, plain, [~(((! [X4] : (p(X4))) <=> ~((? [Y6] : (~(p(Y6))))))), ~((! [X4] : (p(X4)))), ~((? [Y6] : (~(p(Y6))))), ~((~((? [Y6] : (~(p(Y6))))) => (! [X4] : (p(X4))))), ~(p(Sko_0))] --> [], inference(leftNotEx, [status(thm), 2, $fot(Sko_0)], [f7])). +fof(f6, plain, [~((! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))), ~(! [X4]: p(X4)), ~(? [Y6]: ~p(Y6)), ~(~(? [Y6]: ~p(Y6)) => (! [X4]: p(X4))), ~p(Sko_0)] --> [], inference(leftNotEx, [status(thm), 2, $fot(Sko_0)], [f7])). -fof(f4, plain, [~(((! [X4] : (p(X4))) <=> ~((? [Y6] : (~(p(Y6))))))), ~((! [X4] : (p(X4)))), ~((? [Y6] : (~(p(Y6))))), ~((~((? [Y6] : (~(p(Y6))))) => (! [X4] : (p(X4)))))] --> [], inference(leftNotAll, [status(thm), 1, 'Sko_0'], [f6])). +fof(f4, plain, [~((! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))), ~(! [X4]: p(X4)), ~(? [Y6]: ~p(Y6)), ~(~(? [Y6]: ~p(Y6)) => (! [X4]: p(X4)))] --> [], inference(leftNotAll, [status(thm), 1, 'Sko_0'], [f6])). -fof(f11, plain, [~(((! [X4] : (p(X4))) <=> ~((? [Y6] : (~(p(Y6))))))), (! [X4] : (p(X4))), ~(~((? [Y6] : (~(p(Y6)))))), ~(((! [X4] : (p(X4))) => ~((? [Y6] : (~(p(Y6))))))), (? [Y6] : (~(p(Y6)))), ~(p(Sko_1)), p(Sko_1)] --> [], inference(leftHyp, [status(thm), 6], [])). +fof(f11, plain, [~((! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))), ! [X4]: p(X4), ~~(? [Y6]: ~p(Y6)), ~((! [X4]: p(X4)) => ~(? [Y6]: ~p(Y6))), ? [Y6]: ~p(Y6), ~p(Sko_1), p(Sko_1)] --> [], inference(leftHyp, [status(thm), 6], [])). -fof(f10, plain, [~(((! [X4] : (p(X4))) <=> ~((? [Y6] : (~(p(Y6))))))), (! [X4] : (p(X4))), ~(~((? [Y6] : (~(p(Y6)))))), ~(((! [X4] : (p(X4))) => ~((? [Y6] : (~(p(Y6))))))), (? [Y6] : (~(p(Y6)))), ~(p(Sko_1))] --> [], inference(leftForall, [status(thm), 1, $fot(Sko_1)], [f11])). +fof(f10, plain, [~((! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))), ! [X4]: p(X4), ~~(? [Y6]: ~p(Y6)), ~((! [X4]: p(X4)) => ~(? [Y6]: ~p(Y6))), ? [Y6]: ~p(Y6), ~p(Sko_1)] --> [], inference(leftForall, [status(thm), 1, $fot(Sko_1)], [f11])). -fof(f9, plain, [~(((! [X4] : (p(X4))) <=> ~((? [Y6] : (~(p(Y6))))))), (! [X4] : (p(X4))), ~(~((? [Y6] : (~(p(Y6)))))), ~(((! [X4] : (p(X4))) => ~((? [Y6] : (~(p(Y6))))))), (? [Y6] : (~(p(Y6))))] --> [], inference(leftExists, [status(thm), 4, 'Sko_1'], [f10])). +fof(f9, plain, [~((! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))), ! [X4]: p(X4), ~~(? [Y6]: ~p(Y6)), ~((! [X4]: p(X4)) => ~(? [Y6]: ~p(Y6))), ? [Y6]: ~p(Y6)] --> [], inference(leftExists, [status(thm), 4, 'Sko_1'], [f10])). -fof(f5, plain, [~(((! [X4] : (p(X4))) <=> ~((? [Y6] : (~(p(Y6))))))), (! [X4] : (p(X4))), ~(~((? [Y6] : (~(p(Y6)))))), ~(((! [X4] : (p(X4))) => ~((? [Y6] : (~(p(Y6)))))))] --> [], inference(leftNotNot, [status(thm), 2], [f9])). +fof(f5, plain, [~((! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))), ! [X4]: p(X4), ~~(? [Y6]: ~p(Y6)), ~((! [X4]: p(X4)) => ~(? [Y6]: ~p(Y6)))] --> [], inference(leftNotNot, [status(thm), 2], [f9])). -fof(f3ext2, plain, [~(((! [X4] : (p(X4))) <=> ~((? [Y6] : (~(p(Y6))))))), ~((~((? [Y6] : (~(p(Y6))))) => (! [X4] : (p(X4)))))] --> [], inference(leftNotImplies, [status(thm), 1], [f4])). +fof(f3ext2, plain, [~((! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))), ~(~(? [Y6]: ~p(Y6)) => (! [X4]: p(X4)))] --> [], inference(leftNotImplies, [status(thm), 1], [f4])). -fof(f3ext1, plain, [~(((! [X4] : (p(X4))) <=> ~((? [Y6] : (~(p(Y6))))))), ~(((! [X4] : (p(X4))) => ~((? [Y6] : (~(p(Y6)))))))] --> [], inference(leftNotImplies, [status(thm), 1], [f5])). +fof(f3ext1, plain, [~((! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))), ~((! [X4]: p(X4)) => ~(? [Y6]: ~p(Y6)))] --> [], inference(leftNotImplies, [status(thm), 1], [f5])). -fof(f3, plain, [~(((! [X4] : (p(X4))) <=> ~((? [Y6] : (~(p(Y6)))))))] --> [], inference(leftNotIff, [status(thm), 0], [f3ext1, f3ext2])). +fof(f3, plain, [~((! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6)))] --> [], inference(leftNotIff, [status(thm), 0], [f3ext1, f3ext2])). -fof(f2, plain, [((! [X4] : (p(X4))) <=> ~((? [Y6] : (~(p(Y6))))))] --> [((! [X4] : (p(X4))) <=> ~((? [Y6] : (~(p(Y6))))))], inference(hyp, [status(thm), 0], [])). +fof(f2, plain, [(! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))] --> [(! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))], inference(hyp, [status(thm), 0], [])). -fof(f1, plain, [] --> [((! [X4] : (p(X4))) <=> ~((? [Y6] : (~(p(Y6)))))), ~(((! [X4] : (p(X4))) <=> ~((? [Y6] : (~(p(Y6)))))))], inference(rightNot, [status(thm), 1], [f2])). +fof(f1, plain, [] --> [(! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6)), ~((! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6)))], inference(rightNot, [status(thm), 1], [f2])). -fof(f0, plain, [] --> [((! [X4] : (p(X4))) <=> ~((? [Y6] : (~(p(Y6))))))], inference(cut, [status(thm), 1], [f1, f3])). \ No newline at end of file +fof(f0, plain, [] --> [(! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))], inference(cut, [status(thm), 1], [f1, f3])). diff --git a/devtools/test-suite/proofs/example_sctptp.p b/devtools/test-suite/proofs/example_sctptp.p index 25b76bce..d877b98f 100644 --- a/devtools/test-suite/proofs/example_sctptp.p +++ b/devtools/test-suite/proofs/example_sctptp.p @@ -1,7 +1,5 @@ -% args: -no_id -osctptp +% args: -osctptp % result: VALID fof(test_sctptp, conjecture, (! [X] : p(X)) <=> (~(? [Y] : ~p(Y)))). - - \ No newline at end of file diff --git a/devtools/test-suite/proofs/example_tptp.out b/devtools/test-suite/proofs/example_tptp.out index f574adc7..3ae286e7 100644 --- a/devtools/test-suite/proofs/example_tptp.out +++ b/devtools/test-suite/proofs/example_tptp.out @@ -1,29 +1,29 @@ -fof(c_example_tptp_p, conjecture, ((! [X4] : (p(X4))) <=> ~((? [Y6] : (~(p(Y6))))))). +fof(c_example_tptp_p, conjecture, (! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))). -fof(f8, plain, [~(((! [X4] : (p(X4))) <=> ~((? [Y6] : (~(p(Y6))))))), ~((! [X4] : (p(X4)))), ~((? [Y6] : (~(p(Y6))))), ~((~((? [Y6] : (~(p(Y6))))) => (! [X4] : (p(X4))))), ~(p(sko_0)), ~(~(p(sko_0))), p(sko_0)] --> [], inference(leftHyp, [status(thm), 6], [])). +fof(f8, plain, [~((! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))), ~(! [X4]: p(X4)), ~(? [Y6]: ~p(Y6)), ~(~(? [Y6]: ~p(Y6)) => (! [X4]: p(X4))), ~p(sko_0), ~~p(sko_0), p(sko_0)] --> [], inference(leftHyp, [status(thm), 6], [])). -fof(f7, plain, [~(((! [X4] : (p(X4))) <=> ~((? [Y6] : (~(p(Y6))))))), ~((! [X4] : (p(X4)))), ~((? [Y6] : (~(p(Y6))))), ~((~((? [Y6] : (~(p(Y6))))) => (! [X4] : (p(X4))))), ~(p(sko_0)), ~(~(p(sko_0)))] --> [], inference(leftNotNot, [status(thm), 5], [f8])). +fof(f7, plain, [~((! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))), ~(! [X4]: p(X4)), ~(? [Y6]: ~p(Y6)), ~(~(? [Y6]: ~p(Y6)) => (! [X4]: p(X4))), ~p(sko_0), ~~p(sko_0)] --> [], inference(leftNotNot, [status(thm), 5], [f8])). -fof(f6, plain, [~(((! [X4] : (p(X4))) <=> ~((? [Y6] : (~(p(Y6))))))), ~((! [X4] : (p(X4)))), ~((? [Y6] : (~(p(Y6))))), ~((~((? [Y6] : (~(p(Y6))))) => (! [X4] : (p(X4))))), ~(p(sko_0))] --> [], inference(leftNotEx, [status(thm), 2, $fot(sko_0)], [f7])). +fof(f6, plain, [~((! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))), ~(! [X4]: p(X4)), ~(? [Y6]: ~p(Y6)), ~(~(? [Y6]: ~p(Y6)) => (! [X4]: p(X4))), ~p(sko_0)] --> [], inference(leftNotEx, [status(thm), 2, $fot(sko_0)], [f7])). -fof(f4, plain, [~(((! [X4] : (p(X4))) <=> ~((? [Y6] : (~(p(Y6))))))), ~((! [X4] : (p(X4)))), ~((? [Y6] : (~(p(Y6))))), ~((~((? [Y6] : (~(p(Y6))))) => (! [X4] : (p(X4)))))] --> [], inference(leftNotAll, [status(thm), 1, 'sko_0'], [f6])). +fof(f4, plain, [~((! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))), ~(! [X4]: p(X4)), ~(? [Y6]: ~p(Y6)), ~(~(? [Y6]: ~p(Y6)) => (! [X4]: p(X4)))] --> [], inference(leftNotAll, [status(thm), 1, 'sko_0'], [f6])). -fof(f11, plain, [~(((! [X4] : (p(X4))) <=> ~((? [Y6] : (~(p(Y6))))))), (! [X4] : (p(X4))), ~(~((? [Y6] : (~(p(Y6)))))), ~(((! [X4] : (p(X4))) => ~((? [Y6] : (~(p(Y6))))))), (? [Y6] : (~(p(Y6)))), ~(p(sko_1)), p(sko_1)] --> [], inference(leftHyp, [status(thm), 6], [])). +fof(f11, plain, [~((! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))), ! [X4]: p(X4), ~~(? [Y6]: ~p(Y6)), ~((! [X4]: p(X4)) => ~(? [Y6]: ~p(Y6))), ? [Y6]: ~p(Y6), ~p(sko_1), p(sko_1)] --> [], inference(leftHyp, [status(thm), 6], [])). -fof(f10, plain, [~(((! [X4] : (p(X4))) <=> ~((? [Y6] : (~(p(Y6))))))), (! [X4] : (p(X4))), ~(~((? [Y6] : (~(p(Y6)))))), ~(((! [X4] : (p(X4))) => ~((? [Y6] : (~(p(Y6))))))), (? [Y6] : (~(p(Y6)))), ~(p(sko_1))] --> [], inference(leftForall, [status(thm), 1, $fot(sko_1)], [f11])). +fof(f10, plain, [~((! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))), ! [X4]: p(X4), ~~(? [Y6]: ~p(Y6)), ~((! [X4]: p(X4)) => ~(? [Y6]: ~p(Y6))), ? [Y6]: ~p(Y6), ~p(sko_1)] --> [], inference(leftForall, [status(thm), 1, $fot(sko_1)], [f11])). -fof(f9, plain, [~(((! [X4] : (p(X4))) <=> ~((? [Y6] : (~(p(Y6))))))), (! [X4] : (p(X4))), ~(~((? [Y6] : (~(p(Y6)))))), ~(((! [X4] : (p(X4))) => ~((? [Y6] : (~(p(Y6))))))), (? [Y6] : (~(p(Y6))))] --> [], inference(leftExists, [status(thm), 4, 'sko_1'], [f10])). +fof(f9, plain, [~((! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))), ! [X4]: p(X4), ~~(? [Y6]: ~p(Y6)), ~((! [X4]: p(X4)) => ~(? [Y6]: ~p(Y6))), ? [Y6]: ~p(Y6)] --> [], inference(leftExists, [status(thm), 4, 'sko_1'], [f10])). -fof(f5, plain, [~(((! [X4] : (p(X4))) <=> ~((? [Y6] : (~(p(Y6))))))), (! [X4] : (p(X4))), ~(~((? [Y6] : (~(p(Y6)))))), ~(((! [X4] : (p(X4))) => ~((? [Y6] : (~(p(Y6)))))))] --> [], inference(leftNotNot, [status(thm), 2], [f9])). +fof(f5, plain, [~((! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))), ! [X4]: p(X4), ~~(? [Y6]: ~p(Y6)), ~((! [X4]: p(X4)) => ~(? [Y6]: ~p(Y6)))] --> [], inference(leftNotNot, [status(thm), 2], [f9])). -fof(f3ext2, plain, [~(((! [X4] : (p(X4))) <=> ~((? [Y6] : (~(p(Y6))))))), ~((~((? [Y6] : (~(p(Y6))))) => (! [X4] : (p(X4)))))] --> [], inference(leftNotImplies, [status(thm), 1], [f4])). +fof(f3ext2, plain, [~((! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))), ~(~(? [Y6]: ~p(Y6)) => (! [X4]: p(X4)))] --> [], inference(leftNotImplies, [status(thm), 1], [f4])). -fof(f3ext1, plain, [~(((! [X4] : (p(X4))) <=> ~((? [Y6] : (~(p(Y6))))))), ~(((! [X4] : (p(X4))) => ~((? [Y6] : (~(p(Y6)))))))] --> [], inference(leftNotImplies, [status(thm), 1], [f5])). +fof(f3ext1, plain, [~((! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))), ~((! [X4]: p(X4)) => ~(? [Y6]: ~p(Y6)))] --> [], inference(leftNotImplies, [status(thm), 1], [f5])). -fof(f3, plain, [~(((! [X4] : (p(X4))) <=> ~((? [Y6] : (~(p(Y6)))))))] --> [], inference(leftNotIff, [status(thm), 0], [f3ext1, f3ext2])). +fof(f3, plain, [~((! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6)))] --> [], inference(leftNotIff, [status(thm), 0], [f3ext1, f3ext2])). -fof(f2, plain, [((! [X4] : (p(X4))) <=> ~((? [Y6] : (~(p(Y6))))))] --> [((! [X4] : (p(X4))) <=> ~((? [Y6] : (~(p(Y6))))))], inference(hyp, [status(thm), 0], [])). +fof(f2, plain, [(! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))] --> [(! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))], inference(hyp, [status(thm), 0], [])). -fof(f1, plain, [] --> [((! [X4] : (p(X4))) <=> ~((? [Y6] : (~(p(Y6)))))), ~(((! [X4] : (p(X4))) <=> ~((? [Y6] : (~(p(Y6)))))))], inference(rightNot, [status(thm), 1], [f2])). +fof(f1, plain, [] --> [(! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6)), ~((! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6)))], inference(rightNot, [status(thm), 1], [f2])). -fof(f0, plain, [] --> [((! [X4] : (p(X4))) <=> ~((? [Y6] : (~(p(Y6))))))], inference(cut, [status(thm), 1], [f1, f3])). \ No newline at end of file +fof(f0, plain, [] --> [(! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))], inference(cut, [status(thm), 1], [f1, f3])). diff --git a/devtools/test-suite/proofs/example_tptp.p b/devtools/test-suite/proofs/example_tptp.p index a7835d7c..7c6928d5 100644 --- a/devtools/test-suite/proofs/example_tptp.p +++ b/devtools/test-suite/proofs/example_tptp.p @@ -1,4 +1,4 @@ -% args: -no_id -otptp +% args: -otptp % result: VALID fof(test_tptp, conjecture, diff --git a/devtools/test-suite/proofs/flatten-1.out b/devtools/test-suite/proofs/flatten-1.out index 8f7c127f..def47b3c 100644 --- a/devtools/test-suite/proofs/flatten-1.out +++ b/devtools/test-suite/proofs/flatten-1.out @@ -1,7 +1,7 @@ -[0] ALPHA_NOT_NOT : ~(~((p_1 & q_2 & ~(p_1)))) - -> [1] (p_1 & q_2 & ~(p_1)) +[0] ALPHA_NOT_NOT : ~~(p & q & ~p) + -> [1] p & q & ~p -[1] ALPHA_AND : (p_1 & q_2 & ~(p_1)) - -> [2] p_1, q_2, ~(p_1) +[1] ALPHA_AND : p & q & ~p + -> [2] p, q, ~p -[2] CLOSURE : p_1 +[2] CLOSURE : p diff --git a/devtools/test-suite/proofs/flatten-2.out b/devtools/test-suite/proofs/flatten-2.out index 09a62e72..4de193ea 100644 --- a/devtools/test-suite/proofs/flatten-2.out +++ b/devtools/test-suite/proofs/flatten-2.out @@ -1,7 +1,7 @@ -[0] ALPHA_NOT_OR : ~((p_1 | q_2 | ~(p_1))) - -> [1] ~(p_1), ~(q_2), ~(~(p_1)) +[0] ALPHA_NOT_OR : ~(p | q | ~p) + -> [1] ~p, ~q, ~~p -[1] ALPHA_NOT_NOT : ~(~(p_1)) - -> [2] p_1 +[1] ALPHA_NOT_NOT : ~~p + -> [2] p -[2] CLOSURE : p_1 +[2] CLOSURE : p diff --git a/devtools/test-suite/proofs/tf1_basic_thm-2.out b/devtools/test-suite/proofs/tf1_basic_thm-2.out index b87de471..9f8a3e0e 100644 --- a/devtools/test-suite/proofs/tf1_basic_thm-2.out +++ b/devtools/test-suite/proofs/tf1_basic_thm-2.out @@ -1,28 +1,28 @@ -[0] ALPHA_AND : ((! [A13]: ((maybe(A13) ; head(A13;nil(A13;)) = none(A13;)))) & (! [A15 X17 XS19]: ((maybe(A15) ; head(A15;cons(A15;X17, XS19)) = some(A15;X17)))) & ~((! [A21 X23 Y25 Z27]: ((maybe(A21) ; head(A21;cons(A21;X23, cons(A21;Y25, cons(A21;Z27, nil(A21;))))) = some(A21;X23)))))) - -> [1] (! [A13]: ((maybe(A13) ; head(A13;nil(A13;)) = none(A13;)))), (! [A15 X17 XS19]: ((maybe(A15) ; head(A15;cons(A15;X17, XS19)) = some(A15;X17)))), ~((! [A21 X23 Y25 Z27]: ((maybe(A21) ; head(A21;cons(A21;X23, cons(A21;Y25, cons(A21;Z27, nil(A21;))))) = some(A21;X23))))) +[0] ALPHA_AND : (! [A13]: head(A13 ; nil(A13 ; )) = none(A13 ; )) & (! [A15, X17, XS19]: head(A15 ; cons(A15 ; X17, XS19)) = some(A15 ; X17)) & ~(! [A21, X23, Y25, Z27]: head(A21 ; cons(A21 ; X23, cons(A21 ; Y25, cons(A21 ; Z27, nil(A21 ; ))))) = some(A21 ; X23)) + -> [1] ! [A13]: head(A13 ; nil(A13 ; )) = none(A13 ; ), ! [A15, X17, XS19]: head(A15 ; cons(A15 ; X17, XS19)) = some(A15 ; X17), ~(! [A21, X23, Y25, Z27]: head(A21 ; cons(A21 ; X23, cons(A21 ; Y25, cons(A21 ; Z27, nil(A21 ; ))))) = some(A21 ; X23)) -[1] DELTA_NOT_FORALL : ~((! [A21 X23 Y25 Z27]: ((maybe(A21) ; head(A21;cons(A21;X23, cons(A21;Y25, cons(A21;Z27, nil(A21;))))) = some(A21;X23))))) - -> [2] ~((! [X23 Y25 Z27]: ((maybe(skoTy) ; head(skoTy;cons(skoTy;X23, cons(skoTy;Y25, cons(skoTy;Z27, nil(skoTy;))))) = some(skoTy;X23))))) +[1] DELTA_NOT_FORALL : ~(! [A21, X23, Y25, Z27]: head(A21 ; cons(A21 ; X23, cons(A21 ; Y25, cons(A21 ; Z27, nil(A21 ; ))))) = some(A21 ; X23)) + -> [2] ~(! [X23, Y25, Z27]: head(skoTy@29 ; cons(skoTy@29 ; X23, cons(skoTy@29 ; Y25, cons(skoTy@29 ; Z27, nil(skoTy@29 ; ))))) = some(skoTy@29 ; X23)) -[2] DELTA_NOT_FORALL : ~((! [X23 Y25 Z27]: ((maybe(skoTy) ; head(skoTy;cons(skoTy;X23, cons(skoTy;Y25, cons(skoTy;Z27, nil(skoTy;))))) = some(skoTy;X23))))) - -> [3] ~((! [Y25 Z27]: ((maybe(skoTy) ; head(skoTy;cons(skoTy;skolem@X23, cons(skoTy;Y25, cons(skoTy;Z27, nil(skoTy;))))) = some(skoTy;skolem@X23))))) +[2] DELTA_NOT_FORALL : ~(! [X23, Y25, Z27]: head(skoTy@29 ; cons(skoTy@29 ; X23, cons(skoTy@29 ; Y25, cons(skoTy@29 ; Z27, nil(skoTy@29 ; ))))) = some(skoTy@29 ; X23)) + -> [3] ~(! [Y25, Z27]: head(skoTy@29 ; cons(skoTy@29 ; skolem@X23@0, cons(skoTy@29 ; Y25, cons(skoTy@29 ; Z27, nil(skoTy@29 ; ))))) = some(skoTy@29 ; skolem@X23@0)) -[3] DELTA_NOT_FORALL : ~((! [Y25 Z27]: ((maybe(skoTy) ; head(skoTy;cons(skoTy;skolem@X23, cons(skoTy;Y25, cons(skoTy;Z27, nil(skoTy;))))) = some(skoTy;skolem@X23))))) - -> [4] ~((! [Z27]: ((maybe(skoTy) ; head(skoTy;cons(skoTy;skolem@X23, cons(skoTy;skolem@Y25, cons(skoTy;Z27, nil(skoTy;))))) = some(skoTy;skolem@X23))))) +[3] DELTA_NOT_FORALL : ~(! [Y25, Z27]: head(skoTy@29 ; cons(skoTy@29 ; skolem@X23@0, cons(skoTy@29 ; Y25, cons(skoTy@29 ; Z27, nil(skoTy@29 ; ))))) = some(skoTy@29 ; skolem@X23@0)) + -> [4] ~(! [Z27]: head(skoTy@29 ; cons(skoTy@29 ; skolem@X23@0, cons(skoTy@29 ; skolem@Y25@1, cons(skoTy@29 ; Z27, nil(skoTy@29 ; ))))) = some(skoTy@29 ; skolem@X23@0)) -[4] DELTA_NOT_FORALL : ~((! [Z27]: ((maybe(skoTy) ; head(skoTy;cons(skoTy;skolem@X23, cons(skoTy;skolem@Y25, cons(skoTy;Z27, nil(skoTy;))))) = some(skoTy;skolem@X23))))) - -> [5] ~((maybe(skoTy) ; head(skoTy;cons(skoTy;skolem@X23, cons(skoTy;skolem@Y25, cons(skoTy;skolem@Z27, nil(skoTy;))))) = some(skoTy;skolem@X23))) +[4] DELTA_NOT_FORALL : ~(! [Z27]: head(skoTy@29 ; cons(skoTy@29 ; skolem@X23@0, cons(skoTy@29 ; skolem@Y25@1, cons(skoTy@29 ; Z27, nil(skoTy@29 ; ))))) = some(skoTy@29 ; skolem@X23@0)) + -> [5] ~(head(skoTy@29 ; cons(skoTy@29 ; skolem@X23@0, cons(skoTy@29 ; skolem@Y25@1, cons(skoTy@29 ; skolem@Z27@2, nil(skoTy@29 ; ))))) = some(skoTy@29 ; skolem@X23@0)) -[5] GAMMA_FORALL : (! [A13]: ((maybe(A13) ; head(A13;nil(A13;)) = none(A13;)))) - -> [6] (maybe(A13_1) ; head(A13_1;nil(A13_1;)) = none(A13_1;)) +[5] GAMMA_FORALL : ! [A13]: head(A13 ; nil(A13 ; )) = none(A13 ; ) + -> [6] head(A13 ; nil(A13 ; )) = none(A13 ; ) -[6] GAMMA_FORALL : (! [A15 X17 XS19]: ((maybe(A15) ; head(A15;cons(A15;X17, XS19)) = some(A15;X17)))) - -> [7] (! [X17 XS19]: ((maybe(skoTy) ; head(skoTy;cons(skoTy;X17, XS19)) = some(skoTy;X17)))) +[6] GAMMA_FORALL : ! [A15, X17, XS19]: head(A15 ; cons(A15 ; X17, XS19)) = some(A15 ; X17) + -> [7] ! [X17, XS19]: head(skoTy@29 ; cons(skoTy@29 ; X17, XS19)) = some(skoTy@29 ; X17) -[7] GAMMA_FORALL : (! [X17 XS19]: ((maybe(skoTy) ; head(skoTy;cons(skoTy;X17, XS19)) = some(skoTy;X17)))) - -> [8] (! [XS19]: ((maybe(skoTy) ; head(skoTy;cons(skoTy;skolem@X23, XS19)) = some(skoTy;skolem@X23)))) +[7] GAMMA_FORALL : ! [X17, XS19]: head(skoTy@29 ; cons(skoTy@29 ; X17, XS19)) = some(skoTy@29 ; X17) + -> [8] ! [XS19]: head(skoTy@29 ; cons(skoTy@29 ; skolem@X23@0, XS19)) = some(skoTy@29 ; skolem@X23@0) -[8] GAMMA_FORALL : (! [XS19]: ((maybe(skoTy) ; head(skoTy;cons(skoTy;skolem@X23, XS19)) = some(skoTy;skolem@X23)))) - -> [9] (maybe(skoTy) ; head(skoTy;cons(skoTy;skolem@X23, cons(skoTy;skolem@Y25, cons(skoTy;skolem@Z27, nil(skoTy;))))) = some(skoTy;skolem@X23)) +[8] GAMMA_FORALL : ! [XS19]: head(skoTy@29 ; cons(skoTy@29 ; skolem@X23@0, XS19)) = some(skoTy@29 ; skolem@X23@0) + -> [9] head(skoTy@29 ; cons(skoTy@29 ; skolem@X23@0, cons(skoTy@29 ; skolem@Y25@1, cons(skoTy@29 ; skolem@Z27@2, nil(skoTy@29 ; ))))) = some(skoTy@29 ; skolem@X23@0) -[9] CLOSURE : (maybe(skoTy) ; head(skoTy;cons(skoTy;skolem@X23, cons(skoTy;skolem@Y25, cons(skoTy;skolem@Z27, nil(skoTy;))))) = some(skoTy;skolem@X23)) +[9] CLOSURE : head(skoTy@29 ; cons(skoTy@29 ; skolem@X23@0, cons(skoTy@29 ; skolem@Y25@1, cons(skoTy@29 ; skolem@Z27@2, nil(skoTy@29 ; ))))) = some(skoTy@29 ; skolem@X23@0) diff --git a/devtools/test-suite/proofs/tf1_basic_thm.out b/devtools/test-suite/proofs/tf1_basic_thm.out index 39c81f0d..3a5ce077 100644 --- a/devtools/test-suite/proofs/tf1_basic_thm.out +++ b/devtools/test-suite/proofs/tf1_basic_thm.out @@ -1,16 +1,16 @@ -[0] ALPHA_AND : ((! [A14]: ((maybe(A14) ; head(A14;nil(A14;)) = none(A14;)))) & (! [A16 X18 XS20]: ((maybe(A16) ; head(A16;cons(A16;X18, XS20)) = some(A16;X18)))) & ~((maybe($int) ; head($int;cons($int;1, cons($int;2, cons($int;3, nil($int;))))) = some($int;1)))) - -> [1] (! [A14]: ((maybe(A14) ; head(A14;nil(A14;)) = none(A14;)))), (! [A16 X18 XS20]: ((maybe(A16) ; head(A16;cons(A16;X18, XS20)) = some(A16;X18)))), ~((maybe($int) ; head($int;cons($int;1, cons($int;2, cons($int;3, nil($int;))))) = some($int;1))) +[0] ALPHA_AND : (! [A14]: head(A14 ; nil(A14 ; )) = none(A14 ; )) & (! [A16, X18, XS20]: head(A16 ; cons(A16 ; X18, XS20)) = some(A16 ; X18)) & ~(head($int ; cons($int ; 1, cons($int ; 2, cons($int ; 3, nil($int ; ))))) = some($int ; 1)) + -> [1] ! [A14]: head(A14 ; nil(A14 ; )) = none(A14 ; ), ! [A16, X18, XS20]: head(A16 ; cons(A16 ; X18, XS20)) = some(A16 ; X18), ~(head($int ; cons($int ; 1, cons($int ; 2, cons($int ; 3, nil($int ; ))))) = some($int ; 1)) -[1] GAMMA_FORALL : (! [A14]: ((maybe(A14) ; head(A14;nil(A14;)) = none(A14;)))) - -> [2] (maybe(A14_1) ; head(A14_1;nil(A14_1;)) = none(A14_1;)) +[1] GAMMA_FORALL : ! [A14]: head(A14 ; nil(A14 ; )) = none(A14 ; ) + -> [2] head(A14 ; nil(A14 ; )) = none(A14 ; ) -[2] GAMMA_FORALL : (! [A16 X18 XS20]: ((maybe(A16) ; head(A16;cons(A16;X18, XS20)) = some(A16;X18)))) - -> [3] (! [X18 XS20]: ((maybe($int) ; head($int;cons($int;X18, XS20)) = some($int;X18)))) +[2] GAMMA_FORALL : ! [A16, X18, XS20]: head(A16 ; cons(A16 ; X18, XS20)) = some(A16 ; X18) + -> [3] ! [X18, XS20]: head($int ; cons($int ; X18, XS20)) = some($int ; X18) -[3] GAMMA_FORALL : (! [X18 XS20]: ((maybe($int) ; head($int;cons($int;X18, XS20)) = some($int;X18)))) - -> [4] (! [XS20]: ((maybe($int) ; head($int;cons($int;1, XS20)) = some($int;1)))) +[3] GAMMA_FORALL : ! [X18, XS20]: head($int ; cons($int ; X18, XS20)) = some($int ; X18) + -> [4] ! [XS20]: head($int ; cons($int ; 1, XS20)) = some($int ; 1) -[4] GAMMA_FORALL : (! [XS20]: ((maybe($int) ; head($int;cons($int;1, XS20)) = some($int;1)))) - -> [5] (maybe($int) ; head($int;cons($int;1, cons($int;2, cons($int;3, nil($int;))))) = some($int;1)) +[4] GAMMA_FORALL : ! [XS20]: head($int ; cons($int ; 1, XS20)) = some($int ; 1) + -> [5] head($int ; cons($int ; 1, cons($int ; 2, cons($int ; 3, nil($int ; ))))) = some($int ; 1) -[5] CLOSURE : (maybe($int) ; head($int;cons($int;1, cons($int;2, cons($int;3, nil($int;))))) = some($int;1)) +[5] CLOSURE : head($int ; cons($int ; 1, cons($int ; 2, cons($int ; 3, nil($int ; ))))) = some($int ; 1) diff --git a/shell.nix b/shell.nix index 121645eb..97d4cf1a 100644 --- a/shell.nix +++ b/shell.nix @@ -7,6 +7,7 @@ pkgs.mkShell { gotools python314 rocq-core + rocqPackages.stdlib ocamlPackages.lambdapi ]; } diff --git a/src/Core/Sko/interface.go b/src/Core/Sko/interface.go index b94c1d5f..8ef14586 100644 --- a/src/Core/Sko/interface.go +++ b/src/Core/Sko/interface.go @@ -62,7 +62,7 @@ type Skolemization interface { */ func genFreshSymbol(existingSymbols *Lib.Set[AST.Id], x AST.TypedVar) AST.Id { symbol := AST.MakerNewId( - fmt.Sprintf("skolem@%v", x.GetName()), + fmt.Sprintf("skolem@%v@%d", x.GetName(), existingSymbols.Cardinal()), ) *existingSymbols = existingSymbols.Add(symbol) diff --git a/src/Core/skolemisation.go b/src/Core/skolemisation.go index 66238d50..e8947805 100644 --- a/src/Core/skolemisation.go +++ b/src/Core/skolemisation.go @@ -32,6 +32,7 @@ package Core import ( + "fmt" "github.com/GoelandProver/Goeland/AST" "github.com/GoelandProver/Goeland/Core/Sko" "github.com/GoelandProver/Goeland/Glob" @@ -128,6 +129,7 @@ func realSkolemize( if AST.IsTType(x.GetTy()) { id := AST.MakerId("skoTy") + id = AST.MakerId(fmt.Sprintf("skoTy@%d", id.GetIndex())) res = deltaForm.SubstTy(x.ToTyBoundVar(), AST.MkTyConst(id.ToString())) } else { selectedSkolemization, res = selectedSkolemization.Skolemize( From 6d8ef733a99523f4242e9f0763232d661eb4e50f Mon Sep 17 00:00:00 2001 From: Johann Rosain Date: Tue, 29 Jul 2025 15:14:31 +0200 Subject: [PATCH 15/30] Add rocq installation in GitHub test-suite workflow --- .github/workflows/full-ci.yml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/full-ci.yml b/.github/workflows/full-ci.yml index 111b1a24..018987fb 100644 --- a/.github/workflows/full-ci.yml +++ b/.github/workflows/full-ci.yml @@ -86,9 +86,19 @@ jobs: - uses: actions/checkout@v5 with: ref: ${{ github.event.pull_request.head.sha }} + - uses: cachix/install-nix-action@v31 + with: + nix_path: nixpkgs=channel:nixos-unstable - uses: actions/setup-go@v3 with: go-version: ${{ env.goVersion }} - run: go install golang.org/x/tools/cmd/goyacc@latest - run: cd src && make - - run: cd devtools && make test-suite + - uses: rrbutani/use-nix-shell-action@v1 + with: + file: shell.nix + script: | + cd devtools + make test-suite + + From 84463130104567b1ea16d8e6b839f3cb38147280 Mon Sep 17 00:00:00 2001 From: Johann Rosain Date: Sun, 5 Oct 2025 18:28:51 +0200 Subject: [PATCH 16/30] Add: proof-certification folder with instructions on how to certify proofs with Goeland --- .gitignore | 2 ++ .../LambdaPi}/CCC.lp | 0 .../LambdaPi}/FOL.lp | 0 .../LambdaPi}/GS3.lp | 0 .../LambdaPi}/ICC.lp | 0 .../LambdaPi}/LL.lp | 0 .../LambdaPi}/LL_ND.lp | 0 proof-certification/LambdaPi/Makefile | 20 +++++++++++++++++++ .../LambdaPi}/ND.lp | 0 .../LambdaPi}/ND_eps.lp | 0 .../LambdaPi}/ND_eps_aux.lp | 0 .../LambdaPi}/ND_eps_full.lp | 0 proof-certification/LambdaPi/README.md | 12 +++++++++++ .../LambdaPi}/lambdapi.pkg | 0 proof-certification/README.md | 5 +++++ 15 files changed, 39 insertions(+) rename {LambdaPi => proof-certification/LambdaPi}/CCC.lp (100%) rename {LambdaPi => proof-certification/LambdaPi}/FOL.lp (100%) rename {LambdaPi => proof-certification/LambdaPi}/GS3.lp (100%) rename {LambdaPi => proof-certification/LambdaPi}/ICC.lp (100%) rename {LambdaPi => proof-certification/LambdaPi}/LL.lp (100%) rename {LambdaPi => proof-certification/LambdaPi}/LL_ND.lp (100%) create mode 100644 proof-certification/LambdaPi/Makefile rename {LambdaPi => proof-certification/LambdaPi}/ND.lp (100%) rename {LambdaPi => proof-certification/LambdaPi}/ND_eps.lp (100%) rename {LambdaPi => proof-certification/LambdaPi}/ND_eps_aux.lp (100%) rename {LambdaPi => proof-certification/LambdaPi}/ND_eps_full.lp (100%) create mode 100644 proof-certification/LambdaPi/README.md rename {LambdaPi => proof-certification/LambdaPi}/lambdapi.pkg (100%) create mode 100644 proof-certification/README.md diff --git a/.gitignore b/.gitignore index c1a48f56..9671578e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +*.lpo + .direnv [Pp]roblems [Oo]utput diff --git a/LambdaPi/CCC.lp b/proof-certification/LambdaPi/CCC.lp similarity index 100% rename from LambdaPi/CCC.lp rename to proof-certification/LambdaPi/CCC.lp diff --git a/LambdaPi/FOL.lp b/proof-certification/LambdaPi/FOL.lp similarity index 100% rename from LambdaPi/FOL.lp rename to proof-certification/LambdaPi/FOL.lp diff --git a/LambdaPi/GS3.lp b/proof-certification/LambdaPi/GS3.lp similarity index 100% rename from LambdaPi/GS3.lp rename to proof-certification/LambdaPi/GS3.lp diff --git a/LambdaPi/ICC.lp b/proof-certification/LambdaPi/ICC.lp similarity index 100% rename from LambdaPi/ICC.lp rename to proof-certification/LambdaPi/ICC.lp diff --git a/LambdaPi/LL.lp b/proof-certification/LambdaPi/LL.lp similarity index 100% rename from LambdaPi/LL.lp rename to proof-certification/LambdaPi/LL.lp diff --git a/LambdaPi/LL_ND.lp b/proof-certification/LambdaPi/LL_ND.lp similarity index 100% rename from LambdaPi/LL_ND.lp rename to proof-certification/LambdaPi/LL_ND.lp diff --git a/proof-certification/LambdaPi/Makefile b/proof-certification/LambdaPi/Makefile new file mode 100644 index 00000000..4a6ba9f7 --- /dev/null +++ b/proof-certification/LambdaPi/Makefile @@ -0,0 +1,20 @@ +.POSIX: +SRC = +OBJ = $(SRC:.lp=.lpo) +.SUFFIXES: + +all: $(OBJ) + +install: $(OBJ) lambdapi.pkg + lambdapi install lambdapi.pkg $(OBJ) $(SRC) + +uninstall: + lambdapi uninstall lambdapi.pkg + +clean: + rm -f $(OBJ) + +.SUFFIXES: .lp .lpo + +.lp.lpo: + lambdapi check --gen-obj $< diff --git a/LambdaPi/ND.lp b/proof-certification/LambdaPi/ND.lp similarity index 100% rename from LambdaPi/ND.lp rename to proof-certification/LambdaPi/ND.lp diff --git a/LambdaPi/ND_eps.lp b/proof-certification/LambdaPi/ND_eps.lp similarity index 100% rename from LambdaPi/ND_eps.lp rename to proof-certification/LambdaPi/ND_eps.lp diff --git a/LambdaPi/ND_eps_aux.lp b/proof-certification/LambdaPi/ND_eps_aux.lp similarity index 100% rename from LambdaPi/ND_eps_aux.lp rename to proof-certification/LambdaPi/ND_eps_aux.lp diff --git a/LambdaPi/ND_eps_full.lp b/proof-certification/LambdaPi/ND_eps_full.lp similarity index 100% rename from LambdaPi/ND_eps_full.lp rename to proof-certification/LambdaPi/ND_eps_full.lp diff --git a/proof-certification/LambdaPi/README.md b/proof-certification/LambdaPi/README.md new file mode 100644 index 00000000..1caa76e3 --- /dev/null +++ b/proof-certification/LambdaPi/README.md @@ -0,0 +1,12 @@ +# Proof Certification Using Goéland+LambdaPi + +To output a LambdaPi proof of a problem file `problem.p`, use the `-olp` option: +``` +./_build/goeland -olp problem.p +``` + +Assuming you are at the root of your local clone of this GitHub repo, checking this file +can be done using the following command: +``` +lambdapi check --lib-root . --map-dir Logic.Goeland:proof-certification/LambdaPi problem.lp +``` diff --git a/LambdaPi/lambdapi.pkg b/proof-certification/LambdaPi/lambdapi.pkg similarity index 100% rename from LambdaPi/lambdapi.pkg rename to proof-certification/LambdaPi/lambdapi.pkg diff --git a/proof-certification/README.md b/proof-certification/README.md new file mode 100644 index 00000000..a851dab1 --- /dev/null +++ b/proof-certification/README.md @@ -0,0 +1,5 @@ +# Proof Certification + +This directory contains all the files that are necessary for Goéland to translate its +proof in different languages. We provide a small documentation of their usage: +* for LambdaPi, see [this file](LambdaPi/README.md) From f5f429bf558381c35f2a15ee53f56d9e6b66ee53 Mon Sep 17 00:00:00 2001 From: Johann Rosain Date: Sun, 5 Oct 2025 18:29:15 +0200 Subject: [PATCH 17/30] Add: use lambdapi to check the test-suite --- devtools/run-test-suite.py | 109 ++++++++++++++++++++++--------------- 1 file changed, 66 insertions(+), 43 deletions(-) diff --git a/devtools/run-test-suite.py b/devtools/run-test-suite.py index a280e565..a3383f16 100644 --- a/devtools/run-test-suite.py +++ b/devtools/run-test-suite.py @@ -13,7 +13,7 @@ class Parser: RES = "% result: " ENV = "% env: " EXIT_CODE = "% exit: " - no_rocq_check = False + no_check = False def __init__(self, filename): self.filename = filename @@ -24,7 +24,7 @@ def __init__(self, filename): args_avoid_chk = ["-proof", "-otptp", "-osctptp"] if "no_chk" in filename or self.expectedExitCode != "" or any(arg in self.arguments for arg in args_avoid_chk) or self.expectedResult == "NOT VALID": - self.no_rocq_check = True + self.no_check = True def parseGen(self, pat): with open(self.filename) as f: @@ -48,23 +48,20 @@ def parseEnv(self): def parseExitCode(self): self.expectedExitCode = self.parseGen(self.EXIT_CODE).strip() - def getCommandLine(self): - arguments = self.arguments - if not self.no_rocq_check: - arguments += " -context -orocq" + def getCommandLine(self, checker_args): + arguments = self.arguments + checker_args return self.env + " ../src/_build/goeland " + arguments + " " + self.filename def getArgsForPrinting(self): - rocq_chk_str = "" - if self.no_rocq_check: - rocq_chk_str = " (no Rocq check)" - return self.arguments + rocq_chk_str + chk_str = "" + if self.no_check: + chk_str = " (no check)" + return self.arguments + chk_str def sanitize(s): return s.encode('utf-8', errors='ignore').decode(errors='ignore') def runProver(f, command): - print(f"{f}\t{parser.getArgsForPrinting()}") result = run(command, stdout=PIPE, stderr=PIPE, universal_newlines=True, shell=True, encoding='utf-8') return (sanitize(result.stdout), sanitize(result.stderr), result.returncode) @@ -87,6 +84,28 @@ def getRelevantOutput(output): def isExecutable(prog) : return shutil.which(prog) is not None +def makeGenericCheck(command, extension, cleanup_always, cleanup_compile_success, f, output): + check_lines = getRelevantOutput(output) + check_success = False + filename = os.getcwd() + "/" + os.path.basename(f)[:-2].replace("-", "_") + + with open(f"{filename}.{extension}", "w") as chk_file: + chk_file.write("\n".join(check_lines)) + + result = run(f"{command} {filename}.{extension}", stdout=PIPE, stderr=PIPE, universal_newlines=True, shell=True, encoding='utf-8') + check_success = result.returncode == 0 + + for ext in cleanup_always: + os.remove(f"{filename}.{ext}") + + if not check_success: + return False, result.stderr + else: + for ext in cleanup_compile_success: + os.remove(f"{filename}.{ext}") + + return True, None + def getRocqCompiler() : if isExecutable("rocq"): return "rocq compile" @@ -96,35 +115,29 @@ def getRocqCompiler() : raise Exception("No Rocq executable found on the system") def makeRocqCheck(f, output): - rocq = getRocqCompiler() - rocq_lines = getRelevantOutput(output) - compile_success = False - filename = os.getcwd() + "/" + os.path.basename(f)[:-2].replace("-", "_") - with open(f"{filename}.v", "w") as tmp: - tmp.write("\n".join(rocq_lines)) + check_status, err = makeGenericCheck(getRocqCompiler(), "v", ["glob"], ["v", "vo", "vok", "vos"], f, output) - result = run(f"{rocq} {filename}.v", stdout=PIPE, stderr=PIPE, universal_newlines=True, shell=True, encoding='utf-8') - compile_success = result.returncode == 0 + if not check_status: + print(f"ROCQ check has failed.") + print(f"Reason: {err}") + exit(1) - try: - os.remove(f"{filename}.glob") - except FileNotFoundError: - pass +def makeLambdapiCheck(f, output): + lp_command = "lambdapi check --lib-root .. --map-dir Logic.Goeland:../proof-certification/LambdaPi" + check_status, err = makeGenericCheck(lp_command, "lp", [], ["lp"], f, output) - if not compile_success: - print(f"ROCQ compile has failed.") - print(f"Reason: {result.stderr}") - exit(1) - else: - try: - os.remove(f"{filename}.v") - os.remove(f"{filename}.vo") - os.remove(f"{filename}.vok") - os.remove(f"{filename}.vos") - except FileNotFoundError: - pass - -def runWithExpected(f, parser): + # As the lambdapi output does not manage equality, we tolerate fails for the problems + # of the test suite that have equality. + lp_tolerated_fails = ["TEST_EQ.p", "TEST_EQ2.p", "sankalp.p"] + + if not check_status: + if os.path.basename(f) in lp_tolerated_fails: + print(f"LAMBDAPI check has failed, but it was expected.") + else: + print(f"LAMBDAPI check has failed") + exit(1) + +def runWithExpected(f, parser, checker_args, check_fun): """ Runs Goéland on [f] using the parsed command line, then checks if the output corresponds to the expected one. This function manages: @@ -132,9 +145,10 @@ def runWithExpected(f, parser): - results (e.g., VALID, NOT VALID). If Goéland runs into an unexpected error, we report it. Moreover, if the kind of expected return is a VALID - result, we run Rocq to check that the proof is indeed valid (except for files in the no-chk folder). + result, we run a checker (specified by checker_args and check_fun) to check that the proof is indeed valid + (except for files in the no-chk folder). """ - output, err, exit_code = runProver(f, parser.getCommandLine()) + output, err, exit_code = runProver(f, parser.getCommandLine("")) if err != "": print(f"Runtime error: {err}") @@ -155,15 +169,22 @@ def runWithExpected(f, parser): print(f"Error: expected '{parser.expectedResult}', got: '{actual}'") exit(1) else: - if parser.no_rocq_check: return - makeRocqCheck(f, output) + if parser.no_check: return + output, _, _ = runProver(f, parser.getCommandLine(checker_args)) + check_fun(f, output) return print(f"Unknown error: got\n{output}") exit(1) +def runWithRocqChk(f, parser): + runWithExpected(f, parser, " -context -orocq", makeRocqCheck) + +def runWithLpChk(f, parser): + runWithExpected(f, parser, " -olp", makeLambdapiCheck) + def compareOutputs(f, parser): - output, err, exit_code = runProver(f, parser.getCommandLine()) + output, err, exit_code = runProver(f, parser.getCommandLine("")) if err != "" or exit_code != 0: print(f"Runtime error: {err}") @@ -195,4 +216,6 @@ def compareOutputs(f, parser): if any(out in parser.arguments for out in outputTest) : compareOutputs(f, parser) else : - runWithExpected(f, parser) + print(f"{f}\t{parser.getArgsForPrinting()}") + runWithRocqChk(f, parser) + runWithLpChk(f, parser) From 720be91547a8db1d8902f66a1ce5362cdfb0c278 Mon Sep 17 00:00:00 2001 From: Johann Rosain Date: Sun, 5 Oct 2025 18:29:43 +0200 Subject: [PATCH 18/30] Fix: use new printer system to have a valid lambdapi output --- proof-certification/LambdaPi/Makefile | 2 +- src/AST/formsDef.go | 19 +- src/AST/modular-printing.go | 42 +- src/AST/printers.go | 6 + src/AST/quantifiers.go | 4 +- src/AST/termsDef.go | 7 +- src/Mods/CertifUtils/context.go | 128 +++++ src/Mods/CertifUtils/sanitizer.go | 49 ++ src/Mods/CertifUtils/utils.go | 50 ++ src/Mods/gs3/proof.go | 2 +- src/Mods/gs3/sequent.go | 3 +- src/Mods/lambdapi/context.go | 214 +------- .../lambdapi/{utils.go => local_context.go} | 79 ++- src/Mods/lambdapi/output.go | 143 ++++-- src/Mods/lambdapi/proof.go | 473 +++++++++--------- src/Mods/rocq/context.go | 84 +--- src/Mods/rocq/output.go | 1 + src/Mods/rocq/proof.go | 20 +- src/main.go | 2 + 19 files changed, 686 insertions(+), 642 deletions(-) create mode 100644 src/Mods/CertifUtils/context.go create mode 100644 src/Mods/CertifUtils/sanitizer.go create mode 100644 src/Mods/CertifUtils/utils.go rename src/Mods/lambdapi/{utils.go => local_context.go} (50%) diff --git a/proof-certification/LambdaPi/Makefile b/proof-certification/LambdaPi/Makefile index 4a6ba9f7..0aa80a08 100644 --- a/proof-certification/LambdaPi/Makefile +++ b/proof-certification/LambdaPi/Makefile @@ -1,5 +1,5 @@ .POSIX: -SRC = +SRC = CCC.lp FOL.lp GS3.lp ICC.lp LL.lp LL_ND.lp ND_eps_aux.lp ND_eps_full.lp ND_eps.lp ND.lp OBJ = $(SRC:.lp=.lpo) .SUFFIXES: diff --git a/src/AST/formsDef.go b/src/AST/formsDef.go index 412d633f..15894989 100644 --- a/src/AST/formsDef.go +++ b/src/AST/formsDef.go @@ -467,11 +467,11 @@ func (e Equ) GetMetas() Lib.Set[Meta] { } func (e Equ) ToString() string { - return fmt.Sprintf("%s %s %s", + return printer.Str(fmt.Sprintf("%s %s %s", printer.Str(printer.SurroundChild(e.f1.ToString())), printer.StrConn(ConnEqu), printer.Str(printer.SurroundChild(e.f2.ToString())), - ) + )) } func (e Equ) Equals(f any) bool { @@ -579,11 +579,11 @@ func (i Imp) GetMetas() Lib.Set[Meta] { } func (i Imp) ToString() string { - return fmt.Sprintf("%s %s %s", + return printer.Str(fmt.Sprintf("%s %s %s", printer.Str(printer.SurroundChild(i.f1.ToString())), printer.StrConn(ConnImp), printer.Str(printer.SurroundChild(i.f2.ToString())), - ) + )) } func (i Imp) Equals(other any) bool { @@ -704,10 +704,10 @@ func (n Not) Copy() Form { } func (n Not) ToString() string { - return fmt.Sprintf("%s%s", + return printer.Str(fmt.Sprintf("%s%s", printer.StrConn(ConnNot), printer.Str(printer.SurroundChild(n.f.ToString())), - ) + )) } func (n Not) ReplaceTermByTerm(old Term, new Term) (Form, bool) { @@ -845,11 +845,10 @@ func (p Pred) GetArgs() Lib.List[Term] { return p.args } func (p Pred) RenameVariables() Form { return p } func (p Pred) ToString() string { - return printer.OnFunctionalArgs( + return printer.StrFunctional( p.id, - Lib.ListToString(p.tys, printer.StrConn(SepTyArgs), ""), - printer.StrConn(SepArgsTyArgs), - p.args, + Lib.ListMap(p.tys, Ty.ToString), + Lib.ListMap(p.args, Term.ToString), ) } diff --git a/src/AST/modular-printing.go b/src/AST/modular-printing.go index a901bc16..97d886e5 100644 --- a/src/AST/modular-printing.go +++ b/src/AST/modular-printing.go @@ -53,6 +53,7 @@ package AST import ( "fmt" + "strings" "unicode" "unicode/utf8" @@ -63,12 +64,13 @@ import ( var printer_debug Glob.Debugger type PrinterAction struct { - genericAction func(string) string // Always executed - actionOnId func(Id) string - actionOnBoundVar func(string, int) string - actionOnMeta func(string, int) string - actionOnType func(string) string - actionOnTypedVar func(Lib.Pair[string, Ty]) string + genericAction func(string) string // Always executed + actionOnId func(Id) string + actionOnBoundVar func(string, int) string + actionOnMeta func(string, int) string + actionOnType func(string) string + actionOnTypedVar func(Lib.Pair[string, Ty]) string + actionOnFunctional func(id Id, tys Lib.List[string], args Lib.List[string]) string } func (p PrinterAction) Compose(oth PrinterAction) PrinterAction { @@ -87,6 +89,9 @@ func (p PrinterAction) Compose(oth PrinterAction) PrinterAction { actionOnTypedVar: func(pair Lib.Pair[string, Ty]) string { return oth.actionOnTypedVar(Lib.MkPair(p.actionOnTypedVar(pair), pair.Snd)) }, + actionOnFunctional: func(id Id, tys Lib.List[string], args Lib.List[string]) string { + return p.actionOnFunctional(id, tys, args) // we can't compose that + }, } } @@ -114,6 +119,10 @@ func (p PrinterAction) StrTyVar(pair Lib.Pair[string, Ty]) string { return p.Str(p.actionOnTypedVar(pair)) } +func (p PrinterAction) StrFunctional(i Id, tys, args Lib.List[string]) string { + return p.Str(p.actionOnFunctional(i, tys, args)) +} + func PrinterIdentity(x string) string { return x } func PrinterIdentityPair[T any](p Lib.Pair[string, T]) string { return p.Fst } func PrinterIdentity2[T any](s string, _ T) string { return s } @@ -125,8 +134,9 @@ func MkPrinterAction( actionOnMeta func(string, int) string, actionOnType func(string) string, actionOnTypedVar func(Lib.Pair[string, Ty]) string, + actionOnFunctional func(id Id, tys Lib.List[string], args Lib.List[string]) string, ) PrinterAction { - return PrinterAction{genericAction, actionOnId, actionOnBoundVar, actionOnMeta, actionOnType, actionOnTypedVar} + return PrinterAction{genericAction, actionOnId, actionOnBoundVar, actionOnMeta, actionOnType, actionOnTypedVar, actionOnFunctional} } type Connective int @@ -186,13 +196,11 @@ type Printer struct { *PrinterConnective } -func (p Printer) OnFunctionalArgs(i Id, tys, con string, args Lib.List[Term]) string { - // Hard-coding of the infix functionals. - // It'd maybe be useful to have an [Infix] generic action but I don't see how to do - // that for now. +func (c PrinterConnective) DefaultOnFunctionalArgs(id Id, tys Lib.List[string], args Lib.List[string]) string { infix := Lib.MkListV(Id_eq) - is_infix := Lib.ListMem(i, infix) - arguments := Lib.ListToString(args, p.StrConn(SepArgs), "") + is_infix := Lib.ListMem(id, infix) + types := strings.Join(tys.GetSlice(), c.StrConn(SepTyArgs)) + arguments := strings.Join(args.GetSlice(), c.StrConn(SepArgs)) if is_infix { if args.Len() != 2 { @@ -202,12 +210,12 @@ func (p Printer) OnFunctionalArgs(i Id, tys, con string, args Lib.List[Term]) st arguments, )) } - return fmt.Sprintf("%s %s %s", args.At(0).ToString(), i.ToString(), args.At(1).ToString()) + return fmt.Sprintf("%s %s %s", args.At(0), id.ToString(), args.At(1)) } else { - if len(tys) > 0 { - arguments = tys + con + arguments + if tys.Len() > 0 { + arguments = types + c.StrConn(SepArgsTyArgs) + arguments } - return fmt.Sprintf("%s%s", i.ToString(), p.SurroundArgs(arguments)) + return fmt.Sprintf("%s%s", id.ToString(), c.SurroundArgs(arguments)) } } diff --git a/src/AST/printers.go b/src/AST/printers.go index dffbe26e..c48c4b3f 100644 --- a/src/AST/printers.go +++ b/src/AST/printers.go @@ -75,6 +75,9 @@ func RemoveSuperfluousParenthesesAction(connectives PrinterConnective) PrinterAc actionOnMeta: func(s string, index int) string { return s }, actionOnType: func(s string) string { return s }, actionOnTypedVar: func(p Lib.Pair[string, Ty]) string { return p.Fst }, + actionOnFunctional: func(id Id, tys Lib.List[string], args Lib.List[string]) string { + return connectives.DefaultOnFunctionalArgs(id, tys, args) + }, } } @@ -91,5 +94,8 @@ func SanitizerAction(connectives PrinterConnective, forbidden_chars []string) Pr actionOnMeta: func(s string, index int) string { return s }, actionOnType: func(s string) string { return s }, actionOnTypedVar: func(p Lib.Pair[string, Ty]) string { return p.Fst }, + actionOnFunctional: func(id Id, tys Lib.List[string], args Lib.List[string]) string { + return connectives.DefaultOnFunctionalArgs(id, tys, args) + }, } } diff --git a/src/AST/quantifiers.go b/src/AST/quantifiers.go index 73b9723e..9c0afbb2 100644 --- a/src/AST/quantifiers.go +++ b/src/AST/quantifiers.go @@ -81,7 +81,7 @@ func (q quantifier) GetMetas() Lib.Set[Meta] { } func (q quantifier) ToString() string { - return fmt.Sprintf( + return printer.Str(fmt.Sprintf( "%s %s%s%s", printer.StrConn(q.symbol), printer.SurroundQuantified( @@ -91,7 +91,7 @@ func (q quantifier) ToString() string { ), printer.StrConn(SepVarsForm), printer.Str(q.subForm.ToString()), - ) + )) } func (q quantifier) GetChildFormulas() Lib.List[Form] { diff --git a/src/AST/termsDef.go b/src/AST/termsDef.go index 3e195eee..83994bb6 100644 --- a/src/AST/termsDef.go +++ b/src/AST/termsDef.go @@ -118,11 +118,10 @@ type Fun struct { } func (f Fun) ToString() string { - return printer.OnFunctionalArgs( + return printer.StrFunctional( f.p, - Lib.ListToString(f.tys, printer.StrConn(SepTyArgs), ""), - printer.StrConn(SepArgsTyArgs), - f.args, + Lib.ListMap(f.tys, Ty.ToString), + Lib.ListMap(f.args, Term.ToString), ) } diff --git a/src/Mods/CertifUtils/context.go b/src/Mods/CertifUtils/context.go new file mode 100644 index 00000000..c5322cb7 --- /dev/null +++ b/src/Mods/CertifUtils/context.go @@ -0,0 +1,128 @@ +/** +* Copyright 2022 by the authors (see AUTHORS). +* +* Goéland is an automated theorem prover for first order logic. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +**/ +package CertifUtils + +/** + * This file provides a function that returns the context of a proof (the symbols appearing in it). + **/ + +import ( + "github.com/GoelandProver/Goeland/AST" + "github.com/GoelandProver/Goeland/Glob" + "github.com/GoelandProver/Goeland/Lib" + "github.com/GoelandProver/Goeland/Typing" +) + +type OrderedConPair Lib.Pair[AST.Id, AST.Ty] + +func (p OrderedConPair) Equals(oth any) bool { + if op, is_op := oth.(OrderedConPair); is_op { + return p.Fst.Equals(op.Fst) && p.Snd.Equals(op.Snd) + } + return false +} + +func (p OrderedConPair) Less(oth any) bool { + if op, is_op := oth.(OrderedConPair); is_op { + return p.Fst.Less(op.Fst) + } + return false +} + +func GetContextFromFormula(root AST.Form) Lib.List[Lib.Pair[AST.Id, AST.Ty]] { + out_list := Lib.NewList[Lib.Pair[AST.Id, AST.Ty]]() + for _, p := range getContextFromFormula(root).Elements().GetSlice() { + out_list.Append(Lib.MkPair(p.Fst, p.Snd)) + } + return out_list +} + +func getContextFromFormula(root AST.Form) Lib.Set[OrderedConPair] { + aux := func(children Lib.List[AST.Form]) Lib.Set[OrderedConPair] { + res := Lib.EmptySet[OrderedConPair]() + for _, child := range children.GetSlice() { + res = res.Union(getContextFromFormula(child)) + } + return res + } + + switch nf := root.(type) { + case AST.Top, AST.Bot: + return Lib.EmptySet[OrderedConPair]() + case AST.All, AST.Ex, AST.And, AST.Or, AST.Imp, AST.Equ, AST.Not: + return aux(root.GetChildFormulas()) + case AST.Pred: + res := Lib.EmptySet[OrderedConPair]() + if !nf.GetID().Equals(AST.Id_eq) { + oty := Typing.QueryGlobalEnv(nf.GetID().GetName()) + var ty AST.Ty + switch rty := oty.(type) { + case Lib.Some[AST.Ty]: + ty = rty.Val + case Lib.None[AST.Ty]: + ty = AST.MkDefaultPredType(nf.GetArgs().Len()) + } + + res = res.Add(OrderedConPair(Lib.MkPair(nf.GetID(), ty))) + } + for _, term := range nf.GetArgs().GetSlice() { + res = res.Union(getContextFromTerm(term)) + } + return res + } + Glob.Anomaly("CertifUtils", "Reached an impossible case") + return Lib.EmptySet[OrderedConPair]() +} + +func getContextFromTerm(trm AST.Term) Lib.Set[OrderedConPair] { + fun, isFun := trm.(AST.Fun) + if !isFun { + return Lib.EmptySet[OrderedConPair]() + } + + oty := Typing.QueryGlobalEnv(fun.GetName()) + var ty AST.Ty + + switch rty := oty.(type) { + case Lib.Some[AST.Ty]: + ty = rty.Val + case Lib.None[AST.Ty]: + ty = AST.MkDefaultFunctionType(fun.GetArgs().Len()) + } + + res := Lib.Singleton(OrderedConPair(Lib.MkPair(fun.GetID(), ty))) + for _, term := range fun.GetArgs().GetSlice() { + res = res.Union(getContextFromTerm(term)) + } + + return res +} diff --git a/src/Mods/CertifUtils/sanitizer.go b/src/Mods/CertifUtils/sanitizer.go new file mode 100644 index 00000000..3549646a --- /dev/null +++ b/src/Mods/CertifUtils/sanitizer.go @@ -0,0 +1,49 @@ +/** +* Copyright 2022 by the authors (see AUTHORS). +* +* Goéland is an automated theorem prover for first order logic. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +**/ +package CertifUtils + +/** + * This file provides a function that returns the context of a proof (the symbols appearing in it). + **/ + +import ( + "github.com/GoelandProver/Goeland/Glob" + "strings" +) + +func SanitizedTheoremName() string { + problemName := Glob.GetProblemName() + for _, s := range []string{".", "=", "+", "-"} { + problemName = strings.ReplaceAll(problemName, s, "_") + } + return problemName +} diff --git a/src/Mods/CertifUtils/utils.go b/src/Mods/CertifUtils/utils.go new file mode 100644 index 00000000..3a0726f5 --- /dev/null +++ b/src/Mods/CertifUtils/utils.go @@ -0,0 +1,50 @@ +/** +* Copyright 2022 by the authors (see AUTHORS). +* +* Goéland is an automated theorem prover for first order logic. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +**/ +package CertifUtils + +/** + * This file provides utility functions for proof certification + **/ + +import ( + "github.com/GoelandProver/Goeland/AST" +) + +func IsPredEqual(f AST.Form) bool { + if not, isNot := f.(AST.Not); isNot { + f = not.GetForm() + } + if p, isPred := f.(AST.Pred); isPred { + return p.GetID().Equals(AST.Id_eq) + } + return false +} diff --git a/src/Mods/gs3/proof.go b/src/Mods/gs3/proof.go index bf35faa8..feaee1e3 100644 --- a/src/Mods/gs3/proof.go +++ b/src/Mods/gs3/proof.go @@ -381,7 +381,7 @@ func makeProofStructFrom(f, nf AST.Form, rule Rule) Search.ProofStruct { nf, Lib.NewList[AST.Term]()), ))} - proofStruct.Rule_name = ruleToTableauxString(rule) + proofStruct.Rule_name = rule.ToString() return proofStruct } diff --git a/src/Mods/gs3/sequent.go b/src/Mods/gs3/sequent.go index aa1d3d5c..36b6125b 100644 --- a/src/Mods/gs3/sequent.go +++ b/src/Mods/gs3/sequent.go @@ -249,7 +249,8 @@ func proofStructRuleToGS3Rule(rule string) Rule { } return mapping[rule] } -func ruleToTableauxString(rule Rule) string { + +func (rule Rule) ToString() string { mapping := map[Rule]string{ NNOT: "ALPHA_NOT_NOT", NOR: "ALPHA_NOT_OR", diff --git a/src/Mods/lambdapi/context.go b/src/Mods/lambdapi/context.go index 50102369..25b5c368 100644 --- a/src/Mods/lambdapi/context.go +++ b/src/Mods/lambdapi/context.go @@ -33,11 +33,11 @@ package lambdapi import ( "fmt" - "strings" "github.com/GoelandProver/Goeland/AST" "github.com/GoelandProver/Goeland/Glob" "github.com/GoelandProver/Goeland/Lib" + "github.com/GoelandProver/Goeland/Mods/CertifUtils" "github.com/GoelandProver/Goeland/Mods/dmt" ) @@ -51,7 +51,11 @@ func makeContextIfNeeded(root AST.Form, metaList Lib.List[AST.Meta]) string { } // if AST.EmptyGlobalContext() { - resultString += strings.Join(getContextFromFormula(root), "\n") + "\n" + contextual_symbols := CertifUtils.GetContextFromFormula(root) + for _, p := range contextual_symbols.GetSlice() { + addToGlobalEnv(Lib.MkPair(p.Fst.ToString(), p.Snd)) + resultString += fmt.Sprintf("symbol %s : %s;\n", p.Fst.ToString(), p.Snd.ToString()) + } if metaList.Len() > 0 { resultString += contextualizeMetas(metaList) @@ -66,213 +70,15 @@ func makeContextIfNeeded(root AST.Form, metaList Lib.List[AST.Meta]) string { return resultString } -func getContextAsString(root AST.Form) string { - types, arrows, others := GlobContextPairs() - ids := getIdsFromFormula(root) - - final := types - - for _, arrow := range arrows { - for _, id := range ids { - if id.Fst == arrow.Fst { - found := false - for _, fin := range final { - if fin.Fst == id.Snd { - found = true - } - } - - if !found { - final = append(final, Glob.MakePair(id.Snd, arrow.Snd)) - } - } - } - } - - for _, other := range others { - for _, id := range ids { - if id.Fst == other.Fst { - found := false - for _, fin := range final { - if fin.Fst == id.Snd { - found = true - } - } - - if !found { - final = append(final, Glob.MakePair(id.Snd, other.Snd)) - } - } - } - } - - result := "" - - for _, fin := range final { - result += "symbol " + fin.Fst + " : " + mapDefault(fin.Snd) + ";\n" - } - - return result -} - -func GlobContextPairs() (types, arrows, others []Glob.Pair[string, string]) { - return []Glob.Pair[string, string]{}, []Glob.Pair[string, string]{}, []Glob.Pair[string, string]{} - // context := AST.GetGlobalContext() - // for k, v := range context { - // if k != "=" && k[0] != '$' { - // switch typed := v[0].App.(type) { - // case AST.TypeArrow: - // primitives := typed.GetPrimitives() - // typesStr := "" - - // for i, prim := range primitives { - // if i != len(primitives)-1 { - // typesStr += "τ (" + prim.ToString() + ") → " - // } else { - // typesStr += prim.ToString() - // } - // } - // arrows = append(arrows, Glob.MakePair(k, typesStr)) - // case AST.QuantifiedType: - // primitives := typed.GetPrimitives() - // typesStr := "" - // contextualized := []string{} - - // for i, prim := range primitives { - // if i != len(primitives)-1 { - // switch typedPrim := prim.(type) { - // case AST.TypeVar: - // str := AST.SimpleStringMappable(typedPrim.ToString()) - // symbol := addToContext(&str) - // typesStr += "τ (" + symbol + ") → " - // contextualized = append(contextualized, symbol) - // case AST.TypeHint: - // typesStr += "τ (" + prim.ToString() + ") → " - // } - // } else { - // typesStr += prim.ToString() - // } - // } - // arrows = append(arrows, Glob.MakePair(k, fmt.Sprintf("Π (%s : Type), %s", strings.Join(contextualized, " : Type), ("), typesStr))) - // case AST.TypeHint: - // if k == typed.ToString() { - // types = append(types, Glob.MakePair(k, "Type")) - // } else { - // others = append(others, Glob.MakePair(k, fmt.Sprintf("τ (%s)", typed.ToString()))) - // } - // } - // } - // } - - // return types, arrows, others -} - func contextPreamble() string { return "require open Logic.Goeland.FOL Logic.Goeland.LL Logic.Goeland.ND Logic.Goeland.ND_eps Logic.Goeland.ND_eps_full Logic.Goeland.ND_eps_aux Logic.Goeland.LL_ND Logic.Goeland.GS3;" } -func getContextFromFormula(root AST.Form) []string { - result := []string{} - - switch nf := root.(type) { - case AST.All: - result = getContextFromFormula(nf.GetForm()) - case AST.Ex: - result = getContextFromFormula(nf.GetForm()) - case AST.And: - for _, f := range nf.GetChildFormulas().GetSlice() { - result = append(result, clean(result, getContextFromFormula(f))...) - } - case AST.Or: - for _, f := range nf.GetChildFormulas().GetSlice() { - result = append(result, clean(result, getContextFromFormula(f))...) - } - case AST.Imp: - result = clean(result, getContextFromFormula(nf.GetF1())) - result = append(result, clean(result, getContextFromFormula(nf.GetF2()))...) - case AST.Equ: - result = clean(result, getContextFromFormula(nf.GetF1())) - result = append(result, clean(result, getContextFromFormula(nf.GetF2()))...) - case AST.Not: - result = append(result, getContextFromFormula(nf.GetForm())...) - case AST.Pred: - if !nf.GetID().Equals(AST.Id_eq) { - result = append(result, mapDefault(fmt.Sprintf("symbol %s;", nf.GetID().ToString()))) - } - for _, term := range nf.GetArgs().GetSlice() { - result = append(result, clean(result, getContextFromTerm(term))...) - } - } - return result -} - -func getIdsFromFormula(root AST.Form) []Glob.Pair[string, string] { - result := []Glob.Pair[string, string]{} - - switch nf := root.(type) { - case AST.All: - result = getIdsFromFormula(nf.GetForm()) - case AST.Ex: - result = getIdsFromFormula(nf.GetForm()) - case AST.And: - for _, f := range nf.GetChildFormulas().GetSlice() { - result = append(result, getIdsFromFormula(f)...) - } - case AST.Or: - for _, f := range nf.GetChildFormulas().GetSlice() { - result = append(result, getIdsFromFormula(f)...) - } - case AST.Imp: - result = getIdsFromFormula(nf.GetF1()) - result = append(result, getIdsFromFormula(nf.GetF2())...) - case AST.Equ: - result = getIdsFromFormula(nf.GetF1()) - result = append(result, getIdsFromFormula(nf.GetF2())...) - case AST.Not: - result = getIdsFromFormula(nf.GetForm()) - case AST.Pred: - result = append(result, Glob.MakePair(nf.GetID().GetName(), nf.GetID().ToString())) - for _, f := range nf.GetArgs().GetSlice() { - result = append(result, Glob.MakePair(f.GetName(), f.ToString())) - } - } - return result -} - -func getContextFromTerm(trm AST.Term) []string { - result := []string{} - - if fun, isFun := trm.(AST.Fun); isFun { - result = append(result, mapDefault(fmt.Sprintf("symbol %s;", fun.GetID().ToString()))) - for _, term := range fun.GetArgs().GetSlice() { - result = append(result, clean(result, getContextFromTerm(term))...) - } - } - return result -} - -// Returns everything in add not in set -func clean(set, add []string) []string { - result := []string{} - for _, str := range add { - found := false - for _, s := range set { - if s == str { - found = true - break - } - } - if !found { - result = append(result, str) - } - } - return result -} - func contextualizeMetas(metaList Lib.List[AST.Meta]) string { - result := []string{} + result := "" for _, meta := range metaList.GetSlice() { - result = append(result, meta.ToString()) + addToGlobalEnv(Lib.MkPair(meta.ToString(), meta.GetTy())) + result += fmt.Sprintf("symbol %s : %s;\n", meta.ToString(), meta.GetTy().ToString()) } - return "symbol " + strings.Join(result, " ") + " : τ (ι);" + return result } diff --git a/src/Mods/lambdapi/utils.go b/src/Mods/lambdapi/local_context.go similarity index 50% rename from src/Mods/lambdapi/utils.go rename to src/Mods/lambdapi/local_context.go index 5e6421c8..a6edc97b 100644 --- a/src/Mods/lambdapi/utils.go +++ b/src/Mods/lambdapi/local_context.go @@ -34,60 +34,51 @@ package lambdapi import ( "fmt" + "github.com/GoelandProver/Goeland/AST" "github.com/GoelandProver/Goeland/Glob" + "github.com/GoelandProver/Goeland/Lib" ) -var varCounter int +var global_env Lib.List[Lib.Pair[string, AST.Ty]] = Lib.NewList[Lib.Pair[string, AST.Ty]]() -func getIncreasedCounter() int { - varCounter++ - return varCounter - 1 +func toLocalVar(i int) string { + return fmt.Sprintf("v%d", i) } -var context Glob.Map[Glob.Basic, Glob.String] = *Glob.NewMap[Glob.Basic, Glob.String]() - -func addToContext(key Glob.Basic) string { - if _, ok := context.GetExists(key); !ok { - context.Set(key, Glob.String(fmt.Sprintf("v%v", getIncreasedCounter()))) - } - - return string(context.Get(key)) +func addToLocalContext(form AST.Form, local_con Lib.List[AST.Form]) (string, Lib.List[AST.Form]) { + index := local_con.Len() + local_con.Append(form) + return toLocalVar(index), local_con } -func getFromContext(key Glob.Basic) string { - return string(context.Get(key)) -} +func getFromLocalContext(form AST.Form, local_con Lib.List[AST.Form]) string { + opt_int := Lib.ListIndexOf(form, local_con) -func toLambdaString(element Glob.Basic, str string) string { - return fmt.Sprintf("λ (%s : ϵ (%s))", addToContext(element), str) + switch index := opt_int.(type) { + case Lib.Some[int]: + return toLocalVar(index.Val) + case Lib.None[int]: + debug(Lib.MkLazy(func() string { + return fmt.Sprintf( + "Trying to find %s in local context %s", + form.ToString(), + Lib.ListToString(local_con, ", ", "{}"), + ) + })) + Glob.Anomaly("LambdaPi", "a formula was not found in the local context while translating") + } + return "" } -func toLambdaIntroString(element Glob.Basic, typeStr string) string { - return fmt.Sprintf("λ (%s : τ (%s))", addToContext(element), mapDefault(typeStr)) +func addToGlobalEnv(p Lib.Pair[string, AST.Ty]) { + global_env.Append(p) } -// func toCorrectString(element AST.MappableString) string { -// isNotSkolem := len(element.ToString()) <= 5 || element.ToString()[:6] != "skolem" -// element = decorateForm(element) -// surround := element.ToMappedStringSurround(lambdaPiMapConnectors, false) -// separator, emptyValue := element.ToMappedStringChild(lambdaPiMapConnectors, false) -// children := "" -// if isNotSkolem { -// children = ListToMappedString(element.GetChildrenForMappedString(), separator, emptyValue) -// } -// return fmt.Sprintf(surround, children) -// } - -// func ListToMappedString[T AST.MappableString](children []T, separator, emptyValue string) string { -// strArr := []string{} - -// for _, element := range children { -// strArr = append(strArr, toCorrectString(element)) -// } - -// if len(strArr) == 0 && emptyValue != "" { -// strArr = append(strArr, emptyValue) -// } - -// return strings.Join(strArr, separator) -// } +func searchGlobalEnv(ty AST.Ty) Lib.Option[string] { + for _, p := range global_env.GetSlice() { + if p.Snd.Equals(ty) { + return Lib.MkSome(p.Fst) + } + } + return Lib.MkNone[string]() +} diff --git a/src/Mods/lambdapi/output.go b/src/Mods/lambdapi/output.go index a40a73e8..0f891d6a 100644 --- a/src/Mods/lambdapi/output.go +++ b/src/Mods/lambdapi/output.go @@ -32,6 +32,8 @@ package lambdapi import ( + "fmt" + "regexp" "strings" "github.com/GoelandProver/Goeland/AST" @@ -42,60 +44,141 @@ import ( ) var contextEnabled bool = false - -// var lambdaPiMapConnectors = map[AST.FormulaType]string{ -// AST.AndConn: "∧", -// AST.OrConn: "∨", -// AST.ImpConn: "⇒", -// AST.EquConn: "⇔", -// AST.NotConn: "¬", -// AST.TopType: "⊤", -// AST.BotType: "⊥", -// AST.AllQuant: "∀α", -// AST.ExQuant: "∃α", -// AST.AllTypeQuant: "∀", -// AST.QuantVarOpen: "(", -// AST.QuantVarClose: ")", -// AST.QuantVarSep: " ", -// AST.PredEmpty: "", -// AST.PredTypeVarSep: ") (", -// AST.TypeVarType: "Type", -// } - +var debug Glob.Debugger var LambdapiOutputProofStruct = &Search.OutputProofStruct{ProofOutput: MakeLambdapiOutput, Name: "Lambdapi", Extension: ".lp"} // ---------------------------------------------------------------------------- // Plugin initialisation and main function to call. // Section: init -// Functions: MakeRocqOutput -// Main functions of the rocq module. +// Functions: MakeLambdapiOutput +// Main functions of the lambdapi module. // TODO: // * Write the context for TFF problems +func InitDebugger() { + debug = Glob.CreateDebugger("LambdaPi") +} + func MakeLambdapiOutput(prf []Search.ProofStruct, meta Lib.List[AST.Meta]) string { if len(prf) == 0 { - Glob.PrintError("LambdaPi", "Nothing to output") - return "" + Glob.Fatal("LambdaPi", "Nothing to output") } - // FIXME: set the AST printer to (to be defined soon) LPPrinter + connectives := LambdapiPrinterConnectives() + printer := AST.Printer{PrinterAction: LambdapiPrinterAction(), PrinterConnective: &connectives} + AST.SetPrinter(printer) // Transform tableaux's proof in GS3 proof return MakeLambdaPiProof(gs3.MakeGS3Proof(prf), meta) } +func LambdapiPrinterConnectives() AST.PrinterConnective { + return AST.MkPrinterConnective( + "LambdapiPrinterConnectives", + map[AST.Connective]string{ + AST.ConnAll: "∀α λ", + AST.ConnEx: "∃α λ", + AST.ConnAnd: " ∧ ", + AST.ConnOr: " ∨ ", + AST.ConnImp: "⇒", + AST.ConnEqu: "⇔", + AST.ConnTop: "⊤", + AST.ConnBot: "⊥", + AST.ConnNot: "¬ ", + + AST.ConnPi: "∀", + AST.ConnMap: "→", + AST.ConnProd: "→", + + AST.SepArgs: " ", + AST.SepTyArgs: " ", + AST.SepArgsTyArgs: " ", + AST.SepVarsForm: ", ", + AST.SepTyVars: " ", + AST.SepVarTy: "", + + AST.SurQuantStart: "", + AST.SurQuantEnd: "", + AST.SurFunctionalStart: " ", + AST.SurFunctionalEnd: "", + }, + ) +} + +func LambdapiPrinterAction() AST.PrinterAction { + connectives := LambdapiPrinterConnectives() + + sanitize_type := func(ty_str string) string { + replace := map[string]string{ + "$i": "τ (ι)", + "$o": "Prop", + "$tType": "Type", + // FIXME: define a replacement for every defined stuff + } + for k, v := range replace { + ty_str = strings.ReplaceAll(ty_str, k, v) + } + return ty_str + } + lambdapi_action := AST.MkPrinterAction( + func(s string) string { + reg := regexp.MustCompile("([^∀∃]*)(∀α|∃α) λ ([^,]+), ([^∀∃]*)") + matches := reg.FindAllStringSubmatch(s, -1) + + if len(matches) == 0 { + return s + } + + // Properly format quantifiers: Q λ (X1 : t1), Q λ (X2 : t2), ... instead of + // Q λ (X1 : t1) (X2 : t2) ..., ... + result_string := "" + for _, match := range matches { + result_string += match[1] + quantifier := match[2] + variables := match[3] + ed := match[4] + variables_list := strings.Split(variables, ") (") + for i, variable := range variables_list { + prefix := "(" + suffix := ")" + if i == 0 { + prefix = "" + } + if i == len(variables_list)-1 { + suffix = "" + } + result_string += quantifier + " λ " + prefix + variable + suffix + ", " + } + result_string += ed + } + return result_string + }, + func(i AST.Id) string { return i.GetName() }, + AST.PrinterIdentity2[int], + func(metaName string, index int) string { return fmt.Sprintf("%s_%d", metaName, index) }, + sanitize_type, + func(typed_var Lib.Pair[string, AST.Ty]) string { + return fmt.Sprintf("(%s : %s)", typed_var.Fst, sanitize_type(typed_var.Snd.ToString())) + }, + func(id AST.Id, tys Lib.List[string], args Lib.List[string]) string { + if strings.Contains(id.GetName(), "sko") { + return id.ToString() + } else { + return connectives.DefaultOnFunctionalArgs(id, tys, args) + } + }, + ) + lambdapi_action = lambdapi_action.Compose(AST.SanitizerAction(connectives, []string{"@"})) + return lambdapi_action.Compose(AST.RemoveSuperfluousParenthesesAction(connectives)) +} + var MakeLambdaPiProof = func(proof *gs3.GS3Sequent, meta Lib.List[AST.Meta]) string { contextString := makeContextIfNeeded(proof.GetTargetForm(), meta) proofString := makeLambdaPiProofFromGS3(proof) return contextString + "\n" + proofString } -func mapDefault(str string) string { - result := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(str, "$i", "ι"), "$o", "Prop"), "->", "→"), "*", "→") - return result -} - // Context flag utility function func GetContextEnabled() bool { return contextEnabled diff --git a/src/Mods/lambdapi/proof.go b/src/Mods/lambdapi/proof.go index 9ff8cb05..d8dcc6f1 100644 --- a/src/Mods/lambdapi/proof.go +++ b/src/Mods/lambdapi/proof.go @@ -38,89 +38,99 @@ import ( "github.com/GoelandProver/Goeland/AST" "github.com/GoelandProver/Goeland/Glob" "github.com/GoelandProver/Goeland/Lib" + "github.com/GoelandProver/Goeland/Mods/CertifUtils" "github.com/GoelandProver/Goeland/Mods/gs3" ) func makeLambdaPiProofFromGS3(proof *gs3.GS3Sequent) string { - axioms, conjecture := processMainFormula(proof.GetTargetForm()) - var resultingString string - - resultingString = makeTheorem(axioms, conjecture) - formula := proof.GetTargetForm() - - formulaStr := formula.ToString() - resultingString += fmt.Sprintf("λ (%s : ϵ %s),\n", addToContext(formula), formulaStr) - proofStr := makeProofStep(proof) - resultingString += proofStr - - return resultingString + ";\n" + axioms, conjecture := processMainFormula(formula) + + resulting_string, to_introduce := makeTheorem(axioms, conjecture) + context := Lib.NewList[AST.Form]() + resulting_string += "begin\n " + str, local_context := assume(to_introduce, context) + if to_introduce.Len() != 1 { + proof = proof.Child(0) + } + return resulting_string + str + makeProofStep(proof, local_context) + "end;\n" } -func makeProofStep(proof *gs3.GS3Sequent) string { +func makeProofStep(proof *gs3.GS3Sequent, context Lib.List[AST.Form]) string { var resultingString string switch proof.Rule() { - // Closure. case gs3.AX: - resultingString = closureAxiom(proof) - - // Alpha rules + resultingString = closureAxiom(proof, context) case gs3.NNOT: - resultingString = alphaNotNot(proof) + resultingString = alphaNotNot(proof, context) case gs3.AND: - resultingString = alphaAnd(proof) + resultingString = alphaAnd(proof, context) case gs3.NOR: - resultingString = alphaNotOr(proof) + resultingString = alphaNotOr(proof, context) case gs3.NIMP: - resultingString = alphaNotImp(proof) - - // Beta rules + resultingString = alphaNotImp(proof, context) case gs3.OR: - resultingString = betaOr(proof) + resultingString = betaOr(proof, context) case gs3.NAND: - resultingString = betaNotAnd(proof) + resultingString = betaNotAnd(proof, context) case gs3.IMP: - resultingString = betaImp(proof) + resultingString = betaImp(proof, context) case gs3.EQU: - resultingString = betaEqu(proof) + resultingString = betaEqu(proof, context) case gs3.NEQU: - resultingString = betaNotEqu(proof) - - // Delta rules + resultingString = betaNotEqu(proof, context) case gs3.EX: - resultingString = deltaEx(proof) + resultingString = deltaEx(proof, context) case gs3.NALL: - resultingString = deltaNotAll(proof) - - // Gamma rules + resultingString = deltaNotAll(proof, context) case gs3.ALL: - resultingString = gammaAll(proof) + resultingString = gammaAll(proof, context) case gs3.NEX: - resultingString = gammaNotEx(proof) + resultingString = gammaNotEx(proof, context) + default: + Glob.Fatal("LambdaPi", fmt.Sprintf("Translation of rule %s not implemented yet", proof.Rule().ToString())) + } + + return resultingString +} - // Weakening rule - case gs3.W: - Glob.PrintError("LP", "Trying to do a weakening rule but it's not implemented yet") +func assume(formulas Lib.List[AST.Form], context Lib.List[AST.Form]) (string, Lib.List[AST.Form]) { + resulting_string := " assume" + for _, form := range formulas.GetSlice() { + val, con := addToLocalContext(form, context) + resulting_string += fmt.Sprintf(" %s", val) + context = con } + return resulting_string + ";\n", context +} - return "//" + proof.GetTargetForm().ToString() + "\n" + resultingString +func refine(lemma string, arguments Lib.List[string], in_con string, goals int) string { + arguments_string := strings.Join(arguments.GetSlice(), " ") + goals_string := strings.Repeat("_ ", goals) + return fmt.Sprintf(" refine %s %s %s %s\n", lemma, arguments_string, goals_string, in_con) } -func closureAxiom(proof *gs3.GS3Sequent) string { - target, notTarget := getPosAndNeg(proof.GetTargetForm()) +func closureAxiom(proof *gs3.GS3Sequent, context Lib.List[AST.Form]) string { + if CertifUtils.IsPredEqual(proof.GetTargetForm()) { + Glob.Fatal("LambdaPi", "congruence closure is not implemented yet") + } + target, notTarget := getPosAndNeg(proof.GetTargetForm()) result := "" - switch target.(type) { case AST.Pred: - result = fmt.Sprintf("GS3axiom (%s) (%s) (%s)\n", target.ToString(), getFromContext(target), getFromContext(notTarget)) + result = refine("GS3axiom", Lib.MkListV( + "("+target.ToString()+")", + getFromLocalContext(target, context), + getFromLocalContext(notTarget, context), + ), "", 0) case AST.Top: - result = fmt.Sprintf("GS3ntop (%s)\n", getFromContext(notTarget)) + result = refine("GS3ntop", Lib.MkListV(getFromLocalContext(notTarget, context)), "", 0) case AST.Bot: - result = fmt.Sprintf("GS3bot (%s)\n", getFromContext(target)) + result = refine("GS3bot", Lib.MkListV(getFromLocalContext(target, context)), "", 0) } - return result + return result + ";" } func getPosAndNeg(target AST.Form) (pos, neg AST.Form) { @@ -130,230 +140,228 @@ func getPosAndNeg(target AST.Form) (pos, neg AST.Form) { return target, AST.MakerNot(target) } -func allRules(rule string, target AST.Form, composingForms Lib.List[AST.Form], nexts []*gs3.GS3Sequent, children []Lib.List[AST.Form]) string { - result := rule + "\n" - - for _, composingForm := range composingForms.GetSlice() { - result += "(" + composingForm.ToString() + ")\n" +func refineGenericRule(lemma string, proof *gs3.GS3Sequent, remaining_goals int, context Lib.List[AST.Form]) string { + formulas_list := Lib.NewList[string]() + + // If a term was generated, get its type and place the stuff in the right order: the type of + // the generated term, the formula and then the term. + if gs3.IsGammaRule(proof.Rule()) || gs3.IsDeltaRule(proof.Rule()) { + ty := getTypeOfFirstBoundVar(proof.GetTargetForm()) + formated_child := getFormattedChild(proof.GetTargetForm()) + formulas_list = Lib.MkListV("("+strings.ReplaceAll(ty.ToString(), "τ", "")+")", "("+formated_child+")") + if gs3.IsGammaRule(proof.Rule()) { + // FIXME: use an option type instead of nil + if proof.TermGenerated() != nil { + formulas_list.Append(getFormattedTerm(proof.TermGenerated())) + } else { + // Try to find something in the global env, otherwise: fail + // FIXME: we should also try to find something in the local (term) environment + // (this does not exist yet) + switch term := searchGlobalEnv(ty).(type) { + case Lib.Some[string]: + formulas_list.Append(term.Val) + default: + Glob.Fatal("LambdaPi", fmt.Sprintf( + "no term of type %s available to instantiate the universal formula %s.", + ty.ToString(), + proof.GetTargetForm().ToString(), + )) + } + } + } + } else { + child_formulas := proof.GetTargetForm().GetChildFormulas() + switch f := proof.GetTargetForm().(type) { + case AST.Not: + child_formulas = f.GetForm().GetChildFormulas() + } + for _, form := range child_formulas.GetSlice() { + formulas_list.Append("(" + form.ToString() + ")") + } } - result += getRecursionUnivStr(nexts, children) - - result += fmt.Sprintf("(%s)\n", getFromContext(target)) + result_string := refine(lemma, formulas_list, getFromLocalContext(proof.GetTargetForm(), context), remaining_goals) - return result -} - -func allRulesQuantUniv( - rule string, - target AST.Form, - composingForms Lib.List[AST.Form], - nexts []*gs3.GS3Sequent, - children []Lib.List[AST.Form], - vars Lib.List[AST.TypedVar], - termGen AST.Term, -) string { - - quant := "" - typeStr := "" - // FIXME get printer - // switch target.(type) { - // case AST.Ex: - // quant = AST.ConnAll - // case AST.Not: - // quant = AST.ConnEx - // } - - typeStr = mapDefault(typeStr) - - result := rule + "\n" - result += "(" + typeStr + ")\n" - result += "(%s, " + composingForms.At(0).ToString() + ")\n" - - varStrs := []string{} - for _, singleVar := range vars.GetSlice() { - varStrs = append(varStrs, toLambdaIntroString(singleVar, "")) + if remaining_goals <= 1 { + result_string = result_string[:len(result_string)-1] + ";\n" + assumptions, con := assume(proof.GetResultFormulasOfChild(0), Lib.ListCpy(context)) + if gs3.IsDeltaRule(proof.Rule()) { + assumptions = fmt.Sprintf("assume %s;", getFormattedTerm(proof.TermGenerated())) + assumptions + } + result_string += assumptions + result_string += makeProofStep(proof.Child(0), con) + } else { + for i := 0; i < remaining_goals; i++ { + result_string += "{\n" + assumptions, con := assume(proof.GetResultFormulasOfChild(i), Lib.ListCpy(context)) + result_string += assumptions + result_string += makeProofStep(proof.Child(i), con) + result_string += "}\n" + } + result_string = result_string[:len(result_string)-1] + ";\n" } - result = fmt.Sprintf(result, strings.Join(varStrs, ", "+quant+" ")) - - result += "(" + termGen.ToString() + ")\n" - - result += getRecursionUnivStr(nexts, children) - - result += fmt.Sprintf("(%s)\n", getFromContext(target)) - - return result + return result_string } -func getRecursionUnivStr(nexts []*gs3.GS3Sequent, children []Lib.List[AST.Form]) (result string) { - for i, next := range nexts { - result += "(\n" - for _, childForm := range children[i].GetSlice() { - result += toLambdaString(childForm, childForm.ToString()) + ",\n" +func getFormattedTerm(term AST.Term) string { + switch t := term.(type) { + case AST.Fun: + if strings.Contains(t.GetName(), "sko") { + return t.GetID().ToString() } - proofStr := makeProofStep(next) - result += proofStr - result += ")\n" } - return result + return term.ToString() } -func allRulesQuantExist( - rule string, - target AST.Form, - composingForms Lib.List[AST.Form], - nexts []*gs3.GS3Sequent, - children []Lib.List[AST.Form], - vars Lib.List[AST.TypedVar], - termGen AST.Term, -) string { - quant := "" - typeStr := "" - // FIXME get printer - // switch target.(type) { - // case AST.Ex: - // quant = AST.ConnAll - // case AST.Not: - // quant = AST.ConnEx - // } - - typeStr = mapDefault(typeStr) - - result := rule + "\n" - result += "(" + typeStr + ")\n" - result += "(%s, " + composingForms.At(0).ToString() + ")\n" - - varStrs := []string{} - for _, singleVar := range vars.GetSlice() { - varStrs = append(varStrs, toLambdaIntroString(singleVar, "")) +func getTypeOfFirstBoundVar(form AST.Form) AST.Ty { + getTySafe := func(var_list Lib.List[AST.TypedVar]) AST.Ty { + if var_list.Empty() { + debug(Lib.MkLazy(func() string { + return fmt.Sprintf( + "Formula %s has no bound variable, cannot get its type", + form.ToString(), + ) + })) + Glob.Anomaly("LambdaPi", "No bound variable.") + } + return var_list.At(0).GetTy() } - result = fmt.Sprintf(result, strings.Join(varStrs, ", "+quant+" ")) - - result += getRecursionExistStr(nexts, children, termGen) - result += fmt.Sprintf("(%s)\n", getFromContext(target)) + switch f := form.(type) { + case AST.Not: + switch nf := f.GetForm().(type) { + case AST.All: + return getTySafe(nf.GetVarList()) + case AST.Ex: + return getTySafe(nf.GetVarList()) + } + case AST.All: + return getTySafe(f.GetVarList()) + case AST.Ex: + return getTySafe(f.GetVarList()) + } - return result + debug(Lib.MkLazy(func() string { + return fmt.Sprintf( + "Called getTypeOfFirstBoundVar of %s which should have been a quantified formula (or a negation of such a formula)", + form.ToString(), + ) + })) + Glob.Anomaly("LambdaPi", "Not a quantifier formula") + return nil } -func getRecursionExistStr(nexts []*gs3.GS3Sequent, children []Lib.List[AST.Form], termGen AST.Term) (result string) { - for i, next := range nexts { - result += "(\n" - typesStr := "" - if _, ok := termGen.(AST.Fun); ok { - typesStr = mapDefault("") - } - result += toLambdaIntroString(termGen, typesStr) + ",\n" - for _, childForm := range children[i].GetSlice() { - result += toLambdaString(childForm, childForm.ToString()) + ",\n" +// Gets the child formula as a λ (bound_var : ty), P +func getFormattedChild(form AST.Form) string { + format := func(var_list Lib.List[AST.TypedVar], f AST.Form, maker func(Lib.List[AST.TypedVar], AST.Form) AST.Form) string { + f = maker(var_list.Slice(1, var_list.Len()), f) + return fmt.Sprintf( + "λ (%s : %s), %s", + var_list.At(0).GetName(), + var_list.At(0).GetTy().ToString(), + f.ToString(), + ) + } + + switch f := form.(type) { + case AST.Not: + switch nf := f.GetForm().(type) { + case AST.All: + return format(nf.GetVarList(), nf.GetForm(), func(vl Lib.List[AST.TypedVar], f AST.Form) AST.Form { + if !vl.Empty() { + f = AST.MakerAll(vl, f) + } + return f + }) + case AST.Ex: + return format(nf.GetVarList(), nf.GetForm(), func(vl Lib.List[AST.TypedVar], f AST.Form) AST.Form { + if !vl.Empty() { + f = AST.MakerEx(vl, f) + } + return f + }) } - proofStr := makeProofStep(next) - result += proofStr - result += ")\n" + case AST.All: + return format(f.GetVarList(), f.GetForm(), func(vl Lib.List[AST.TypedVar], f AST.Form) AST.Form { + if !vl.Empty() { + f = AST.MakerAll(vl, f) + } + return f + }) + case AST.Ex: + return format(f.GetVarList(), f.GetForm(), func(vl Lib.List[AST.TypedVar], f AST.Form) AST.Form { + if !vl.Empty() { + f = AST.MakerEx(vl, f) + } + return f + }) } - return result -} -func alphaNotNot(proof *gs3.GS3Sequent) string { - composingForms := proof.GetTargetForm().GetChildFormulas().At(0).GetChildFormulas() - return allRules("GS3nnot", proof.GetTargetForm(), composingForms, proof.Children(), proof.GetResultFormulasOfChildren()) + Glob.Anomaly("LambdaPi", "Not a quantifier formula") + return "" } -func alphaAnd(proof *gs3.GS3Sequent) string { - return allRules("GS3and", proof.GetTargetForm(), proof.GetTargetForm().GetChildFormulas(), proof.Children(), proof.GetResultFormulasOfChildren()) +func refineUnaryRule(lemma string, proof *gs3.GS3Sequent, context Lib.List[AST.Form]) string { + return refineGenericRule(lemma, proof, 1, context) } -func alphaNotOr(proof *gs3.GS3Sequent) string { - composingForms := proof.GetTargetForm().GetChildFormulas().At(0).GetChildFormulas() - return allRules("GS3nor", proof.GetTargetForm(), composingForms, proof.Children(), proof.GetResultFormulasOfChildren()) +func refineBinaryRule(lemma string, proof *gs3.GS3Sequent, context Lib.List[AST.Form]) string { + return refineGenericRule(lemma, proof, 2, context) } -func alphaNotImp(proof *gs3.GS3Sequent) string { - composingForms := proof.GetTargetForm().GetChildFormulas().At(0).GetChildFormulas() - return allRules("GS3nimp", proof.GetTargetForm(), composingForms, proof.Children(), proof.GetResultFormulasOfChildren()) +func alphaNotNot(proof *gs3.GS3Sequent, context Lib.List[AST.Form]) string { + return refineUnaryRule("GS3nnot", proof, context) } -func betaOr(proof *gs3.GS3Sequent) string { - return allRules("GS3or", proof.GetTargetForm(), proof.GetTargetForm().GetChildFormulas(), proof.Children(), proof.GetResultFormulasOfChildren()) +func alphaAnd(proof *gs3.GS3Sequent, context Lib.List[AST.Form]) string { + return refineUnaryRule("GS3and", proof, context) } -func betaNotAnd(proof *gs3.GS3Sequent) string { - composingForms := proof.GetTargetForm().GetChildFormulas().At(0).GetChildFormulas() - return allRules("GS3nand", proof.GetTargetForm(), composingForms, proof.Children(), proof.GetResultFormulasOfChildren()) +func alphaNotOr(proof *gs3.GS3Sequent, context Lib.List[AST.Form]) string { + return refineUnaryRule("GS3nor", proof, context) } -func betaImp(proof *gs3.GS3Sequent) string { - return allRules("GS3imp", proof.GetTargetForm(), proof.GetTargetForm().GetChildFormulas(), proof.Children(), proof.GetResultFormulasOfChildren()) +func alphaNotImp(proof *gs3.GS3Sequent, context Lib.List[AST.Form]) string { + return refineUnaryRule("GS3nimp", proof, context) } -func betaEqu(proof *gs3.GS3Sequent) string { - return allRules("GS3equ", proof.GetTargetForm(), proof.GetTargetForm().GetChildFormulas(), proof.Children(), proof.GetResultFormulasOfChildren()) +func betaOr(proof *gs3.GS3Sequent, context Lib.List[AST.Form]) string { + return refineBinaryRule("GS3or", proof, context) } -func betaNotEqu(proof *gs3.GS3Sequent) string { - composingForms := proof.GetTargetForm().GetChildFormulas().At(0).GetChildFormulas() - return allRules("GS3nequ", proof.GetTargetForm(), composingForms, proof.Children(), proof.GetResultFormulasOfChildren()) +func betaNotAnd(proof *gs3.GS3Sequent, context Lib.List[AST.Form]) string { + return refineBinaryRule("GS3nand", proof, context) } -func deltaEx(proof *gs3.GS3Sequent) string { - var formulaEx AST.Ex - if form, ok := proof.GetTargetForm().(AST.Ex); ok { - formulaEx = form - } - - return allRulesQuantExist( - "GS3ex", - proof.GetTargetForm(), - proof.GetTargetForm().GetChildFormulas(), - proof.Children(), - proof.GetResultFormulasOfChildren(), - formulaEx.GetVarList(), - proof.TermGenerated(), - ) +func betaImp(proof *gs3.GS3Sequent, context Lib.List[AST.Form]) string { + return refineBinaryRule("GS3imp", proof, context) } -func deltaNotAll(proof *gs3.GS3Sequent) string { - var formulaAll AST.All - if notForm, ok := proof.GetTargetForm().(AST.Not); ok { - if form, ok := notForm.GetForm().(AST.All); ok { - formulaAll = form - } - } - composingForms := proof.GetTargetForm().GetChildFormulas().At(0).GetChildFormulas() +func betaEqu(proof *gs3.GS3Sequent, context Lib.List[AST.Form]) string { + return refineBinaryRule("GS3equ", proof, context) +} - return allRulesQuantExist("GS3nall", proof.GetTargetForm(), composingForms, proof.Children(), proof.GetResultFormulasOfChildren(), formulaAll.GetVarList(), proof.TermGenerated()) +func betaNotEqu(proof *gs3.GS3Sequent, context Lib.List[AST.Form]) string { + return refineBinaryRule("GS3nequ", proof, context) } -func gammaAll(proof *gs3.GS3Sequent) string { - var formulaAll AST.All - if form, ok := proof.GetTargetForm().(AST.All); ok { - formulaAll = form - } +func deltaEx(proof *gs3.GS3Sequent, context Lib.List[AST.Form]) string { + return refineUnaryRule("GS3ex", proof, context) +} - return allRulesQuantUniv( - "GS3all", - proof.GetTargetForm(), - proof.GetTargetForm().GetChildFormulas(), - proof.Children(), - proof.GetResultFormulasOfChildren(), - formulaAll.GetVarList(), - proof.TermGenerated(), - ) +func deltaNotAll(proof *gs3.GS3Sequent, context Lib.List[AST.Form]) string { + return refineUnaryRule("GS3nall", proof, context) } -func gammaNotEx(proof *gs3.GS3Sequent) string { - var formulaEx AST.Ex - if notForm, ok := proof.GetTargetForm().(AST.Not); ok { - if form, ok := notForm.GetForm().(AST.Ex); ok { - formulaEx = form - } - } - composingForms := proof.GetTargetForm().GetChildFormulas().At(0).GetChildFormulas() +func gammaAll(proof *gs3.GS3Sequent, context Lib.List[AST.Form]) string { + return refineUnaryRule("GS3all", proof, context) +} - return allRulesQuantUniv("GS3nex", proof.GetTargetForm(), composingForms, proof.Children(), proof.GetResultFormulasOfChildren(), formulaEx.GetVarList(), proof.TermGenerated()) +func gammaNotEx(proof *gs3.GS3Sequent, context Lib.List[AST.Form]) string { + return refineUnaryRule("GS3nex", proof, context) } -// Processes the formula that was proven by Goéland. +// Split the axiom & conjecture formula from the root formula. func processMainFormula(form AST.Form) (Lib.List[AST.Form], AST.Form) { formList := Lib.NewList[AST.Form]() switch nf := form.(type) { @@ -368,20 +376,19 @@ func processMainFormula(form AST.Form) (Lib.List[AST.Form], AST.Form) { } // Prints the theorem's name & properly formats the first formula. -func makeTheorem(axioms Lib.List[AST.Form], conjecture AST.Form) string { - problemName := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(Glob.GetProblemName(), ".", "_"), "=", "_"), "+", "_") +func makeTheorem(axioms Lib.List[AST.Form], conjecture AST.Form) (string, Lib.List[AST.Form]) { + problemName := CertifUtils.SanitizedTheoremName() axioms = Lib.ListCpy(axioms) axioms.Append(AST.MakerNot(conjecture)) formattedProblem := makeImpChain(axioms) - return "symbol goeland_" + problemName + " : \nϵ " + formattedProblem.ToString() + " → ϵ ⊥ ≔ \n" + return "symbol goeland_" + problemName + " : \n" + formattedProblem + " → ϵ ⊥ ≔ \n", axioms } // If [F1, F2, F3] is a formlist, then this function returns F1 -> (F2 -> F3). -func makeImpChain(forms Lib.List[AST.Form]) AST.Form { - last := forms.Len() - 1 - form := forms.At(last) - for i := last - 1; i >= 0; i-- { - form = AST.MakerImp(forms.At(i), form) +func makeImpChain(forms Lib.List[AST.Form]) string { + imp_chain := []string{} + for _, form := range forms.GetSlice() { + imp_chain = append(imp_chain, fmt.Sprintf("ϵ (%s)", form.ToString())) } - return form + return strings.Join(imp_chain, " → ") } diff --git a/src/Mods/rocq/context.go b/src/Mods/rocq/context.go index 15d16e86..27d185e3 100644 --- a/src/Mods/rocq/context.go +++ b/src/Mods/rocq/context.go @@ -43,9 +43,8 @@ import ( "github.com/GoelandProver/Goeland/AST" "github.com/GoelandProver/Goeland/Glob" "github.com/GoelandProver/Goeland/Lib" + "github.com/GoelandProver/Goeland/Mods/CertifUtils" "github.com/GoelandProver/Goeland/Mods/dmt" - "github.com/GoelandProver/Goeland/Typing" - "slices" ) func makeContextIfNeeded(root AST.Form, metaList Lib.List[AST.Meta]) string { @@ -62,7 +61,10 @@ func makeContextIfNeeded(root AST.Form, metaList Lib.List[AST.Meta]) string { } // if AST.EmptyGlobalContext() { - resultingString += strings.Join(getContextFromFormula(root), "\n") + "\n" + contextual_symbols := CertifUtils.GetContextFromFormula(root) + for _, p := range contextual_symbols.GetSlice() { + resultingString += fmt.Sprintf("Parameter %s : %s.\n", p.Fst.ToString(), p.Snd.ToString()) + } if metaList.Len() > 0 { resultingString += contextualizeMetas(metaList) @@ -94,82 +96,6 @@ func contextPreamble() string { return str } -func getContextFromFormula(root AST.Form) []string { - result := []string{} - switch nf := root.(type) { - case AST.All: - result = getContextFromFormula(nf.GetForm()) - case AST.Ex: - result = getContextFromFormula(nf.GetForm()) - case AST.And: - for _, f := range nf.GetChildFormulas().GetSlice() { - result = append(result, clean(result, getContextFromFormula(f))...) - } - case AST.Or: - for _, f := range nf.GetChildFormulas().GetSlice() { - result = append(result, clean(result, getContextFromFormula(f))...) - } - case AST.Imp: - result = clean(result, getContextFromFormula(nf.GetF1())) - result = append(result, clean(result, getContextFromFormula(nf.GetF2()))...) - case AST.Equ: - result = clean(result, getContextFromFormula(nf.GetF1())) - result = append(result, clean(result, getContextFromFormula(nf.GetF2()))...) - case AST.Not: - result = clean(result, getContextFromFormula(nf.GetForm())) - case AST.Pred: - if !nf.GetID().Equals(AST.Id_eq) { - oty := Typing.QueryGlobalEnv(nf.GetID().GetName()) - var ty AST.Ty - switch rty := oty.(type) { - case Lib.Some[AST.Ty]: - ty = rty.Val - case Lib.None[AST.Ty]: - ty = AST.MkDefaultPredType(nf.GetArgs().Len()) - } - - result = append(result, fmt.Sprintf("Parameter %s : %s.", nf.GetID().ToString(), ty.ToString())) - } - for _, term := range nf.GetArgs().GetSlice() { - result = append(result, clean(result, getContextFromTerm(term))...) - } - } - return result -} - -func getContextFromTerm(trm AST.Term) []string { - result := []string{} - if fun, isFun := trm.(AST.Fun); isFun { - oty := Typing.QueryGlobalEnv(fun.GetName()) - var ty AST.Ty - switch rty := oty.(type) { - case Lib.Some[AST.Ty]: - ty = rty.Val - case Lib.None[AST.Ty]: - ty = AST.MkDefaultFunctionType(fun.GetArgs().Len()) - } - - result = append(result, - fmt.Sprintf("Parameter %s : %s.", fun.GetID().ToString(), ty.ToString())) - for _, term := range fun.GetArgs().GetSlice() { - result = append(result, clean(result, getContextFromTerm(term))...) - } - } - return result -} - -// Returns everything in add not in set -func clean(set, add []string) []string { - result := []string{} - for _, str := range add { - found := slices.Contains(set, str) - if !found { - result = append(result, str) - } - } - return result -} - func contextualizeMetas(metaList Lib.List[AST.Meta]) string { result := []string{} for _, meta := range metaList.GetSlice() { diff --git a/src/Mods/rocq/output.go b/src/Mods/rocq/output.go index a03afa3b..bea023d6 100644 --- a/src/Mods/rocq/output.go +++ b/src/Mods/rocq/output.go @@ -121,6 +121,7 @@ func RocqPrinterAction() AST.PrinterAction { func(typed_var Lib.Pair[string, AST.Ty]) string { return fmt.Sprintf("(%s : %s)", typed_var.Fst, sanitize_type(typed_var.Snd.ToString())) }, + connectives.DefaultOnFunctionalArgs, ) rocq_action = rocq_action.Compose(AST.SanitizerAction(connectives, []string{"@"})) return rocq_action.Compose(AST.RemoveSuperfluousParenthesesAction(connectives)) diff --git a/src/Mods/rocq/proof.go b/src/Mods/rocq/proof.go index b9e5de1d..9eec8f0d 100644 --- a/src/Mods/rocq/proof.go +++ b/src/Mods/rocq/proof.go @@ -43,6 +43,7 @@ import ( "github.com/GoelandProver/Goeland/AST" "github.com/GoelandProver/Goeland/Glob" "github.com/GoelandProver/Goeland/Lib" + "github.com/GoelandProver/Goeland/Mods/CertifUtils" "github.com/GoelandProver/Goeland/Mods/dmt" "github.com/GoelandProver/Goeland/Mods/gs3" ) @@ -111,7 +112,7 @@ func makeStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], constantsCre // If the target formula is an equality, it _does not_ target any formula of the context, // it simply tells us to close by congruence. Hence, we don't raise an anomaly if the // target form is an equality. - if !isPredEqual(proof.GetTargetForm()) { + if !CertifUtils.IsPredEqual(proof.GetTargetForm()) { Glob.Anomaly("rocq", fmt.Sprintf( "Index of %s not found in { %s }", proof.GetTargetForm().ToString(), @@ -123,7 +124,7 @@ func makeStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], constantsCre switch proof.Rule() { // Closure. case gs3.AX: - if isPredEqual(proof.GetTargetForm()) { + if CertifUtils.IsPredEqual(proof.GetTargetForm()) { resultingString = "congruence." } else { resultingString = "auto." @@ -253,10 +254,7 @@ func processMainFormula(form AST.Form) (Lib.List[AST.Form], AST.Form) { // Prints the theorem's name & properly formats the first formula. func makeTheorem(axioms Lib.List[AST.Form], conjecture AST.Form) string { - problemName := Glob.GetProblemName() - for _, s := range []string{".", "=", "+", "-"} { - problemName = strings.ReplaceAll(problemName, s, "_") - } + problemName := CertifUtils.SanitizedTheoremName() axiomsWithConj := Lib.ListCpy(axioms) axiomsWithConj.Append(AST.MakerNot(AST.MakerNot(conjecture))) formattedProblem := makeImpChain(axiomsWithConj) @@ -303,16 +301,6 @@ func introNames(il []int, sep ...string) string { return strings.Join(Glob.MapTo(il, func(_ int, f int) string { return introName(f) }), s) } -func isPredEqual(f AST.Form) bool { - if not, isNot := f.(AST.Not); isNot { - f = not.GetForm() - } - if p, isPred := f.(AST.Pred); isPred { - return p.GetID().Equals(AST.Id_eq) - } - return false -} - func addTermGenerated(constantsCreated []AST.Term, term AST.Term) ([]AST.Term, string) { if term == nil { dummy++ diff --git a/src/main.go b/src/main.go index 0b82d896..7240cbad 100644 --- a/src/main.go +++ b/src/main.go @@ -56,6 +56,7 @@ import ( "github.com/GoelandProver/Goeland/Mods/dmt" equality "github.com/GoelandProver/Goeland/Mods/equality/bse" "github.com/GoelandProver/Goeland/Mods/gs3" + "github.com/GoelandProver/Goeland/Mods/lambdapi" "github.com/GoelandProver/Goeland/Parser" "github.com/GoelandProver/Goeland/Search" "github.com/GoelandProver/Goeland/Search/incremental" @@ -210,6 +211,7 @@ func initDebuggers() { Unif.InitDebugger() Engine.InitDebugger() gs3.InitDebugger() + lambdapi.InitDebugger() } // FIXME: eventually, we would want to add an "interpretation" layer between elab and internal representation that does this From dacea15b34244e83c7df7eb2bd20a4bf59f65e91 Mon Sep 17 00:00:00 2001 From: Johann Rosain Date: Wed, 8 Oct 2025 10:06:06 +0200 Subject: [PATCH 19/30] Upd: update contributing to include test-suite instructions (and special instructions for lambdapi) --- CONTRIBUTING.md | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a3632354..db6ba779 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,11 +8,12 @@ wish to contribute to Goéland, you should start by [forking](https://github.com/GoelandProver/Goeland/fork) the repository. Then, you can work on on your feature/bug fix/enhancement in your local repository. -Once you deem your work satisfactory, you should [open a pull -request](https://github.com/GoelandProver/Goeland/compare) **targeting -master**. Then, one of the maintainer will review your code as soon as -possible. If you have no feedback for a few days, do not hesitate to ping one of -them. The current maintainers are: @jcailler, @jrosain. +Once you deem your work satisfactory and have properly updated the test suite +(c.f. [Managing the test suite](#managing-the-test-suite)), you should [open a pull +request](https://github.com/GoelandProver/Goeland/compare) **targeting master**. Then, one +of the maintainer will review your code as soon as possible. If you have no feedback for a +few days, do not hesitate to ping one of them. The current maintainers are: @jcailler, +@jrosain. Your code is expected to (i) build, (ii) satisfy the unit tests and (iii) not prove countertheorems. This check *does not* run automatically. One of the @@ -39,6 +40,25 @@ have a very descriptive error as it will make things easier to debug. Note that, by default, neither of these options `panic`. You have to activate the `-debug` flag in order for them to panic and you to have a backtrace. +### Managing the test suite + +In order to have a systematic testing of Goéland, we have a [test +suite](devtools/test-suite) that contains: +- basic test files to check functionalities, +- bug files that correspond to a reported bug that has been resolved, and +- output files that test the output of Goéland. + +When you add a new functionality to Goéland, you must add some files to the +[basic](devtools/test-suite/basic) folder that tests your newly implemented +functionalities. If your pull request fixes a bug, you must add the bug file to the +[bugs](devtools/test-suite/bugs) folder. Beware that we run the Rocq and Lambdapi output +on the test suite, so you should think about whether a problem is checkable or not. If +it's not, add them in the corresponding `no_chk` instead. The current not-checkable +problems are problems involving a typed context. Moreover, if your problem includes +equalities, the Lambdapi check may fail. If so, add your problem to the +`lp_tolerate_fails` variable in the `run-test-suite` file. + + ## For Maintainers By default, a pull request that modifies the go source code has the `needs:ci` label. You From 85f405e6e26dd1b505afff2c68c8b888e93d4e6c Mon Sep 17 00:00:00 2001 From: Johann Rosain Date: Mon, 1 Sep 2025 12:44:03 +0200 Subject: [PATCH 20/30] Add proof interface and adapter for Search.ProofStruct --- src/Lib/int.go | 12 + src/Search/proof-adapter.go | 437 ++++++++++++++++++++++++++++++++++++ src/Search/tableau-proof.go | 82 +++++++ 3 files changed, 531 insertions(+) create mode 100644 src/Search/proof-adapter.go create mode 100644 src/Search/tableau-proof.go diff --git a/src/Lib/int.go b/src/Lib/int.go index a7e4ef5b..980741cc 100644 --- a/src/Lib/int.go +++ b/src/Lib/int.go @@ -37,6 +37,10 @@ package Lib +import ( + "fmt" +) + type Int int func (s Int) Equals(oth any) bool { @@ -53,6 +57,14 @@ func (s Int) Less(oth any) bool { return false } +func (s Int) Copy() Int { + return Int(s) +} + +func (s Int) ToString() string { + return fmt.Sprintf("%d", s) +} + func MkInt(s int) Int { return Int(s) } diff --git a/src/Search/proof-adapter.go b/src/Search/proof-adapter.go new file mode 100644 index 00000000..99620061 --- /dev/null +++ b/src/Search/proof-adapter.go @@ -0,0 +1,437 @@ +/** +* Copyright 2022 by the authors (see AUTHORS). +* +* Goéland is an automated theorem prover for first order logic. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +**/ + +/** + * This file adapts the []ProofStruct to have an IProof implementation + **/ + +package Search + +import ( + "fmt" + + "github.com/GoelandProver/Goeland/AST" + "github.com/GoelandProver/Goeland/Glob" + "github.com/GoelandProver/Goeland/Lib" + "github.com/GoelandProver/Goeland/Mods/dmt" +) + +type TableauxProof []ProofStruct + +var label string = "TableauxProof" + +func (proof TableauxProof) makeSanityCheck() { + if len(proof) == 0 { + Glob.Anomaly(label, "Got an empty proof") + } +} + +// ---------------------------------------------------------------------------- +// IProof implementation +// ---------------------------------------------------------------------------- + +func (proof TableauxProof) AppliedOn() AST.Form { + proof.makeSanityCheck() + + return proof[0].Formula.GetForm() +} + +func (proof TableauxProof) RuleApplied() TableauxRule { + proof.makeSanityCheck() + + rule_map := map[string]TableauxRule{ + "ALPHA_NOT_NOT": RuleNotNot, + "ALPHA_NOT_OR": RuleNotOr, + "ALPHA_NOT_IMPLY": RuleNotImp, + "ALPHA_AND": RuleAnd, + "BETA_NOT_AND": RuleNotAnd, + "BETA_NOT_EQUIV": RuleNotEqu, + "BETA_OR": RuleOr, + "BETA_IMPLY": RuleImp, + "BETA_EQUIV": RuleEqu, + "GAMMA_NOT_EXISTS": RuleNotEx, + "GAMMA_FORALL": RuleAll, + "DELTA_NOT_FORALL": RuleNotAll, + "DELTA_EXISTS": RuleEx, + "CLOSURE": RuleClosure, + "Reintroduction": RuleReintro, + "Rewrite": RuleRew, + } + + r, ok := rule_map[proof[0].Rule] + if !ok { + Glob.Anomaly(label, fmt.Sprintf("Unknown tableau rule %s", proof[0].Rule)) + } + + return r +} + +func (proof TableauxProof) KindOfRule() TableauxRuleKind { + rule := proof.RuleApplied() + + switch rule { + case RuleNotNot, RuleNotOr, RuleNotImp, RuleAnd: + return KindAlpha + case RuleNotAnd, RuleNotEqu, RuleOr, RuleImp, RuleEqu: + return KindBeta + case RuleNotAll, RuleEx: + return KindDelta + case RuleNotEx, RuleAll, RuleReintro: + return KindGamma + case RuleRew: + return KindRew + } + + Glob.Anomaly(label, "Unknown kind of rule") + return 0 +} + +func (proof TableauxProof) ResultFormulas() Lib.List[Lib.List[AST.Form]] { + proof.makeSanityCheck() + + result_forms := Lib.MkList[Lib.List[AST.Form]](len(proof[0].Result_formulas)) + for i, forms := range proof[0].Result_formulas { + result_forms.Upd(i, forms.GetForms()) + } + return result_forms +} + +func (proof TableauxProof) Children() Lib.List[IProof] { + proof.makeSanityCheck() + + // If proof has only one element, then either: + // + // (1) it's a closure rule, but then we return an emptyh list + // (2) it's a beta rule, and we need to return the children + // + // In both cases, it suffices to convert the children to a list. + // Otherwise, the children are empty and we simply delete the first element. + if len(proof) == 1 { + children_proofs := Lib.MkList[IProof](len(proof[0].Children)) + for i, child := range proof[0].Children { + children_proofs.Upd(i, IProof(TableauxProof(child))) + } + return children_proofs + } else { + return Lib.MkListV(IProof(TableauxProof(proof[1:]))) + } +} + +func (proof TableauxProof) RewrittenWith() Lib.Option[AST.Form] { + proof.makeSanityCheck() + + dmt_axioms := dmt.GetRegisteredAxioms() + rewrite_id := proof[0].Id_dmt + form_opt := Lib.MkNone[AST.Form]() + + for _, axiom := range dmt_axioms.GetSlice() { + end_form := axiom + for Glob.Is[AST.All](end_form) { + end_form = end_form.(AST.All).GetForm() + } + end_form = getAtomic(end_form) + if end_form.GetIndex() == rewrite_id { + form_opt = Lib.MkSome(axiom) + } + } + + return form_opt +} + +func (proof TableauxProof) TermGenerated() Lib.Option[Lib.Either[AST.Ty, AST.Term]] { + proof.makeSanityCheck() + + if !(len(proof[0].Result_formulas) == 1 && + proof[0].Result_formulas[0].GetForms().Len() == 1) { + return Lib.MkNone[AST.Term]() + } + + source_form := proof[0].Formula.GetForm() + target_form := proof[0].Result_formulas[0].GetForms().At(0) + + replaced_variable := getReplacedVariable(source_form) + occurrence_opt := getOneOccurrence(source_form, replaced_variable) + + return Lib.OptBind( + occurrence_opt, + func(occurrence Lib.List[Lib.Int]) Lib.Option[AST.Term] { + return Lib.MkSome(getTermAtOcc(target_form, occurrence)) + }, + ) +} + +// ---------------------------------------------------------------------------- +// Private utility functions +// ---------------------------------------------------------------------------- + +func getAtomic(f AST.Form) AST.Form { + switch nf := f.(type) { + case AST.Imp: + if pred, isPred := nf.GetF1().(AST.Pred); isPred { + return pred + } + case AST.Equ: + if pred, isPred := nf.GetF1().(AST.Pred); isPred { + return pred + } + if pred, isPred := nf.GetF2().(AST.Pred); isPred { + return pred + } + } + + debug( + Lib.MkLazy(func() string { + return fmt.Sprintf( + "Tried to rewrite using %s, but no atomic formula can be found in this formula.", + f.ToString(), + ) + }), + ) + Glob.Anomaly(label, "Could not find rewritten atom") + return nil +} + +func getReplacedVariable(form AST.Form) AST.TypedVar { + get_first := func(vars Lib.List[AST.TypedVar]) AST.TypedVar { + if vars.Empty() { + Glob.Anomaly(label, "Found a quantified formula with an empty list of vars") + } + return vars.At(0) + } + + switch f := form.(type) { + case AST.All: + return get_first(f.GetVarList()) + case AST.Ex: + return get_first(f.GetVarList()) + case AST.Not: + switch nf := f.GetForm().(type) { + case AST.All: + return get_first(nf.GetVarList()) + case AST.Ex: + return get_first(nf.GetVarList()) + } + } + + Glob.Anomaly(label, "Found quantifier rule on non-quantified formula") + return AST.TypedVar{} +} + +// A variable might be quantified but never appear in a formula +func getOneOccurrence(form AST.Form, v AST.TypedVar) Lib.Option[Lib.List[Lib.Int]] { + clean_form := getCleanForm(form) + return getOneOccInCleanForm(clean_form, v, Lib.NewList[Lib.Int]()) +} + +func getTermAtOcc(form AST.Form, occurrence Lib.List[Lib.Int]) Lib.Either[AST.Ty, AST.Term] { + clean_form := getCleanForm(form) + return getTermAtOccInCleanForm(clean_form, occurrence) +} + +func getCleanForm(form AST.Form) AST.Form { + switch f := form.(type) { + case AST.All: + return f.GetForm() + case AST.Ex: + return f.GetForm() + case AST.Not: + switch nf := f.GetForm().(type) { + case AST.All: + return AST.MakerNot(nf.GetForm()) + case AST.Ex: + return AST.MakerNot(nf.GetForm()) + } + } + return form +} + +func getOneOccInCleanForm(form AST.Form, v AST.TypedVar, occurrence Lib.List[Lib.Int]) Lib.Option[Lib.List[Lib.Int]] { + switch f := form.(type) { + case AST.Pred: + return getFunctionalOcc(f.GetTyArgs(), f.GetArgs(), v, occurrence) + + default: + for i, child := range form.GetChildFormulas().GetSlice() { + local_occ := appCopy(Lib.MkInt(i), occurrence) + occ := getOneOccInCleanForm(child, v, local_occ) + + if _, ok := occ.(Lib.Some[Lib.List[Lib.Int]]); ok { + return occ + } + } + } + + return Lib.MkNone[Lib.List[Lib.Int]]() +} + +func getTermAtOccInCleanForm(form AST.Form, occurrence Lib.List[Lib.Int]) Lib.Either[AST.Ty, AST.Term] { + switch f := form.(type) { + case AST.Pred: + return getFunctionalTermAtOcc(f.GetTyArgs(), f.GetArgs(), occurrence) + + default: + return getTermAtOcc( + f.GetChildFormulas().At(int(occurrence.At(0))), + occurrence.Slice(1, occurrence.Len()), + ) + } +} + +func getFunctionalOcc( + tys Lib.List[AST.Ty], + terms Lib.List[AST.Term], + v AST.TypedVar, + occurrence Lib.List[Lib.Int], +) Lib.Option[Lib.List[Lib.Int]] { + for i, ty := range tys.GetSlice() { + local_occ := appCopy(Lib.MkInt(i), occurrence) + occ := getOneOccInTy(ty, v.ToTyBoundVar(), local_occ) + + if _, ok := occ.(Lib.Some[Lib.List[Lib.Int]]); ok { + return occ + } + } + + offset := tys.Len() + for i, trm := range terms.GetSlice() { + local_occ := appCopy(Lib.MkInt(i+offset), occurrence) + occ := getOneOccInTrm(trm, v, local_occ) + + if _, ok := occ.(Lib.Some[Lib.List[Lib.Int]]); ok { + return occ + } + } + + return Lib.MkNone[Lib.List[Lib.Int]]() +} + +func getFunctionalTermAtOcc( + tys Lib.List[AST.Ty], + terms Lib.List[AST.Term], + occurrence Lib.List[Lib.Int], +) Lib.Either[AST.Ty, AST.Term] { + index := int(occurrence.At(0)) + next_occ := occurrence.Slice(1, occurrence.Len()) + + if index < tys.Len() { + return Lib.MkLeft[AST.Ty, AST.Term](getTermInTy(tys.At(index), next_occ)) + } else { + return getTermInTerm(terms.At(index), next_occ) + } +} + +func appCopy[A Lib.Copyable[A]](x A, ls Lib.List[A]) Lib.List[A] { + result_list := Lib.ListCpy(ls) + result_list.Append(x) + return result_list +} + +func getOneOccInTy(ty AST.Ty, v AST.TyBound, occurrence Lib.List[Lib.Int]) Lib.Option[Lib.List[Lib.Int]] { + switch t := ty.(type) { + case AST.TyBound: + if t.Equals(v) { + return Lib.MkSome(occurrence) + } + return Lib.MkNone[Lib.List[Lib.Int]]() + + case AST.TyConstr: + for i, arg := range t.Args().GetSlice() { + local_occ := appCopy(Lib.MkInt(i), occurrence) + occ := getOneOccInTy(arg, v, local_occ) + + if _, ok := occ.(Lib.Some[Lib.List[Lib.Int]]); ok { + return occ + } + } + + return Lib.MkNone[Lib.List[Lib.Int]]() + } + + return Lib.MkNone[Lib.List[Lib.Int]]() +} + +func getTermInTy(ty AST.Ty, occurrence Lib.List[Lib.Int]) AST.Ty { + if occurrence.Empty() { + return ty + } else { + switch t := ty.(type) { + case AST.TyConstr: + return getTermInTy(t.Args().At(int(occurrence.At(0))), occurrence.Slice(1, occurrence.Len())) + } + + debug(Lib.MkLazy(func() string { + return fmt.Sprintf( + "Tried to get occurrence [%s] in %s", + Lib.ListToString(occurrence, ", ", ""), + ty.ToString(), + ) + })) + Glob.Anomaly(label, "Occurrence not found in type") + return nil + } +} + +func getOneOccInTrm(trm AST.Term, v AST.TypedVar, occurrence Lib.List[Lib.Int]) Lib.Option[Lib.List[Lib.Int]] { + switch t := trm.(type) { + case AST.Var: + if t.Equals(v.ToBoundVar()) { + return Lib.MkSome(occurrence) + } + return Lib.MkNone[Lib.List[Lib.Int]]() + + case AST.Fun: + return getFunctionalOcc(t.GetTyArgs(), t.GetArgs(), v, occurrence) + } + + return Lib.MkNone[Lib.List[Lib.Int]]() +} + +func getTermInTerm(trm AST.Term, occurrence Lib.List[Lib.Int]) Lib.Either[AST.Ty, AST.Term] { + if occurrence.Empty() { + return Lib.MkRight[AST.Ty, AST.Term](trm) + } else { + switch t := trm.(type) { + case AST.Fun: + return getFunctionalTermAtOcc(t.GetTyArgs(), t.GetArgs(), occurrence) + } + + debug(Lib.MkLazy(func() string { + return fmt.Sprintf( + "Tried to get occurrence [%s] in %s", + Lib.ListToString(occurrence, ", ", ""), + trm.ToString(), + ) + })) + Glob.Anomaly(label, "Occurrence not found in type") + return nil + } +} diff --git a/src/Search/tableau-proof.go b/src/Search/tableau-proof.go new file mode 100644 index 00000000..dcdd4bb5 --- /dev/null +++ b/src/Search/tableau-proof.go @@ -0,0 +1,82 @@ +/** +* Copyright 2022 by the authors (see AUTHORS). +* +* Goéland is an automated theorem prover for first order logic. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +**/ + +/** + * This file provides an interface to ease communication between proof structures. + **/ + +package Search + +import ( + "github.com/GoelandProver/Goeland/AST" + "github.com/GoelandProver/Goeland/Lib" +) + +type TableauxRule int +type TableauxRuleKind int + +const ( + RuleClosure TableauxRule = iota + RuleImp + RuleAnd + RuleOr + RuleEqu + RuleEx + RuleAll + RuleNotNot + RuleNotImp + RuleNotAnd + RuleNotOr + RuleNotEqu + RuleNotEx + RuleNotAll + RuleReintro + RuleRew +) + +const ( + KindAlpha TableauxRuleKind = iota + KindBeta + KindDelta + KindGamma + KindRew +) + +type IProof interface { + AppliedOn() AST.Form + RuleApplied() TableauxRule + KindOfRule() TableauxRuleKind + ResultFormulas() Lib.List[Lib.List[AST.Form]] + Children() Lib.List[IProof] + RewrittenWith() Lib.Option[AST.Form] + TermGenerated() Lib.Option[Lib.Either[AST.Ty, AST.Term]] +} From 99329c8cb63e6fafe0acace23e8613351c156871 Mon Sep 17 00:00:00 2001 From: Johann Rosain Date: Sun, 22 Feb 2026 11:21:08 +0100 Subject: [PATCH 21/30] Add: golines as a dependency to avoid having lines over a 100 characters --- CONTRIBUTING.md | 22 ++++++++++++++++++++++ shell.nix | 1 + 2 files changed, 23 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index db6ba779..d2cfe4e8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -27,6 +27,28 @@ master*. If you are solving a bug referenced in the issue tracker, do not forget to link it in the PR. +### Code formatting + +We expect the code to be formatted using the `golines` tool, with the linebreak configured +at *100* characters. `golines` is furnished in the Nix environment, but can otherwise be +installed by following the instructions of the [official +repository](https://github.com/golangci/golines). You can enable `golines` to run on save +in your IDE. + +#### Formatting on save in `emacs` + +```elisp +(use-package go-mode + :init + (defun my/go-format () + (interactive) + (save-buffer) + (shell-command + (format "golines -m 100 -w %s" buffer-file-name))) + + :hook ((before-save . my/go-format))) +``` + ### Error management When you add code or fix old code, try to find the possible error cases where an diff --git a/shell.nix b/shell.nix index 97d4cf1a..4fca80e6 100644 --- a/shell.nix +++ b/shell.nix @@ -5,6 +5,7 @@ pkgs.mkShell { go gopls gotools + golines python314 rocq-core rocqPackages.stdlib From 104d20d81d0d60aea51c692de8a51aeeb23af90f Mon Sep 17 00:00:00 2001 From: Johann Rosain Date: Fri, 20 Feb 2026 09:47:45 +0100 Subject: [PATCH 22/30] fix: Rework deskolemization algorithm and adapt proof outputs to IProof --- src/AST/formsDef.go | 110 +- src/AST/formula.go | 17 +- src/AST/modular-printing.go | 31 +- src/AST/quantifiers.go | 14 +- src/AST/term.go | 25 +- src/AST/termsDef.go | 43 +- src/AST/ty-syntax.go | 23 +- src/Glob/log.go | 24 +- src/Lib/list.go | 27 + src/Lib/pair.go | 22 + src/Lib/string.go | 2 + .../CertifUtils/epsilon-terms-management.go | 225 ++++ src/Mods/CertifUtils/utils.go | 48 + src/Mods/desko/on-branch-information.go | 109 ++ src/Mods/desko/proof.go | 301 +++++ src/Mods/desko/sequent.go | 79 ++ .../equality/bse/equality_rules_try_apply.go | 59 +- src/Mods/gs3/dependency.go | 248 ---- src/Mods/gs3/graph.go | 162 --- src/Mods/gs3/proof.go | 724 ----------- src/Mods/gs3/sequent.go | 310 ----- src/Mods/lambdapi/output.go | 23 +- src/Mods/lambdapi/proof.go | 160 ++- src/Mods/rocq/context.go | 3 +- src/Mods/rocq/output.go | 30 +- src/Mods/rocq/proof.go | 426 ++++--- src/Mods/tptp/output.go | 23 +- src/Mods/tptp/proof.go | 1136 +++++++++-------- src/Search/print_proof.go | 15 +- src/Search/proof-adapter.go | 136 +- src/Search/proof.go | 51 +- src/Search/tableau-proof.go | 57 +- src/Unif/parsing.go | 15 +- src/main.go | 27 +- src/options.go | 45 +- 35 files changed, 2346 insertions(+), 2404 deletions(-) create mode 100644 src/Mods/CertifUtils/epsilon-terms-management.go create mode 100644 src/Mods/desko/on-branch-information.go create mode 100644 src/Mods/desko/proof.go create mode 100644 src/Mods/desko/sequent.go delete mode 100644 src/Mods/gs3/dependency.go delete mode 100644 src/Mods/gs3/graph.go delete mode 100644 src/Mods/gs3/proof.go delete mode 100644 src/Mods/gs3/sequent.go diff --git a/src/AST/formsDef.go b/src/AST/formsDef.go index 15894989..b705c815 100644 --- a/src/AST/formsDef.go +++ b/src/AST/formsDef.go @@ -38,6 +38,7 @@ package AST import ( "fmt" + "github.com/GoelandProver/Goeland/Glob" "github.com/GoelandProver/Goeland/Lib" ) @@ -134,6 +135,8 @@ func (a All) ReplaceMetaByTerm(meta Meta, term Term) Form { return All{a.quantifier.replaceMetaByTerm(meta, term)} } +func (a All) Less(oth any) bool { return less(a, oth) } + // ----------------------------------------------------------------------------- // Exists @@ -189,6 +192,8 @@ func (e Ex) ReplaceMetaByTerm(meta Meta, term Term) Form { return Ex{e.quantifier.replaceMetaByTerm(meta, term)} } +func (e Ex) Less(oth any) bool { return less(e, oth) } + // ----------------------------------------------------------------------------- // Or @@ -228,11 +233,21 @@ func (o Or) GetMetas() Lib.Set[Meta] { return o.metas.Get(o) } -func (o Or) GetSubTerms() Lib.List[Term] { - res := Lib.NewList[Term]() +func (o Or) GetSubTerms() Lib.Set[Term] { + res := Lib.EmptySet[Term]() + + for _, tl := range o.forms.GetSlice() { + res = res.Union(tl.GetSubTerms()) + } + + return res +} + +func (o Or) GetSymbols() Lib.Set[Id] { + res := Lib.EmptySet[Id]() for _, tl := range o.forms.GetSlice() { - res.Add(TermEquals, tl.GetSubTerms().GetSlice()...) + res = res.Union(tl.GetSymbols()) } return res @@ -293,6 +308,8 @@ func (o Or) ReplaceMetaByTerm(meta Meta, term Term) Form { return MakeOr(o.GetIndex(), LsSubstByTerm(o.forms, meta, term)) } +func (o Or) Less(oth any) bool { return less(o, oth) } + // ----------------------------------------------------------------------------- // And @@ -349,11 +366,21 @@ func (a And) GetMetas() Lib.Set[Meta] { return a.metas.Get(a) } -func (a And) GetSubTerms() Lib.List[Term] { - res := Lib.NewList[Term]() +func (a And) GetSubTerms() Lib.Set[Term] { + res := Lib.EmptySet[Term]() + + for _, tl := range a.forms.GetSlice() { + res = res.Union(tl.GetSubTerms()) + } + + return res +} + +func (a And) GetSymbols() Lib.Set[Id] { + res := Lib.EmptySet[Id]() for _, tl := range a.forms.GetSlice() { - res.Add(TermEquals, tl.GetSubTerms().GetSlice()...) + res = res.Union(tl.GetSymbols()) } return res @@ -417,6 +444,8 @@ func (a And) ReplaceMetaByTerm(meta Meta, term Term) Form { return MakeAnd(a.GetIndex(), LsSubstByTerm(a.forms, meta, term)) } +func (a And) Less(oth any) bool { return less(a, oth) } + // ----------------------------------------------------------------------------- // Equivalence @@ -505,11 +534,12 @@ func (e Equ) RenameVariables() Form { return MakeEqu(e.GetIndex(), e.GetF1().RenameVariables(), e.GetF2().RenameVariables()) } -func (e Equ) GetSubTerms() Lib.List[Term] { - res := e.GetF1().GetSubTerms().Copy(Term.Copy) - res.Add(TermEquals, e.GetF2().GetSubTerms().GetSlice()...) +func (e Equ) GetSubTerms() Lib.Set[Term] { + return e.GetF1().GetSubTerms().Union(e.GetF2().GetSubTerms()) +} - return res +func (e Equ) GetSymbols() Lib.Set[Id] { + return e.GetF1().GetSymbols().Union(e.GetF2().GetSymbols()) } func (e Equ) SubstituteVarByMeta(old Var, new Meta) Form { @@ -526,9 +556,15 @@ func (e Equ) GetChildFormulas() Lib.List[Form] { } func (e Equ) ReplaceMetaByTerm(meta Meta, term Term) Form { - return MakeEqu(e.GetIndex(), e.f1.ReplaceMetaByTerm(meta, term), e.f2.ReplaceMetaByTerm(meta, term)) + return MakeEqu( + e.GetIndex(), + e.f1.ReplaceMetaByTerm(meta, term), + e.f2.ReplaceMetaByTerm(meta, term), + ) } +func (e Equ) Less(oth any) bool { return less(e, oth) } + // ----------------------------------------------------------------------------- // Implication @@ -620,11 +656,12 @@ func (i Imp) RenameVariables() Form { return MakeImp(i.GetIndex(), i.GetF1().RenameVariables(), i.GetF2().RenameVariables()) } -func (i Imp) GetSubTerms() Lib.List[Term] { - res := i.GetF1().GetSubTerms().Copy(Term.Copy) - res.Add(TermEquals, i.GetF2().GetSubTerms().GetSlice()...) +func (i Imp) GetSubTerms() Lib.Set[Term] { + return i.GetF1().GetSubTerms().Union(i.GetF2().GetSubTerms()) +} - return res +func (i Imp) GetSymbols() Lib.Set[Id] { + return i.GetF1().GetSymbols().Union(i.GetF2().GetSymbols()) } func (i Imp) SubstituteVarByMeta(old Var, new Meta) Form { @@ -641,9 +678,15 @@ func (i Imp) GetChildFormulas() Lib.List[Form] { } func (i Imp) ReplaceMetaByTerm(meta Meta, term Term) Form { - return MakeImp(i.GetIndex(), i.f1.ReplaceMetaByTerm(meta, term), i.f2.ReplaceMetaByTerm(meta, term)) + return MakeImp( + i.GetIndex(), + i.f1.ReplaceMetaByTerm(meta, term), + i.f2.ReplaceMetaByTerm(meta, term), + ) } +func (i Imp) Less(oth any) bool { return less(i, oth) } + // ----------------------------------------------------------------------------- // Not @@ -683,10 +726,14 @@ func (n Not) GetMetas() Lib.Set[Meta] { return n.metas.Get(n) } -func (n Not) GetSubTerms() Lib.List[Term] { +func (n Not) GetSubTerms() Lib.Set[Term] { return n.GetForm().GetSubTerms() } +func (n Not) GetSymbols() Lib.Set[Id] { + return n.GetForm().GetSymbols() +} + func (n Not) Equals(other any) bool { if typed, ok := other.(Not); ok { return typed.f.Equals(n.f) @@ -783,6 +830,8 @@ func getDeepFormWithoutNot(form Form, isEven bool) (Form, bool) { } } +func (n Not) Less(oth any) bool { return less(n, oth) } + // ----------------------------------------------------------------------------- // Predicates @@ -943,12 +992,21 @@ func (p Pred) SubstTy(old TyGenVar, new Ty) Form { ) } -func (p Pred) GetSubTerms() Lib.List[Term] { - res := Lib.NewList[Term]() +func (p Pred) GetSubTerms() Lib.Set[Term] { + res := Lib.EmptySet[Term]() + + for _, t := range p.GetArgs().GetSlice() { + res = res.Add(t).Union(t.GetSubTerms()) + } + + return res +} + +func (p Pred) GetSymbols() Lib.Set[Id] { + res := Lib.EmptySet[Id]() for _, t := range p.GetArgs().GetSlice() { - res.Add(TermEquals, t) - res.Add(TermEquals, t.GetSubTerms().GetSlice()...) + res = res.Union(t.GetSymbols()) } return res @@ -993,6 +1051,8 @@ func (p Pred) ReplaceMetaByTerm(meta Meta, term Term) Form { ) } +func (p Pred) Less(oth any) bool { return less(p, oth) } + // ----------------------------------------------------------------------------- // True and False @@ -1016,12 +1076,14 @@ func (t Top) ReplaceTermByTerm(Term, Term) (Form, bool) { return MakeTop(t.Get func (t Top) SubstTy(TyGenVar, Ty) Form { return t } func (t Top) RenameVariables() Form { return MakeTop(t.GetIndex()) } func (t Top) GetIndex() int { return t.index } -func (t Top) GetSubTerms() Lib.List[Term] { return Lib.NewList[Term]() } +func (t Top) GetSubTerms() Lib.Set[Term] { return Lib.EmptySet[Term]() } +func (t Top) GetSymbols() Lib.Set[Id] { return Lib.EmptySet[Id]() } func (t Top) SubstituteVarByMeta(Var, Meta) Form { return t } func (t Top) GetInternalMetas() Lib.Set[Meta] { return Lib.EmptySet[Meta]() } func (t Top) GetSubFormulasRecur() Lib.List[Form] { return Lib.MkListV[Form](t) } func (t Top) GetChildFormulas() Lib.List[Form] { return Lib.NewList[Form]() } func (t Top) ReplaceMetaByTerm(meta Meta, term Term) Form { return t } +func (t Top) Less(oth any) bool { return less(t, oth) } /* Bot (always false) definition */ type Bot struct { @@ -1044,9 +1106,11 @@ func (b Bot) ReplaceTermByTerm(Term, Term) (Form, bool) { return MakeBot(b.Get func (b Bot) SubstTy(TyGenVar, Ty) Form { return b } func (b Bot) RenameVariables() Form { return MakeBot(b.GetIndex()) } func (b Bot) GetIndex() int { return b.index } -func (b Bot) GetSubTerms() Lib.List[Term] { return Lib.NewList[Term]() } +func (b Bot) GetSubTerms() Lib.Set[Term] { return Lib.EmptySet[Term]() } +func (b Bot) GetSymbols() Lib.Set[Id] { return Lib.EmptySet[Id]() } func (b Bot) SubstituteVarByMeta(Var, Meta) Form { return b } func (b Bot) GetInternalMetas() Lib.Set[Meta] { return Lib.EmptySet[Meta]() } func (b Bot) GetSubFormulasRecur() Lib.List[Form] { return Lib.MkListV[Form](b) } func (b Bot) GetChildFormulas() Lib.List[Form] { return Lib.NewList[Form]() } func (b Bot) ReplaceMetaByTerm(meta Meta, term Term) Form { return b } +func (b Bot) Less(oth any) bool { return less(b, oth) } diff --git a/src/AST/formula.go b/src/AST/formula.go index 05ceb63b..3decaf3f 100644 --- a/src/AST/formula.go +++ b/src/AST/formula.go @@ -46,13 +46,15 @@ import ( type Form interface { GetIndex() int GetMetas() Lib.Set[Meta] - GetSubTerms() Lib.List[Term] + GetSubTerms() Lib.Set[Term] + GetSymbols() Lib.Set[Id] GetSubFormulasRecur() Lib.List[Form] GetChildFormulas() Lib.List[Form] Lib.Copyable[Form] Lib.Stringable Lib.Comparable + Lib.Ordered ReplaceTermByTerm(old Term, new Term) (Form, bool) SubstTy(old TyGenVar, new Ty) Form @@ -61,6 +63,13 @@ type Form interface { ReplaceMetaByTerm(meta Meta, term Term) Form } +func less(form Form, oth any) bool { + if f, is_form := oth.(Form); is_form { + return form.GetIndex() < f.GetIndex() + } + return false +} + /* Replace a term by a term inside a function. */ func replaceTermInTermList( terms Lib.List[Term], @@ -124,7 +133,11 @@ func metasUnion(forms Lib.List[Form]) Lib.Set[Meta] { } // Returns whether the term has been replaced in a subformula or not -func replaceTermInFormList(oldForms Lib.List[Form], oldTerm Term, newTerm Term) (Lib.List[Form], bool) { +func replaceTermInFormList( + oldForms Lib.List[Form], + oldTerm Term, + newTerm Term, +) (Lib.List[Form], bool) { newForms := Lib.MkList[Form](oldForms.Len()) res := false diff --git a/src/AST/modular-printing.go b/src/AST/modular-printing.go index 97d886e5..0545bf10 100644 --- a/src/AST/modular-printing.go +++ b/src/AST/modular-printing.go @@ -136,7 +136,15 @@ func MkPrinterAction( actionOnTypedVar func(Lib.Pair[string, Ty]) string, actionOnFunctional func(id Id, tys Lib.List[string], args Lib.List[string]) string, ) PrinterAction { - return PrinterAction{genericAction, actionOnId, actionOnBoundVar, actionOnMeta, actionOnType, actionOnTypedVar, actionOnFunctional} + return PrinterAction{ + genericAction, + actionOnId, + actionOnBoundVar, + actionOnMeta, + actionOnType, + actionOnTypedVar, + actionOnFunctional, + } } type Connective int @@ -159,7 +167,10 @@ func (p *PrinterConnective) StrConn(conn Connective) string { if val, ok := p.connectives[conn]; ok { printer_debug( - Lib.MkLazy(func() string { return fmt.Sprintf("Found connective %d in %s as %s", conn, p.name, val) })) + Lib.MkLazy( + func() string { return fmt.Sprintf("Found connective %d in %s as %s", conn, p.name, val) }, + ), + ) return val } else { if p.name == DefaultPrinterConnectives().name { @@ -171,7 +182,12 @@ func (p *PrinterConnective) StrConn(conn Connective) string { } printer_debug(Lib.MkLazy(func() string { - return fmt.Sprintf("Connective %d not found in %s, trying in %s", conn, p.name, default_connective.name) + return fmt.Sprintf( + "Connective %d not found in %s, trying in %s", + conn, + p.name, + default_connective.name, + ) })) return default_connective.StrConn(conn) } @@ -196,7 +212,11 @@ type Printer struct { *PrinterConnective } -func (c PrinterConnective) DefaultOnFunctionalArgs(id Id, tys Lib.List[string], args Lib.List[string]) string { +func (c PrinterConnective) DefaultOnFunctionalArgs( + id Id, + tys Lib.List[string], + args Lib.List[string], +) string { infix := Lib.MkListV(Id_eq) is_infix := Lib.ListMem(id, infix) types := strings.Join(tys.GetSlice(), c.StrConn(SepTyArgs)) @@ -205,9 +225,10 @@ func (c PrinterConnective) DefaultOnFunctionalArgs(id Id, tys Lib.List[string], if is_infix { if args.Len() != 2 { Glob.Anomaly("Printer", fmt.Sprintf( - "invalid number of infix arguments: expected 2, got %d (in %s)", + "invalid number of infix arguments: expected 2, got %d (in <<%s>> for %s)", args.Len(), arguments, + id.ToString(), )) } return fmt.Sprintf("%s %s %s", args.At(0), id.ToString(), args.At(1)) diff --git a/src/AST/quantifiers.go b/src/AST/quantifiers.go index 9c0afbb2..ca16519f 100644 --- a/src/AST/quantifiers.go +++ b/src/AST/quantifiers.go @@ -50,7 +50,13 @@ type quantifier struct { symbol Connective } -func makeQuantifier(i int, vars Lib.List[TypedVar], subForm Form, metas Lib.Set[Meta], symbol Connective) quantifier { +func makeQuantifier( + i int, + vars Lib.List[TypedVar], + subForm Form, + metas Lib.Set[Meta], + symbol Connective, +) quantifier { return quantifier{ Lib.MkCache(metas, quantifier.forceGetMetas), i, @@ -106,10 +112,14 @@ func (q quantifier) Equals(other any) bool { return false } -func (q quantifier) GetSubTerms() Lib.List[Term] { +func (q quantifier) GetSubTerms() Lib.Set[Term] { return q.GetForm().GetSubTerms() } +func (q quantifier) GetSymbols() Lib.Set[Id] { + return q.GetForm().GetSymbols() +} + func (q quantifier) copy() quantifier { nq := makeQuantifier( q.GetIndex(), diff --git a/src/AST/term.go b/src/AST/term.go index bfe5f5f3..d059226d 100644 --- a/src/AST/term.go +++ b/src/AST/term.go @@ -37,6 +37,7 @@ package AST import ( + "github.com/GoelandProver/Goeland/Glob" "github.com/GoelandProver/Goeland/Lib" ) @@ -52,7 +53,8 @@ type Term interface { ToMeta() Meta GetMetas() Lib.Set[Meta] GetMetaList() Lib.List[Meta] // Metas appearing in the term ORDERED - GetSubTerms() Lib.List[Term] + GetSubTerms() Lib.Set[Term] + GetSymbols() Lib.Set[Id] ReplaceSubTermBy(original_term, new_term Term) Term SubstTy(old TyGenVar, new Ty) Term Less(any) bool @@ -84,3 +86,24 @@ func MakeFun(p Id, ty_args Lib.List[Ty], args Lib.List[Term], metas Lib.Set[Meta func TermEquals(x, y Term) bool { return x.Equals(y) } + +func GetSymbol(tm Term) Lib.Option[Id] { + switch t := tm.(type) { + case Var, Meta: + return Lib.MkNone[Id]() + case Fun: + return Lib.MkSome(t.GetID()) + case Id: + return Lib.MkSome(tm) + } + + debug(Lib.MkLazy(func() string { + return tm.ToString() + })) + + Glob.Anomaly( + "term", + "Found a term that was neither a bound variable nor a free variable nor a function", + ) + return Lib.MkNone[Id]() +} diff --git a/src/AST/termsDef.go b/src/AST/termsDef.go index 83994bb6..3c2ec7c9 100644 --- a/src/AST/termsDef.go +++ b/src/AST/termsDef.go @@ -63,7 +63,7 @@ func (i Id) ToString() string { return printer.StrId(i) } func (i Id) Equals(t any) bool { if typed, ok := t.(Id); ok { - return typed.GetIndex() == i.GetIndex() + return typed.name == i.name } return false } @@ -77,8 +77,12 @@ func (i Id) ReplaceSubTermBy(original_term, new_term Term) Term { func (i Id) SubstTy(TyGenVar, Ty) Term { return i } -func (i Id) GetSubTerms() Lib.List[Term] { - return Lib.MkListV[Term](i) +func (i Id) GetSubTerms() Lib.Set[Term] { + return Lib.Singleton[Term](i) +} + +func (i Id) GetSymbols() Lib.Set[Id] { + return Lib.Singleton(i) } // id < other : -1; id = other : 0; id > other : 1 @@ -234,12 +238,21 @@ func (f Fun) ReplaceAllSubTerm(oldTerm, newTerm Term) Term { } } -func (f Fun) GetSubTerms() Lib.List[Term] { - res := Lib.NewList[Term]() +func (f Fun) GetSubTerms() Lib.Set[Term] { + res := Lib.Singleton(Term(f)) - res.Add(TermEquals, f) for _, arg := range f.GetArgs().GetSlice() { - res.Add(TermEquals, arg.GetSubTerms().GetSlice()...) + res = res.Union(arg.GetSubTerms()) + } + + return res +} + +func (f Fun) GetSymbols() Lib.Set[Id] { + res := Lib.Singleton(f.GetID()) + + for _, arg := range f.GetArgs().GetSlice() { + res = res.Union(arg.GetSymbols()) } return res @@ -280,8 +293,12 @@ func (v Var) Equals(t any) bool { return false } -func (v Var) GetSubTerms() Lib.List[Term] { - return Lib.MkListV[Term](v) +func (v Var) GetSubTerms() Lib.Set[Term] { + return Lib.Singleton[Term](v) +} + +func (v Var) GetSymbols() Lib.Set[Id] { + return Lib.EmptySet[Id]() } func (v Var) ReplaceSubTermBy(original_term, new_term Term) Term { @@ -347,8 +364,12 @@ func (m Meta) ReplaceSubTermBy(original_term, new_term Term) Term { func (m Meta) SubstTy(TyGenVar, Ty) Term { return m } -func (m Meta) GetSubTerms() Lib.List[Term] { - return Lib.MkListV[Term](m) +func (m Meta) GetSubTerms() Lib.Set[Term] { + return Lib.Singleton[Term](m) +} + +func (m Meta) GetSymbols() Lib.Set[Id] { + return Lib.EmptySet[Id]() } func (m Meta) Less(u any) bool { diff --git a/src/AST/ty-syntax.go b/src/AST/ty-syntax.go index f24bc75b..f05d3fd8 100644 --- a/src/AST/ty-syntax.go +++ b/src/AST/ty-syntax.go @@ -433,7 +433,10 @@ func GetArgsTy(ty Ty) Lib.List[Ty] { } Glob.Anomaly( "Ty.GetArgs", - fmt.Sprintf("Tried to extract types of arguments of a non-functional type %s", ty.ToString()), + fmt.Sprintf( + "Tried to extract types of arguments of a non-functional type %s", + ty.ToString(), + ), ) return Lib.NewList[Ty]() } @@ -453,6 +456,14 @@ func GetOutTy(ty Ty) Ty { return nil } +func GetTySymbol(ty Ty) Lib.Option[string] { + switch t := ty.(type) { + case TyConstr: + return Lib.MkSome(t.symbol) + } + return Lib.MkNone[string]() +} + func TyToTerm(ty Ty) Term { switch nty := ty.(type) { case TyMeta: @@ -467,7 +478,10 @@ func TyToTerm(ty Ty) Term { Glob.Anomaly( "AST.Ty", - fmt.Sprintf("Trying to convert the non-atomic (or bound var) type %s to a term", ty.ToString()), + fmt.Sprintf( + "Trying to convert the non-atomic (or bound var) type %s to a term", + ty.ToString(), + ), ) return nil } @@ -485,7 +499,10 @@ func TermToTy(trm Term) Ty { Glob.Anomaly( "AST.Ty", - fmt.Sprintf("Trying to convert the non-atomic (or bound var) term %s to a type", trm.ToString()), + fmt.Sprintf( + "Trying to convert the non-atomic (or bound var) term %s to a type", + trm.ToString(), + ), ) return nil } diff --git a/src/Glob/log.go b/src/Glob/log.go index 91543837..5d0acd0d 100644 --- a/src/Glob/log.go +++ b/src/Glob/log.go @@ -37,13 +37,14 @@ package Glob import ( "fmt" - "github.com/GoelandProver/Goeland/Lib" "io" "log" "os" "path/filepath" "runtime" "time" + + "github.com/GoelandProver/Goeland/Lib" ) var ( @@ -136,7 +137,11 @@ func EnableWriteLogs() { wrt = io.MultiWriter(os.Stdout, f) - f, err = os.OpenFile("/tmp/Goeland"+time.Now().Format("[2006-01-02 15:04:05]")+".log", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666) + f, err = os.OpenFile( + "/tmp/Goeland"+time.Now().Format("[2006-01-02 15:04:05]")+".log", + os.O_RDWR|os.O_CREATE|os.O_TRUNC, + 0666, + ) if err != nil { log.Fatalf("Error opening log file: %v", err) @@ -194,3 +199,18 @@ func CreateDebugger(name string) Debugger { } return debug } + +type InterruptingDebugger func() + +func CreateInterruptingDebugger(name string) func() { + debug := CreateDebugger(name) + return func() { + debug(Lib.MkLazy( + func() string { + fmt.Println("Press enter to continue...") + fmt.Scanln() + return "" + }), + ) + } +} diff --git a/src/Lib/list.go b/src/Lib/list.go index 14a483e8..877a35be 100644 --- a/src/Lib/list.go +++ b/src/Lib/list.go @@ -72,6 +72,12 @@ func (l *List[T]) Append(value ...T) { l.values = append(l.values, value...) } +// Functional version of Append +func (l List[T]) Push(values ...T) List[T] { + l.values = append(l.values, values...) + return l +} + func (l *List[T]) Upd(i int, v T) { l.values[i] = v } @@ -240,6 +246,27 @@ func (l List[T]) Filter(pred Func[T, bool]) List[T] { return res } +func (l List[T]) InsertAt(i int, x T) List[T] { + if i == l.Len() { + l.values = append(l.values, x) + } else if l.Len() <= 0 || i > l.Len() { + return l + } else { + l.values = append(l.values[:i+1], l.values[i:]...) + l.values[i] = x + } + return l +} + +// Shallow copy of the list (returns simply a new list with the same elements) +func (l List[T]) Clone() List[T] { + nl := MkList[T](l.Len()) + for i, x := range l.values { + nl.Upd(i, x) + } + return nl +} + func ToStrictlyOrderedList[T StrictlyOrdered](l List[T]) StrictlyOrderedList[T] { return StrictlyOrderedList[T]{values: l} } diff --git a/src/Lib/pair.go b/src/Lib/pair.go index 975b2038..25f435d7 100644 --- a/src/Lib/pair.go +++ b/src/Lib/pair.go @@ -44,3 +44,25 @@ func MkPair[T, U any](x T, y U) Pair[T, U] { func (p Pair[T, U]) ToString(f Func[T, string], g Func[U, string], sep string) string { return "(" + f(p.Fst) + sep + g(p.Snd) + ")" } + +// Managing lists of pairs +func Pr1[T, U any](ls List[Pair[T, U]]) List[T] { + return ListMap(ls, func(p Pair[T, U]) T { return p.Fst }) +} + +func Pr2[T, U any](ls List[Pair[T, U]]) List[U] { + return ListMap(ls, func(p Pair[T, U]) U { return p.Snd }) +} + +func MemAssoc[T, U Comparable](x T, l List[Pair[T, U]]) bool { + return ListMem(x, Pr1(l)) +} + +func AssqOpt[T, U Comparable](x T, l List[Pair[T, U]]) Option[U] { + return OptBind( + ListIndexOf(x, Pr1(l)), + func(i int) Option[U] { + return MkSome(l.At(i).Snd) + }, + ) +} diff --git a/src/Lib/string.go b/src/Lib/string.go index 05c00449..a485fae7 100644 --- a/src/Lib/string.go +++ b/src/Lib/string.go @@ -53,6 +53,8 @@ func (s String) Less(oth any) bool { return false } +func (s String) ToString() string { return string(s) } + func MkString(s string) String { return String(s) } diff --git a/src/Mods/CertifUtils/epsilon-terms-management.go b/src/Mods/CertifUtils/epsilon-terms-management.go new file mode 100644 index 00000000..04f3ef3e --- /dev/null +++ b/src/Mods/CertifUtils/epsilon-terms-management.go @@ -0,0 +1,225 @@ +/** +* Copyright 2022 by the authors (see AUTHORS). +* +* Goéland is an automated theorem prover for first order logic. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +**/ + +package CertifUtils + +import ( + "strings" + + "github.com/GoelandProver/Goeland/AST" + "github.com/GoelandProver/Goeland/Glob" + "github.com/GoelandProver/Goeland/Lib" +) + +/** + * In this file, we define the management of epsilon terms during the certification process. + * Indeed, the proof search phase can generate two types of Skolemized constants: terms and types. + * Here, we give an API that manages both at the same time. For now, given a function that + * transforms Skolemized terms to epsilon terms and Skolemized types to epsilon types, this file + * simply offers utility functions at the instantiation time. + **/ +type Epsilon struct { + tms Lib.List[Lib.Pair[AST.Term, AST.Term]] + tys Lib.List[Lib.Pair[AST.Ty, AST.Ty]] + ground Lib.Set[AST.Term] + + on_term func(AST.Term) AST.Term + on_type func(AST.Ty) AST.Ty +} + +func EmptyEpsilon( + ground_terms Lib.Set[AST.Term], + on_term func(AST.Term) AST.Term, + on_type func(AST.Ty) AST.Ty, + get func(Lib.Either[AST.Ty, AST.Term]) string, +) Epsilon { + return Epsilon{ + tms: Lib.NewList[Lib.Pair[AST.Term, AST.Term]](), + tys: Lib.NewList[Lib.Pair[AST.Ty, AST.Ty]](), + ground: ground_terms, + on_term: on_term, + on_type: on_type, + } +} + +func (e Epsilon) Introduced(tm Lib.Either[AST.Ty, AST.Term]) bool { + switch t := tm.(type) { + case Lib.Left[AST.Ty, AST.Term]: + return Lib.MemAssoc(t.Val, e.tys) + case Lib.Right[AST.Ty, AST.Term]: + return Lib.MemAssoc(t.Val, e.tms) + } + return false +} + +func (e Epsilon) Copy() Epsilon { + return Epsilon{ + tms: e.tms.Clone(), + tys: e.tys.Clone(), + ground: e.ground, + on_term: e.on_term, + on_type: e.on_type, + } +} + +func (e *Epsilon) Generate( + t Lib.Option[Lib.Either[AST.Ty, AST.Term]], +) Lib.Option[Lib.Either[AST.Ty, AST.Term]] { + return Lib.OptBind( + t, + func(t Lib.Either[AST.Ty, AST.Term]) Lib.Option[Lib.Either[AST.Ty, AST.Term]] { + switch actual := t.(type) { + case Lib.Left[AST.Ty, AST.Term]: + ty := e.on_type(actual.Val) + e.tys.Append(Lib.MkPair(actual.Val, ty)) + return Lib.MkSome(Lib.MkLeft[AST.Ty, AST.Term](ty)) + case Lib.Right[AST.Ty, AST.Term]: + tm := e.on_term(actual.Val) + e.tms.Append(Lib.MkPair(actual.Val, tm)) + return Lib.MkSome(Lib.MkRight[AST.Ty, AST.Term](tm)) + } + + Glob.Anomaly("epsilon terms", "Reached an unreachable state") + return Lib.MkNone[Lib.Either[AST.Ty, AST.Term]]() + }, + ) +} + +func (e Epsilon) Instantiate( + def_ty, def_tm string, + t Lib.Option[Lib.Either[AST.Ty, AST.Term]], +) string { + switch tm := t.(type) { + case Lib.Some[Lib.Either[AST.Ty, AST.Term]]: + switch t := tm.Val.(type) { + case Lib.Left[AST.Ty, AST.Term]: + return e.instantiateTy(def_ty, t.Val) + case Lib.Right[AST.Ty, AST.Term]: + return e.instantiateTm(def_tm, t.Val) + } + } + // FIXME: this should actually depend on what the caller gives, this might be def_ty in + // the future + return def_tm +} + +func (e Epsilon) instantiateTy(def string, ty AST.Ty) string { + switch t := ty.(type) { + case AST.TyBound: + Glob.Anomaly("epsilon terms", "Cannot instantiate with bound variable") + + case AST.TyMeta: + return def + + case AST.TyConstr: + switch v := Lib.AssqOpt(ty, e.tys).(type) { + case Lib.Some[AST.Ty]: + return v.Val.ToString() + case Lib.None[AST.Ty]: + res := t.Symbol() + subtypes := make([]string, 0) + for _, ty := range t.Args().GetSlice() { + subtypes = append(subtypes, e.instantiateTy(def, ty)) + } + if len(subtypes) > 0 { + res += "(" + strings.Join(subtypes, ", ") + ")" + } + return res + } + + case AST.TyProd: + subtypes := make([]string, 0) + for _, ty := range t.GetTys().GetSlice() { + subtypes = append(subtypes, e.instantiateTy(def, ty)) + } + return strings.Join(subtypes, " * ") + + case AST.TyFunc, AST.TyPi: + Glob.Anomaly("epsilon terms", "Cannot instantiate with a functional type") + } + + Glob.Anomaly("epsilon terms", "Unknown type") + return "" +} + +func (e Epsilon) Substitute(dummy_tm AST.Term, form AST.Form) AST.Form { + // FIXME: there is no function to substitute a type by a type yet + // for _, ty := range e.tys.GetSlice() { + + // } + + for _, tm := range form.GetSubTerms().Elements().GetSlice() { + if !(e.ground.Contains(tm)) { + switch repl := Lib.AssqOpt(tm, e.tms).(type) { + case Lib.Some[AST.Term]: + form, _ = form.ReplaceTermByTerm(tm, repl.Val) + case Lib.None[AST.Term]: + form, _ = form.ReplaceTermByTerm(tm, dummy_tm) + } + } + } + + return form +} + +func (e Epsilon) instantiateTm(def string, tm AST.Term) string { + switch t := tm.(type) { + case AST.Id, AST.Var: + Glob.Anomaly("epsilon terms", "Cannot instantiate with id or bound variable") + + case AST.Meta: + return t.ToString() + + case AST.Fun: + switch v := Lib.AssqOpt(tm, e.tms).(type) { + case Lib.Some[AST.Term]: + return v.Val.ToString() + case Lib.None[AST.Term]: + if !(e.ground.Contains(tm)) { + return def + } + + res := t.GetID().ToString() + subterms := make([]string, 0) + for _, tm := range t.GetArgs().GetSlice() { + subterms = append(subterms, e.instantiateTm(def, tm)) + } + if len(subterms) > 0 { + res += "(" + strings.Join(subterms, ", ") + ")" + } + return res + } + } + + Glob.Anomaly("epsilon terms", "Unknown term") + return "" +} diff --git a/src/Mods/CertifUtils/utils.go b/src/Mods/CertifUtils/utils.go index 3a0726f5..d3e8442e 100644 --- a/src/Mods/CertifUtils/utils.go +++ b/src/Mods/CertifUtils/utils.go @@ -36,7 +36,15 @@ package CertifUtils **/ import ( + "fmt" + "github.com/GoelandProver/Goeland/AST" + "github.com/GoelandProver/Goeland/Glob" + "github.com/GoelandProver/Goeland/Lib" +) + +const ( + INVALID_INDEX = -1 ) func IsPredEqual(f AST.Form) bool { @@ -48,3 +56,43 @@ func IsPredEqual(f AST.Form) bool { } return false } + +// Returns the index of the given formula [applied_on] in the list of formulas [hypotheses]. +// As this is an inferrence step, returns [INVALID_INDEX] _only if_ the target formula is an empty +// equality predicate OR [True], which means either that the proof should be concluded by [congruence] +// or that there is a weakening happening on a term and a dummy formula has been used. +// Otherwise, if the formula is not found in the list of hypotheses, raises an [Anomaly]: this +// is certainly something that should never happen. +func GetTargetFormIndex(applied_on AST.Form, hypotheses Lib.List[AST.Form]) int { + switch t := Lib.ListIndexOf(applied_on, hypotheses).(type) { + case Lib.Some[int]: + return t.Val + case Lib.None[int]: + if !IsPredEqual(applied_on) && !applied_on.Equals(AST.MakerTop()) { + Glob.Anomaly( + "certif-utils", + fmt.Sprintf("index of %s not found in { %s }", applied_on.ToString(), Lib.ListToString(hypotheses, " ;; ", "")), + ) + } + } + return INVALID_INDEX +} + +// The first step is always of the form: +// +// H1 & H2 & H3 & H4 & ... & ~C --> H1, H2, H3, H4, ..., ~C +// +// Hence, we return the list of hypothesis [Hi] and the _base_ conjecture, i.e., the +// non-negated version. +func ProcessMainFormula(form AST.Form) (Lib.List[AST.Form], AST.Form) { + formList := Lib.NewList[AST.Form]() + switch nf := form.(type) { + case AST.Not: + form = nf.GetForm() + case AST.And: + last := nf.GetChildFormulas().Len() - 1 + formList = Lib.MkListV(nf.GetChildFormulas().Get(0, last)...) + form = nf.GetChildFormulas().At(last).(AST.Not).GetForm() + } + return formList, form +} diff --git a/src/Mods/desko/on-branch-information.go b/src/Mods/desko/on-branch-information.go new file mode 100644 index 00000000..b385a9f9 --- /dev/null +++ b/src/Mods/desko/on-branch-information.go @@ -0,0 +1,109 @@ +/** + * Copyright 2022 by the authors (see AUTHORS). +* +* Goéland is an automated theorem prover for first order logic. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. + **/ + +/** + * This file defines the `branch_checker` type. Elements of this type are functions + * which test whether a given Skolem symbol is on the branch of another Skolem symbol. + * + * This is achieved through a pre-computation given a proof. + **/ + +package desko + +import ( + "github.com/GoelandProver/Goeland/AST" + "github.com/GoelandProver/Goeland/Lib" + "github.com/GoelandProver/Goeland/Search" +) + +// Returns [true] if the formula has been introduced in the same branch +// as the Skolem symbol. +type branch_checker func(AST.Id, AST.Form) bool + +func precompute_branch_checker(proof Search.IProof) branch_checker { + symbols_map := acc_and_assoc_symbols( + proof, + Lib.EmptySet[AST.Form](), + make(map[AST.Id]Lib.Set[AST.Form]), + ) + + return func(symbol AST.Id, form AST.Form) bool { + if set, found := symbols_map[symbol]; found { + return set.Contains(form) + } + + return false + } +} + +func acc_and_assoc_symbols( + proof Search.IProof, + accumulator Lib.Set[AST.Form], + m map[AST.Id]Lib.Set[AST.Form], +) map[AST.Id]Lib.Set[AST.Form] { + + switch Search.KindOfRule(proof.RuleApplied()) { + + case Search.KindDelta: + switch t := proof.TermGenerated().(type) { + + case Lib.Some[Lib.Either[AST.Ty, AST.Term]]: + switch tm := t.Val.(type) { + case Lib.Left[AST.Ty, AST.Term]: + // pass: we should not have to deskolemize types + case Lib.Right[AST.Ty, AST.Term]: + switch f := tm.Val.(type) { + case AST.Fun: + m[f.GetID()] = accumulator.Copy() + default: + raise_anomaly("Found a non-functional Skolem term: " + tm.Val.ToString()) + } + } + + case Lib.None[Lib.Either[AST.Ty, AST.Term]]: + // pass + // This case might happen when the bound variable that has just been instantiated + // never appears in the formula. + } + + default: + // pass + } + + accumulator = accumulator.Add(proof.AppliedOn()) + + for _, child := range proof.Children().GetSlice() { + m = acc_and_assoc_symbols(child, accumulator.Copy(), m) + } + + return m +} diff --git a/src/Mods/desko/proof.go b/src/Mods/desko/proof.go new file mode 100644 index 00000000..594273f4 --- /dev/null +++ b/src/Mods/desko/proof.go @@ -0,0 +1,301 @@ +/** + * Copyright 2022 by the authors (see AUTHORS). +* +* Goéland is an automated theorem prover for first order logic. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. + **/ + +/** + * This file deskolemizes an `IProof` into a `GS3Sequent`. + **/ + +package desko + +import ( + "fmt" + + "github.com/GoelandProver/Goeland/AST" + "github.com/GoelandProver/Goeland/Glob" + "github.com/GoelandProver/Goeland/Lib" + "github.com/GoelandProver/Goeland/Search" +) + +var label = "desko" +var debug Glob.Debugger +var debug_interrupt Glob.InterruptingDebugger +var raise_anomaly = func(msg string) { Glob.Anomaly(label, msg) } +var desko_delta StrategyRule + +type proof_node struct { + proof Search.IProof + child int +} + +type proof_info struct { + ctx Lib.List[AST.Form] + form_introduction map[int]proof_node +} + +type StrategyRule func(*GS3Sequent, Search.IProof, branch_checker, proof_info) + +func InitDebugger() { + debug = Glob.CreateDebugger(label) + debug_interrupt = Glob.CreateInterruptingDebugger(label + "-interupt") +} + +var MakeDeskolemizedProof = func(proof Search.IProof) *GS3Sequent { + if Glob.IsOuterSko() { + desko_delta = gen_replay + } else if Glob.IsInnerSko() || Glob.IsPreInnerSko() { + desko_delta = desko_inner + } else { + Glob.Fatal(label, "Unsupported Skolemization") + } + + root := new(GS3Sequent) + deskolemize_proof(root, proof, precompute_branch_checker(proof), empty_proof_info()) + return root +} + +func empty_proof_info() proof_info { + return proof_info{ + ctx: Lib.NewList[AST.Form](), + form_introduction: make(map[int]proof_node), + } +} + +func copy_proof_info(info proof_info) proof_info { + nmap := make(map[int]proof_node) + for k, v := range info.form_introduction { + nmap[k] = v + } + return proof_info{ctx: Lib.ListCpy(info.ctx), form_introduction: nmap} +} + +func deskolemize_proof( + node *GS3Sequent, + proof Search.IProof, + is_on_branch branch_checker, + info proof_info, +) { + switch Search.KindOfRule(proof.RuleApplied()) { + case Search.KindClosure: + node.appliedOn = proof.AppliedOn() + node.rule = proof.RuleApplied() + case Search.KindAlpha, Search.KindBeta, Search.KindGamma, Search.KindRew: + gen_replay(node, proof, is_on_branch, info) + case Search.KindDelta: + desko_delta(node, proof, is_on_branch, info) + case Search.KindStructural: + if proof.RuleApplied() == Search.RuleReintro { + deskolemize_proof(node, proof.Children().At(0), is_on_branch, info) + } else { + raise_anomaly("Tableaux proofs should have no structural rules") + } + } +} + +func gen_apply_rule(node *GS3Sequent, proof Search.IProof, info proof_info) []proof_info { + node.children = Lib.NewList[*GS3Sequent]() + node.appliedOn = proof.AppliedOn() + node.formsGenerated = proof.ResultFormulas() + node.rule = proof.RuleApplied() + node.termGenerated = proof.TermGenerated() + node.rewriteWith = proof.RewrittenWith() + child_infos := []proof_info{} + for i := range proof.Children().GetSlice() { + child_info := copy_proof_info(info) + child_info.ctx.Append(node.formsGenerated.At(i).GetSlice()...) + for _, f := range node.formsGenerated.At(i).GetSlice() { + child_info.form_introduction[f.GetIndex()] = proof_node{proof: proof, child: i} + } + child := new(GS3Sequent) + node.children.Append(child) + child_infos = append(child_infos, child_info) + } + return child_infos +} + +func gen_replay( + node *GS3Sequent, + proof Search.IProof, + is_on_branch branch_checker, + info proof_info, +) { + infos := gen_apply_rule(node, proof, info) + + if len(infos) != node.Children().Len() { + raise_anomaly("translated rule does not have the same number of children") + } + + for i, child_proof := range proof.Children().GetSlice() { + deskolemize_proof(node.children.At(i), child_proof, is_on_branch, infos[i]) + } +} + +func gen_weaken( + node *GS3Sequent, + term Lib.Option[Lib.Either[AST.Ty, AST.Term]], + applied_on AST.Form, +) *GS3Sequent { + node.termGenerated = term + node.rewriteWith = Lib.MkNone[AST.Form]() + node.appliedOn = applied_on + node.rule = Search.RuleWeaken + child := new(GS3Sequent) + node.children = Lib.MkListV(child) + return child +} + +func desko_inner( + node *GS3Sequent, + proof Search.IProof, + is_on_branch branch_checker, + info proof_info, +) { + var tm AST.Term + switch t := proof.TermGenerated().(type) { + case Lib.Some[Lib.Either[AST.Ty, AST.Term]]: + switch term := t.Val.(type) { + case Lib.Left[AST.Ty, AST.Term]: + // Shortcut: Skolemized types do not have to be deskolemized. + gen_replay(node, proof, is_on_branch, info) + case Lib.Right[AST.Ty, AST.Term]: + tm = term.Val + } + + case Lib.None[Lib.Either[AST.Ty, AST.Term]]: + // Shortcut: as it doesn't appear in the proof, we don't care about this step + gen_replay(node, proof, is_on_branch, info) + return + } + + if tm == nil { + raise_anomaly("The IProof gives a wrong TermGenerated result") + } + + var sko_symbol AST.Id + switch symb := AST.GetSymbol(tm).(type) { + case Lib.Some[AST.Id]: + sko_symbol = symb.Val + case Lib.None[AST.Id]: + raise_anomaly(fmt.Sprintf("The term %s is not a valid Skolem symbol", tm.ToString())) + } + + // Step 1: weaken the formulas in which the Skolem symbol appears + forms_to_weaken := get_forms_in_ctx_with_symbol(info, sko_symbol) + debug( + Lib.MkLazy(func() string { + return fmt.Sprintf( + "Symbol: %s; formulas to weaken:\n [%s]\n\nResult formula of the delta: %s, context:\n [%s]", + sko_symbol.ToString(), + Lib.ListToString(forms_to_weaken, ",\n", ""), + proof.ResultFormulas().At(0).At(0).ToString(), + Lib.ListToString(info.ctx, ",\n", ""), + ) + }), + ) + + // Fast path: if the delta has already been applied in the branch, skip the delta rule + if Lib.ListMem(proof.ResultFormulas().At(0).At(0), info.ctx) { + debug( + Lib.MkLazy(func() string { + return "Result formula found in the tree, skipping rule..." + })) + deskolemize_proof(node, proof.Children().At(0), is_on_branch, info) + return + } + + to_replay := Lib.NewList[proof_node]() + + // We must delay the weakening of terms as we first have to remove all the formulas + // containing a term before weakening it. + term_delayed_weakening := []Lib.Option[Lib.Either[AST.Ty, AST.Term]]{} + for _, form := range forms_to_weaken.GetSlice() { + comes_from := info.form_introduction[form.GetIndex()].proof.AppliedOn() + if is_on_branch(sko_symbol, comes_from) { + to_replay.Append(info.form_introduction[form.GetIndex()]) + } + node = gen_weaken(node, Lib.MkNone[Lib.Either[AST.Ty, AST.Term]](), form) + if Search.KindOfRule(info.form_introduction[form.GetIndex()].proof.RuleApplied()) == + Search.KindDelta { + term_delayed_weakening = append( + term_delayed_weakening, + info.form_introduction[form.GetIndex()].proof.TermGenerated(), + ) + } + } + for _, delayed := range term_delayed_weakening { + node = gen_weaken(node, delayed, AST.MakerTop()) + } + + debug( + Lib.MkLazy(func() string { + return fmt.Sprintf( + "Formulas to replay: %s", + Lib.ListToString(Lib.ListMap( + to_replay, func(node proof_node) AST.Form { return node.proof.AppliedOn() }, + ), ", ", "[]"), + ) + }), + ) + debug_interrupt() + + info.ctx = info.ctx.Filter(func(f AST.Form) bool { + return !(Lib.ListMem(f, forms_to_weaken)) + }) + + // Step 2: apply the Skolemization rule + infos := gen_apply_rule(node, proof, info) + info = infos[0] + node = node.children.At(0) + + // Step 3: replay only the stuff coming from the same branch + for _, n := range to_replay.GetSlice() { + infos := gen_apply_rule(node, n.proof, info) + for i, child_proof := range n.proof.Children().GetSlice() { + if i != n.child { + deskolemize_proof(node.children.At(i), child_proof, is_on_branch, infos[i]) + } + } + info = infos[n.child] + node = node.children.At(n.child) + } + + deskolemize_proof(node, proof.Children().At(0), is_on_branch, info) +} + +func get_forms_in_ctx_with_symbol(info proof_info, symb AST.Id) Lib.List[AST.Form] { + forms_with_term := Lib.NewList[AST.Form]() + for _, form := range info.ctx.GetSlice() { + if form.GetSymbols().Contains(symb) { + forms_with_term.Append(form) + } + } + return forms_with_term +} diff --git a/src/Mods/desko/sequent.go b/src/Mods/desko/sequent.go new file mode 100644 index 00000000..c9ef1b00 --- /dev/null +++ b/src/Mods/desko/sequent.go @@ -0,0 +1,79 @@ +/** +* Copyright 2022 by the authors (see AUTHORS). +* +* Goéland is an automated theorem prover for first order logic. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +**/ +package desko + +import ( + "fmt" + + "github.com/GoelandProver/Goeland/AST" + "github.com/GoelandProver/Goeland/Lib" + "github.com/GoelandProver/Goeland/Search" +) + +type GS3Sequent struct { + rule Search.TableauxRule + appliedOn AST.Form + rewriteWith Lib.Option[AST.Form] + termGenerated Lib.Option[Lib.Either[AST.Ty, AST.Term]] + formsGenerated Lib.List[Lib.List[AST.Form]] + children Lib.List[*GS3Sequent] +} + +// IProof interface + +func (s *GS3Sequent) AppliedOn() AST.Form { return s.appliedOn } +func (s *GS3Sequent) RuleApplied() Search.TableauxRule { return s.rule } +func (s *GS3Sequent) ResultFormulas() Lib.List[Lib.List[AST.Form]] { return s.formsGenerated } + +func (s *GS3Sequent) Children() Lib.List[Search.IProof] { + return Lib.ListMap( + s.children, + func(child *GS3Sequent) Search.IProof { return Search.IProof(child) }, + ) +} + +func (s *GS3Sequent) RewrittenWith() Lib.Option[AST.Form] { return s.rewriteWith } + +func (s *GS3Sequent) TermGenerated() Lib.Option[Lib.Either[AST.Ty, AST.Term]] { return s.termGenerated } + +func (s *GS3Sequent) ToString() string { + res := Lib.ListToString(s.children, "\n", "") + + return fmt.Sprintf( + "%s\ngs3(%p, %s, %s ---> %s)", + res, + s, + s.appliedOn.ToString(), + s.rule.ToString(), + s.children.ToString(func(c *GS3Sequent) string { return fmt.Sprintf("%p", c) }, ",", "[]"), + ) +} diff --git a/src/Mods/equality/bse/equality_rules_try_apply.go b/src/Mods/equality/bse/equality_rules_try_apply.go index b24dda94..375ad322 100644 --- a/src/Mods/equality/bse/equality_rules_try_apply.go +++ b/src/Mods/equality/bse/equality_rules_try_apply.go @@ -54,8 +54,12 @@ func tryApplyLeftRules(ep EqualityProblem, index_begin int) ruleStructList { i := index_begin for i < len(ep.GetE()) { eq_pair := ep.GetE()[i] - res = append(res, tryApplyRuleAux(eq_pair.GetT1(), eq_pair.GetT2(), ep.copy(), LEFT, true, i)...) - res = append(res, tryApplyRuleAux(eq_pair.GetT2(), eq_pair.GetT1(), ep.copy(), LEFT, false, i)...) + res = append( + res, + tryApplyRuleAux(eq_pair.GetT1(), eq_pair.GetT2(), ep.copy(), LEFT, true, i)...) + res = append( + res, + tryApplyRuleAux(eq_pair.GetT2(), eq_pair.GetT1(), ep.copy(), LEFT, false, i)...) i++ } debug( @@ -79,7 +83,13 @@ func tryApplyRightRules(ep EqualityProblem) ruleStructList { } /* Set rule's parameter */ -func tryApplyRuleAux(t1, t2 AST.Term, ep EqualityProblem, ruleType int, is_s_modified bool, index int) ruleStructList { +func tryApplyRuleAux( + t1, t2 AST.Term, + ep EqualityProblem, + ruleType int, + is_s_modified bool, + index int, +) ruleStructList { res := tryApplyRuleCompute(t1.Copy(), t2.Copy(), ep.copy(), ruleType) new_res := ruleStructList{} for _, r := range res { @@ -110,8 +120,8 @@ func tryApplyRuleCompute(s, t AST.Term, ep EqualityProblem, type_rule int) ruleS debug(Lib.MkLazy(func() string { return fmt.Sprintf( "len subterms found : %v - %v", - subterms_of_s.Len(), - subterms_of_s.ToString(AST.Term.ToString, ",", "[]"), + subterms_of_s.Cardinal(), + Lib.ListToString(subterms_of_s.Elements(), ",", "[]"), ) })) debug( @@ -119,9 +129,11 @@ func tryApplyRuleCompute(s, t AST.Term, ep EqualityProblem, type_rule int) ruleS ) // for each l' substerm of s, return a list (l', l) unifiable - list_l_prime_l := searchUnifBewteenListAndEq(subterms_of_s, ep.getETree()) + list_l_prime_l := searchUnifBewteenListAndEq(subterms_of_s.Elements(), ep.getETree()) debug( - Lib.MkLazy(func() string { return fmt.Sprintf("len unifiable subterms found : %v", len(list_l_prime_l)) }), + Lib.MkLazy( + func() string { return fmt.Sprintf("len unifiable subterms found : %v", len(list_l_prime_l)) }, + ), ) // Now, for each (l', l), retrieve the r corresponding to the l @@ -129,7 +141,13 @@ func tryApplyRuleCompute(s, t AST.Term, ep EqualityProblem, type_rule int) ruleS } /* Retrieve the last membre of rule struct and return the list */ -func connectLAndR(list_l_prime_l []eqStruct.TermPair, ep EqualityProblem, s AST.Term, t AST.Term, type_rule int) ruleStructList { +func connectLAndR( + list_l_prime_l []eqStruct.TermPair, + ep EqualityProblem, + s AST.Term, + t AST.Term, + type_rule int, +) ruleStructList { res := ruleStructList{} for _, l_prime_l_pair := range list_l_prime_l { @@ -163,7 +181,17 @@ func connectLAndR(list_l_prime_l []eqStruct.TermPair, ep EqualityProblem, s AST. debug( Lib.MkLazy(func() string { return "Try apply rule ok !" }), ) - res = append(res, makeRuleStruct(type_rule, l_prime_l_pair.GetT2(), r.Copy(), l_prime_l_pair.GetT1(), s.Copy(), t.Copy())) + res = append( + res, + makeRuleStruct( + type_rule, + l_prime_l_pair.GetT2(), + r.Copy(), + l_prime_l_pair.GetT1(), + s.Copy(), + t.Copy(), + ), + ) } else { debug( Lib.MkLazy(func() string { return "Don't apply an equality on itself" }), @@ -175,7 +203,10 @@ func connectLAndR(list_l_prime_l []eqStruct.TermPair, ep EqualityProblem, s AST. } /* return all the pair (l, l') unifiable */ -func searchUnifBewteenListAndEq(tl Lib.List[AST.Term], tree Unif.DataStructure) []eqStruct.TermPair { +func searchUnifBewteenListAndEq( + tl Lib.List[AST.Term], + tree Unif.DataStructure, +) []eqStruct.TermPair { debug(Lib.MkLazy(func() string { return fmt.Sprintf( "Searching unfication between %v and the eq tree", @@ -189,7 +220,9 @@ func searchUnifBewteenListAndEq(tl Lib.List[AST.Term], tree Unif.DataStructure) Lib.MkLazy(func() string { return "------------------------------------------" }), ) debug( - Lib.MkLazy(func() string { return fmt.Sprintf("Current subterm : %v", t_prime.ToString()) }), + Lib.MkLazy( + func() string { return fmt.Sprintf("Current subterm : %v", t_prime.ToString()) }, + ), ) if !t_prime.IsMeta() { res, tl := checkUnifInTree(t_prime, tree) @@ -199,7 +232,9 @@ func searchUnifBewteenListAndEq(tl Lib.List[AST.Term], tree Unif.DataStructure) ) for _, t := range tl.GetSlice() { debug( - Lib.MkLazy(func() string { return fmt.Sprintf("Unif found with : %v", t.ToString()) }), + Lib.MkLazy( + func() string { return fmt.Sprintf("Unif found with : %v", t.ToString()) }, + ), ) term_pair_list = append(term_pair_list, eqStruct.MakeTermPair(t_prime, t)) } diff --git a/src/Mods/gs3/dependency.go b/src/Mods/gs3/dependency.go deleted file mode 100644 index 80209233..00000000 --- a/src/Mods/gs3/dependency.go +++ /dev/null @@ -1,248 +0,0 @@ -/** -* Copyright 2022 by the authors (see AUTHORS). -* -* Goéland is an automated theorem prover for first order logic. -* -* This software is governed by the CeCILL license under French law and -* abiding by the rules of distribution of free software. You can use, -* modify and/ or redistribute the software under the terms of the CeCILL -* license as circulated by CEA, CNRS and INRIA at the following URL -* "http://www.cecill.info". -* -* As a counterpart to the access to the source code and rights to copy, -* modify and redistribute granted by the license, users are provided only -* with a limited warranty and the software's author, the holder of the -* economic rights, and the successive licensors have only limited -* liability. -* -* In this respect, the user's attention is drawn to the risks associated -* with loading, using, modifying and/or developing or reproducing the -* software by the user in light of its specific status of free software, -* that may mean that it is complicated to manipulate, and that also -* therefore means that it is reserved for developers and experienced -* professionals having in-depth computer knowledge. Users are therefore -* encouraged to load and test the software's suitability as regards their -* requirements in conditions enabling the security of their systems and/or -* data to be ensured and, more generally, to use and operate it in the -* same conditions as regards security. -* -* The fact that you are presently reading this means that you have had -* knowledge of the CeCILL license and that you accept its terms. -**/ -package gs3 - -import ( - "github.com/GoelandProver/Goeland/AST" - "github.com/GoelandProver/Goeland/Glob" - "github.com/GoelandProver/Goeland/Lib" -) - -const ( - IS_ALL = iota - IS_EXISTS -) - -type occurrence []int -type occurrences []occurrence - -// ---------------------------------------------------------------------------- -// The gamma-formulas case. -// ---------------------------------------------------------------------------- - -func manageGammasInstantiations(initialForm, resultForm AST.Form) AST.Term { - var term AST.Term - normalisedInitialForm := getNextFormula(initialForm.Copy()) - //PrintInfo("FORMS", fmt.Sprintf("init: %s, result: %s", initialForm.ToString(), resultForm.ToString())) - switch initialGamma := initialForm.(type) { - case AST.All: - term = getResultTerm(initialGamma.GetVarList().At(0), normalisedInitialForm, resultForm) - case AST.Not: - if ex, ok := initialGamma.GetForm().(AST.Ex); ok { - term = getResultTerm(ex.GetVarList().At(0), normalisedInitialForm, resultForm) - } - } - //PrintInfo("TERM", fmt.Sprintf("Term: %s ; Result: %s", term.ToString(), resultForm.ToString())) - return term -} - -// ---------------------------------------------------------------------------- -// The delta-formula case -// ---------------------------------------------------------------------------- - -func manageDeltasSkolemisations(initialForm, resultForm AST.Form) AST.Term { - var term AST.Term - normalisedInitialForm := getNextFormula(initialForm.Copy()) - switch initialDelta := initialForm.(type) { - case AST.Ex: - term = getResultTerm(initialDelta.GetVarList().At(0), normalisedInitialForm, resultForm) - case AST.Not: - if all, ok := initialDelta.GetForm().(AST.All); ok { - term = getResultTerm(all.GetVarList().At(0), normalisedInitialForm, resultForm) - } - } - return term -} - -// ---------------------------------------------------------------------------- -// Utilitary functions -// ---------------------------------------------------------------------------- - -func getNextFormula(form AST.Form) AST.Form { - switch f := form.(type) { - case AST.All: - varList := f.GetVarList() - if varList.Len() > 1 { - return AST.MakerAll(varList.Slice(1, varList.Len()), f.GetForm()) - } - return f.GetForm() - case AST.Ex: - varList := f.GetVarList() - if varList.Len() > 1 { - return AST.MakerEx(varList.Slice(1, varList.Len()), f.GetForm()) - } - return f.GetForm() - case AST.Not: - return AST.MakerNot(getNextFormula(f.GetForm())) - } - return form -} - -func getResultTerm(v AST.TypedVar, bareForm, endForm AST.Form) AST.Term { - variablesOccurrences := getAllVariableOccurrences(v, bareForm) - return getTermAt(endForm, variablesOccurrences) -} - -// Explores the form and if a variable in the varlist is found, returns its occurrence. -func getAllVariableOccurrences(v AST.TypedVar, form AST.Form) occurrences { - return getVariableOccurrencesForm(v, form, occurrences{}, occurrence{}) -} - -func getVariableOccurrencesForm(v AST.TypedVar, form AST.Form, currentOcc occurrences, path occurrence) occurrences { - workingPath := make(occurrence, len(path)) - copy(workingPath, path) - switch f := form.(type) { - case AST.Pred: - for i, term := range f.GetArgs().GetSlice() { - currentOcc = getVariableOccurrencesTerm(v, term, currentOcc, appcp(workingPath, i)) - } - case AST.Not: - currentOcc = getUnaryOcc(v, f.GetForm(), currentOcc, workingPath) - case AST.And: - currentOcc = getNAryOcc(v, currentOcc, workingPath, f.GetChildFormulas()) - case AST.Or: - currentOcc = getNAryOcc(v, currentOcc, workingPath, f.GetChildFormulas()) - case AST.Imp: - currentOcc = getNAryOcc(v, currentOcc, workingPath, Lib.MkListV(f.GetF1(), f.GetF2())) - case AST.Equ: - currentOcc = getNAryOcc(v, currentOcc, workingPath, Lib.MkListV(f.GetF1(), f.GetF2())) - case AST.All: - currentOcc = getUnaryOcc(v, f.GetForm(), currentOcc, workingPath) - case AST.Ex: - currentOcc = getUnaryOcc(v, f.GetForm(), currentOcc, workingPath) - } - return currentOcc -} - -func getUnaryOcc(v AST.TypedVar, form AST.Form, currentOcc occurrences, path occurrence) occurrences { - return getVariableOccurrencesForm(v, form, currentOcc, append(path, 0)) -} - -func getNAryOcc(v AST.TypedVar, currentOcc occurrences, path occurrence, fl Lib.List[AST.Form]) occurrences { - for i, nf := range fl.GetSlice() { - currentOcc = getVariableOccurrencesForm(v, nf, currentOcc, appcp(path, i)) - } - return currentOcc -} - -func getVariableOccurrencesTerm(v AST.TypedVar, term AST.Term, currentOcc occurrences, path occurrence) occurrences { - workingPath := make(occurrence, len(path)) - copy(workingPath, path) - switch t := term.(type) { - case AST.Var: - if t.Equals(v.ToBoundVar()) { - currentOcc = append(currentOcc, workingPath) - } - case AST.Fun: - for i, nt := range t.GetArgs().GetSlice() { - currentOcc = getVariableOccurrencesTerm(v, nt, currentOcc, appcp(workingPath, i)) - } - } - return currentOcc -} - -func getTermAt(form AST.Form, occsArr occurrences) AST.Term { - var term AST.Term - for _, occ := range occsArr { - t := getTermAux(form, occ) - if term != nil { - if !term.Equals(t) { - Glob.PrintError("GTA", "The same variable is instanciated as two different terms.") - } - } else { - term = t - } - } - return term -} - -func getTermAux(form AST.Form, occ occurrence) AST.Term { - var term AST.Term - - switch f := form.(type) { - case AST.Pred: - if occ[0] < f.GetArgs().Len() { - term = getTerm(f.GetArgs().At(occ[0]), occ[1:]) - } - case AST.Not: - term = getUnaryTerm(f.GetForm(), occ) - case AST.And: - term = getNAryTerm(f.GetChildFormulas(), occ) - case AST.Or: - term = getNAryTerm(f.GetChildFormulas(), occ) - case AST.Imp: - term = getNAryTerm(Lib.MkListV(f.GetF1(), f.GetF2()), occ) - case AST.Equ: - term = getNAryTerm(Lib.MkListV(f.GetF1(), f.GetF2()), occ) - case AST.All: - term = getUnaryTerm(f.GetForm(), occ) - case AST.Ex: - term = getUnaryTerm(f.GetForm(), occ) - } - return term -} - -func getUnaryTerm(form AST.Form, occ occurrence) AST.Term { - if occ[0] > 0 { - return nil - } - - return getTermAux(form, occ[1:]) -} - -func getNAryTerm(fl Lib.List[AST.Form], occ occurrence) AST.Term { - if occ[0] >= fl.Len() { - return nil - } - - return getTermAux(fl.At(occ[0]), occ[1:]) -} - -func getTerm(term AST.Term, occ occurrence) AST.Term { - if len(occ) == 0 { - return term - } - - if fn, ok := term.(AST.Fun); ok { - if occ[0] >= fn.GetArgs().Len() { - return nil - } - return getTerm(fn.GetArgs().At(occ[0]), occ[1:]) - } - return nil -} - -func appcp[T any](arr []T, el ...T) []T { - cp := make([]T, len(arr)) - copy(cp, arr) - return append(cp, el...) -} diff --git a/src/Mods/gs3/graph.go b/src/Mods/gs3/graph.go deleted file mode 100644 index 908c13ce..00000000 --- a/src/Mods/gs3/graph.go +++ /dev/null @@ -1,162 +0,0 @@ -/** - * Copyright 2022 by the authors (see AUTHORS). -* -* Goéland is an automated theorem prover for first order logic. -* -* This software is governed by the CeCILL license under French law and -* abiding by the rules of distribution of free software. You can use, -* modify and/ or redistribute the software under the terms of the CeCILL -* license as circulated by CEA, CNRS and INRIA at the following URL -* "http://www.cecill.info". -* -* As a counterpart to the access to the source code and rights to copy, -* modify and redistribute granted by the license, users are provided only -* with a limited warranty and the software's author, the holder of the -* economic rights, and the successive licensors have only limited -* liability. -* -* In this respect, the user's attention is drawn to the risks associated -* with loading, using, modifying and/or developing or reproducing the -* software by the user in light of its specific status of free software, -* that may mean that it is complicated to manipulate, and that also -* therefore means that it is reserved for developers and experienced -* professionals having in-depth computer knowledge. Users are therefore -* encouraged to load and test the software's suitability as regards their -* requirements in conditions enabling the security of their systems and/or -* data to be ensured and, more generally, to use and operate it in the -* same conditions as regards security. -* -* The fact that you are presently reading this means that you have had -* knowledge of the CeCILL license and that you accept its terms. - **/ - -/** - * This file provides a definition of a polymorphic graph. - **/ - -package gs3 - -import ( - "reflect" -) - -type Graph[T any] struct { - vertices []T - edges [][]int -} - -// ---------------------------------------------------------------------------- -// Public methods -// ---------------------------------------------------------------------------- - -func MakeGraph[T any]() Graph[T] { - g := Graph[T]{} - g.vertices = make([]T, 0) - g.edges = make([][]int, 0) - return g -} - -func (g *Graph[T]) AddVertex(u T) { - g.vertices = append(g.vertices, u) -} - -func (g *Graph[T]) AddEdge(u, v T) { - ux := g.findVertex(u) - vx := g.findVertex(v) - - if ux == -1 { - ux = g.addVertexAndResize(u) - } - if vx == -1 { - vx = g.addVertexAndResize(v) - } - - g.edges[ux] = append(g.edges[ux], vx) -} - -func (g Graph[T]) Copy() Graph[T] { - oth := Graph[T]{} - oth.vertices = make([]T, len(g.vertices)) - copy(oth.vertices, g.vertices) - oth.edges = make([][]int, len(g.edges)) - for i, ls := range g.edges { - oth.edges[i] = make([]int, len(ls)) - copy(oth.edges[i], ls) - } - return oth -} - -func (g Graph[T]) DepthFirstSearch(source T) []T { - return g.DepthFirstSearchList([]T{source}) -} - -func (g Graph[T]) DepthFirstSearchList(sources []T) []T { - seen := make([]bool, len(g.vertices)) - for _, source := range sources { - sourceIndex := g.findVertex(source) - if sourceIndex != -1 { - g.dfsAux(&seen, sourceIndex) - } - } - elementsSeen := []T{} - for i, v := range seen { - if v { - elementsSeen = append(elementsSeen, g.vertices[i]) - } - } - return elementsSeen -} - -func (g *Graph[T]) CleanEdgesFromVertex(u T) { - v := g.findVertex(u) - - if v == -1 { - return - } - - g.edges[v] = make([]int, 0) - - for i, neighbors := range g.edges { - for j, neighbor := range neighbors { - if neighbor == v { - g.edges[i] = append(g.edges[i][:j], g.edges[i][j+1:]...) - break - } - } - } -} - -// ---------------------------------------------------------------------------- -// Private methods -// ---------------------------------------------------------------------------- - -func (g Graph[T]) findVertex(u T) int { - index := -1 - for i, v := range g.vertices { - if reflect.DeepEqual(u, v) { - index = i - break - } - } - return index -} - -func (g *Graph[T]) addVertexAndResize(u T) int { - g.vertices = append(g.vertices, u) - - for len(g.edges) < len(g.vertices) { - g.edges = append(g.edges, make([]int, 0)) - } - - return len(g.vertices) - 1 -} - -func (g Graph[T]) dfsAux(seen *[]bool, src int) { - (*seen)[src] = true - - for _, n := range g.edges[src] { - if !(*seen)[n] { - g.dfsAux(seen, n) - } - } -} diff --git a/src/Mods/gs3/proof.go b/src/Mods/gs3/proof.go deleted file mode 100644 index feaee1e3..00000000 --- a/src/Mods/gs3/proof.go +++ /dev/null @@ -1,724 +0,0 @@ -/** - * Copyright 2022 by the authors (see AUTHORS). -* -* Goéland is an automated theorem prover for first order logic. -* -* This software is governed by the CeCILL license under French law and -* abiding by the rules of distribution of free software. You can use, -* modify and/ or redistribute the software under the terms of the CeCILL -* license as circulated by CEA, CNRS and INRIA at the following URL -* "http://www.cecill.info". -* -* As a counterpart to the access to the source code and rights to copy, -* modify and redistribute granted by the license, users are provided only -* with a limited warranty and the software's author, the holder of the -* economic rights, and the successive licensors have only limited -* liability. -* -* In this respect, the user's attention is drawn to the risks associated -* with loading, using, modifying and/or developing or reproducing the -* software by the user in light of its specific status of free software, -* that may mean that it is complicated to manipulate, and that also -* therefore means that it is reserved for developers and experienced -* professionals having in-depth computer knowledge. Users are therefore -* encouraged to load and test the software's suitability as regards their -* requirements in conditions enabling the security of their systems and/or -* data to be ensured and, more generally, to use and operate it in the -* same conditions as regards security. -* -* The fact that you are presently reading this means that you have had -* knowledge of the CeCILL license and that you accept its terms. - **/ - -/** - * This file provides a definition of a GS3 proof: the object & the exported functions. - **/ - -package gs3 - -import ( - "strings" - - "fmt" - "github.com/GoelandProver/Goeland/AST" - "github.com/GoelandProver/Goeland/Core" - "github.com/GoelandProver/Goeland/Glob" - "github.com/GoelandProver/Goeland/Lib" - "github.com/GoelandProver/Goeland/Mods/dmt" - "github.com/GoelandProver/Goeland/Search" -) - -type dependencyMap []Glob.Pair[AST.Term, Lib.List[AST.Form]] - -func (d dependencyMap) Copy() dependencyMap { - oth := make([]Glob.Pair[AST.Term, Lib.List[AST.Form]], 0) - for _, v := range d { - if v.Fst != nil { - p := Glob.MakePair(v.Fst.Copy(), Lib.MkListV(v.Snd.GetSlice()...)) - oth = append(oth, p) - } - } - return oth -} - -func (d dependencyMap) Get(t AST.Term) (Lib.List[AST.Form], bool) { - for _, v := range d { - if v.Fst != nil && v.Fst.Equals(t) { - return v.Snd, true - } - } - return Lib.NewList[AST.Form](), false -} - -func (d *dependencyMap) Add(t AST.Term, f ...AST.Form) { - found := false - formList := Lib.MkListV(f...) - for i, v := range *d { - if v.Fst != nil && t != nil && v.Fst.Equals(t) { - formList.Append(v.Snd.GetSlice()...) - (*d)[i] = Glob.MakePair(t, formList) - found = true - } - } - - if !found { - *d = append(*d, Glob.MakePair(t, formList)) - } -} - -func (d *dependencyMap) Set(t AST.Term, fl Lib.List[AST.Form]) { - for i, v := range *d { - if v.Fst != nil && v.Fst.Equals(t) { - (*d)[i] = Glob.MakePair(t, fl) - } - } -} - -// Utilitary struct to build the proof. Keeps everything that's needed on a proofstep. -type GS3Proof struct { - dependency dependencyMap // Dependency graph for formulas - branchForms Lib.List[AST.Form] // The formulas generated at the current point in the proof. - rulesApplied []Glob.Pair[Rule, Search.ProofStruct] - lastNode *GS3Sequent - betaHisto []Glob.Pair[int, int] - deltaHisto []Glob.Pair[AST.Term, Glob.Pair[AST.Form, int]] -} - -var debug func(Lib.Lazy[string]) - -func InitDebugger() { - debug = Glob.CreateDebugger("GS3") -} - -var MakeGS3Proof = func(proof []Search.ProofStruct) *GS3Sequent { - gs3Proof := GS3Proof{ - rulesApplied: make([]Glob.Pair[Rule, Search.ProofStruct], 0), - betaHisto: make([]Glob.Pair[int, int], 0), - deltaHisto: make([]Glob.Pair[AST.Term, Glob.Pair[AST.Form, int]], 0), - branchForms: Lib.NewList[AST.Form](), - dependency: make([]Glob.Pair[AST.Term, Lib.List[AST.Form]], 0), - } - if Glob.IsLoaded("dmt") { - gs3Proof.branchForms.Append(dmt.GetRegisteredAxioms().GetSlice()...) - gs3Proof.branchForms.Append(proof[0].Formula.GetForm()) - } - sequent := gs3Proof.makeProof(proof) - return sequent -} - -func (gs GS3Proof) Copy() GS3Proof { - return GS3Proof{ - dependency: gs.dependency.Copy(), - branchForms: Lib.MkListV(appcp(gs.branchForms.GetSlice())...), - lastNode: nil, - rulesApplied: appcp(gs.rulesApplied), - betaHisto: appcp(gs.betaHisto), - deltaHisto: appcp(gs.deltaHisto), - } -} - -// ---------------------------------------------------------------------------- -// Private methods. -// ---------------------------------------------------------------------------- - -// Makes a GS3 proof from a Vizu proof. -func (gs GS3Proof) makeProof(proof []Search.ProofStruct) *GS3Sequent { - if len(proof) == 0 { - seq := MakeNewSequent() - seq.proof = gs.Copy() - return seq - } - subRoot := MakeNewSequent() - var resultFormulas []Lib.List[AST.Form] - if gs.branchForms.Len() == 0 { - gs.branchForms.Append(proof[0].Formula.GetForm()) - } - - // For each proofstep, create a node & populate which is a child of the last proofstep. - for _, prf := range proof { - resultFormulas = gs.makeProofOneStep(prf, subRoot) - } - - // The last proofstep is a branching proofstep, so launch makeProof back on each child. - for i, child := range proof[len(proof)-1].GetChildren() { - childProof := GS3Proof{ - dependency: gs.dependency.Copy(), - branchForms: Lib.MkListV(appcp(gs.branchForms.GetSlice(), resultFormulas[i].GetSlice()...)...), - lastNode: nil, - rulesApplied: appcp(gs.rulesApplied), - betaHisto: appcp(gs.betaHisto, Glob.MakePair(i, proof[len(proof)-1].GetNodeId())), - deltaHisto: appcp(gs.deltaHisto), - } - childRoot := childProof.makeProof(child) - if childRoot != nil { - gs.lastNode.addChild(childRoot) - } - } - - return subRoot -} - -// Returns a sequent and the result formulas. -func (gs *GS3Proof) makeProofOneStep(proofStep Search.ProofStruct, parent *GS3Sequent) []Lib.List[AST.Form] { - seq := MakeNewSequent() - seq.nodeId = proofStep.Node_id - - rule := proofStructRuleToGS3Rule(proofStep.GetRuleName()) - form := proofStep.GetFormula().GetForm() - - // TODO: manage rewrite rules: second return value of proofStructRuleToGS3Rule - switch rule { - // Immediate, just apply the rule. - case NNOT, NOR, NIMP, AND, NAND, NEQU, OR, IMP, EQU, AX, REWRITE: - seq.setAppliedRule(rule) - seq.SetTargetForm(form) - if rule == REWRITE { - seq.setRewrittenWith(proofStep.Id_dmt) - } - if parent.IsEmpty() { - *parent = *seq - seq = parent - } - // Be careful as one gamma rule may instantiate multiple variables. - case ALL, NEX: - seq = gs.manageGammaStep(proofStep, rule, parent) - // Be extra careful as it is a delta-rule - case NALL, EX: - form = gs.manageDeltaStep(proofStep, rule, parent) - seq = MakeNewSequent() - case W: - seq = gs.weakenForm(form) - case R: // Ignore this rule (reintroduction) - seq = MakeNewSequent() - } - - if !seq.IsEmpty() { - if gs.lastNode != nil { - gs.lastNode.addChild(seq) - } - gs.lastNode = seq - } - - // Manage the proof's rules, offspring graph & format the result formulas properly. - forms := gs.postTreatment(proofStep, rule) - - if !seq.IsEmpty() { - seq.setFormsGenerated(forms) - } - - // If the length is superior, then it's a branching rule and it needs to be taken care of in makeProof. - if IsAlphaRule(rule) || IsGammaRule(rule) || IsDeltaRule(rule) || rule == REWRITE { - gs.branchForms.Append(forms[0].GetSlice()...) - // If rule is rewrite: do not weaken the base form, as it is important to get when applying rules back. - // It may however induce bad weakenings. - // TODO: fix the bad weakenings in the sequent. - } - - seq.proof = gs.Copy() - - return forms -} - -func (gs *GS3Proof) manageGammaStep(proofStep Search.ProofStruct, rule Rule, seq *GS3Sequent) *GS3Sequent { - // Manage gamma: add all the gammas except the result formula to the thing - resultForm := proofStep.GetResultFormulas()[0].GetForms().At(0) - originForm := proofStep.GetFormula().GetForm() - // TODO: what happens if the result form doesn't care of what it's instantiated with? - // JRO: Should be OKAY as "nil" is returned if I understand everything properly. - term := manageGammasInstantiations(originForm, resultForm) - - for _, t := range getDepFromTerm(term).GetSlice() { - gs.dependency.Add(t, originForm) - } - - // Create all the next sequents needed. - s := MakeNewSequent() - s.setAppliedRule(rule) - s.SetTargetForm(originForm) - s.setTermGenerated(term) - - if seq.IsEmpty() { - *seq = *s - s = seq - } - - // Needed to have the right offspring tree when updating later - return s -} - -func getDepFromTerm(term AST.Term) Lib.List[AST.Term] { - if typedFun, ok := term.(AST.Fun); ok { - if strings.Contains(typedFun.GetID().GetName(), "sko") { - return Lib.MkListV[AST.Term](typedFun) - } - - res := Lib.NewList[AST.Term]() - - for _, t := range typedFun.GetArgs().GetSlice() { - res.Append(getDepFromTerm(t).GetSlice()...) - } - - return res - } - - return Lib.MkListV(term) -} - -// TODO: factorise this function to merge some steps that are similar between the two cases. -func (gs *GS3Proof) manageDeltaStep(proofStep Search.ProofStruct, rule Rule, parent *GS3Sequent) AST.Form { - originForm := proofStep.GetFormula().GetForm() - resultForm := proofStep.GetResultFormulas()[0].GetForms().At(0) - termGenerated := manageDeltasSkolemisations(proofStep.GetFormula().GetForm(), resultForm) - - if Glob.IsPreInnerSko() && !gs.termHasBeenIntroducedByBranch(termGenerated, proofStep.Node_id) { - return resultForm - } - - var deltaSeq *GS3Sequent - previousRulesApplied := appcp(gs.rulesApplied) - dependantForms, atLeastOneDependantForm := gs.getFormulasDependantFromTerm(termGenerated) - rulesApplied, offsprings := gs.getRulesAppliedInOrder(termGenerated, dependantForms, resultForm) - if atLeastOneDependantForm && len(rulesApplied) > 0 { - // If the delta-rule has already been applied before, remove the term. - var termPreviouslyInstantiated bool - offsprings, termPreviouslyInstantiated = gs.findInDeltaHisto(termGenerated, offsprings) - gs.weakenForms(offsprings, parent) - if termPreviouslyInstantiated { - gs.weakenTerm(termGenerated) - } - deltaSeq = gs.applyDeltaRule(originForm, resultForm, rule, termGenerated, proofStep.Node_id) - if parent.IsEmpty() { - *parent = *deltaSeq - deltaSeq = parent - gs.lastNode = deltaSeq - } else { - gs.lastNode.addChild(deltaSeq) - } - previousRulesApplied = append(previousRulesApplied, Glob.MakePair(rule, makeProofStructFrom(originForm, resultForm, rule))) - gs.lastNode = deltaSeq - gs.branchForms.Append(resultForm) - subRoot, childrenIndex := gs.applyRulesBack(previousRulesApplied, rulesApplied, offsprings) - if subRoot != nil { - gs.lastNode.addChild(subRoot) - deltaSeq = gs.getLastSequent(subRoot, childrenIndex) - } - } else { - forms, rulesBack := gs.weakenAllFormsRelatedToTheTerm(termGenerated) - if forms.Len() > 0 { - gs.weakenForms(forms, parent) - } - _, inHist := gs.findInDeltaHisto(termGenerated, forms) - if inHist { - gs.weakenTerm(termGenerated) - if parent.IsEmpty() { - *parent = *gs.lastNode - gs.lastNode = parent - } - } - deltaSeq = gs.applyDeltaRule(originForm, resultForm, rule, termGenerated, proofStep.Node_id) - if parent.IsEmpty() { - *parent = *deltaSeq - deltaSeq = parent - } - if gs.lastNode != nil { - gs.lastNode.addChild(deltaSeq) - } - if len(rulesBack) > 0 { - subRoot, childrenIndex := gs.applyRulesBack(gs.rulesApplied, rulesBack, forms) - if subRoot != nil { - deltaSeq.addChild(subRoot) - deltaSeq = gs.getLastSequent(subRoot, childrenIndex) - } - } - } - gs.lastNode = deltaSeq - gs.rulesApplied = previousRulesApplied - return resultForm -} - -func (gs *GS3Proof) postTreatment(proofStep Search.ProofStruct, rule Rule) []Lib.List[AST.Form] { - // Add the rule applied & the formula it has been applied on. - gs.rulesApplied = append(gs.rulesApplied, Glob.MakePair(rule, proofStep)) - - var forms []Lib.List[AST.Form] - for i, fs := range proofStep.GetResultFormulas() { - forms = append(forms, fs.GetForms()) - if (rule == NOR || rule == NIMP || rule == AND || rule == EQU) && forms[i].Len() == 1 { - forms[i].Append(forms[i].At(0).Copy()) - } - } - - return forms -} - -func makeProofStructFrom(f, nf AST.Form, rule Rule) Search.ProofStruct { - proofStruct := Search.MakeEmptyProofStruct() - proofStruct.Formula = Core.MakeFormAndTerm(f, Lib.NewList[AST.Term]()) - proofStruct.Result_formulas = []Search.IntFormAndTermsList{ - Search.MakeIntFormAndTermsList( - 0, - Core.MakeSingleElementFormAndTermList(Core.MakeFormAndTerm( - nf, - Lib.NewList[AST.Term]()), - ))} - proofStruct.Rule_name = rule.ToString() - return proofStruct -} - -func (gs GS3Proof) getFormulasDependantFromTerm(term AST.Term) (Lib.List[AST.Form], bool) { - fs, ok := gs.dependency.Get(term) - return fs, ok -} - -func (gs GS3Proof) getRulesAppliedInOrder(term AST.Term, dependantForms Lib.List[AST.Form], deltaForm AST.Form) ([]Glob.Pair[Rule, Search.ProofStruct], Lib.List[AST.Form]) { - offsprings := gs.getOffspringsOf(term) - rules := []Glob.Pair[Rule, Search.ProofStruct]{} - for _, rule := range gs.rulesApplied { - f := rule.Snd.GetFormula().GetForm() - if !f.Equals(deltaForm) && (Lib.ListMem(f, offsprings) || Lib.ListMem(f, dependantForms)) { - rules = append(rules, rule) - } - } - - return rules, offsprings -} - -func (gs GS3Proof) getOffspringsOf(term AST.Term) Lib.List[AST.Form] { - offsprings := Lib.NewList[AST.Form]() - for _, form := range gs.branchForms.GetSlice() { - if form.GetSubTerms().Contains(term, AST.TermEquals) { - offsprings.Append(form) - } - } - return offsprings -} - -func (gs *GS3Proof) weakenForms(forms Lib.List[AST.Form], parent *GS3Sequent) *GS3Sequent { - for i, form := range forms.GetSlice() { - newSeq := gs.weakenForm(form) - if newSeq != nil { - if i == 0 && parent.IsEmpty() { - *parent = *newSeq - newSeq = parent - } else if gs.lastNode != nil { - gs.lastNode.addChild(newSeq) - } - gs.lastNode = newSeq - } - } - return gs.lastNode -} - -func (gs *GS3Proof) weakenForm(form AST.Form) *GS3Sequent { - seq := MakeNewSequent() - seq.setAppliedRule(W) - seq.SetTargetForm(form) - - gs.removeHypothesis(form) - gs.removeDependency(form) - gs.removeRuleAppliedOn(form) - - seq.proof = gs.Copy() - - return seq -} - -func (gs *GS3Proof) weakenTerm(term AST.Term) *GS3Sequent { - seq := MakeNewSequent() - seq.setAppliedRule(W) - seq.setTermGenerated(term) - - gs.removeFromDeltaHisto(term) - - if gs.lastNode != nil { - gs.lastNode.addChild(seq) - } - gs.lastNode = seq - seq.proof = gs.Copy() - return seq -} - -func (gs *GS3Proof) removeHypothesis(form AST.Form) { - index := Lib.ListIndexOf(form, gs.branchForms) - switch i := index.(type) { - case Lib.Some[int]: - gs.branchForms = gs.branchForms.RemoveAt(i.Val) - case Lib.None[int]: - Glob.PrintWarn("gs3", fmt.Sprintf("Hypothesis %s not found", form.ToString())) - } -} - -func (gs *GS3Proof) removeDependency(form AST.Form) { - for _, v := range gs.dependency { - if v.Fst != nil { - ls, _ := gs.dependency.Get(v.Fst) - removed := Lib.ListCpy(ls) - nb_rm := 0 - for i, f := range v.Snd.GetSlice() { - if f.Equals(form) { - removed.RemoveAt(i - nb_rm) - nb_rm++ - } - } - gs.dependency.Set(v.Fst, removed) - } - } -} - -func (gs *GS3Proof) removeRuleAppliedOn(form AST.Form) { - for i, rule := range gs.rulesApplied { - if rule.Snd.GetFormula().GetForm().Equals(form) { - gs.rulesApplied = append(gs.rulesApplied[:i], gs.rulesApplied[i+1:]...) - break - } - } -} - -func (gs *GS3Proof) applyDeltaRule(form, result AST.Form, rule Rule, term AST.Term, nodeId int) *GS3Sequent { - seq := MakeNewSequent() - seq.setAppliedRule(rule) - seq.SetTargetForm(form) - seq.setTermGenerated(term) - seq.setFormsGenerated([]Lib.List[AST.Form]{Lib.MkListV(result)}) - - gs.branchForms.Append(result) - gs.deltaHisto = append(gs.deltaHisto, Glob.MakePair(term, Glob.MakePair(result, nodeId))) - gs.rulesApplied = append(gs.rulesApplied, Glob.MakePair(rule, makeProofStructFrom(form, result, rule))) - - seq.proof = gs.Copy() - - return seq -} - -func (gs GS3Proof) applyRulesBack(rulesApplied, rulesToApply []Glob.Pair[Rule, Search.ProofStruct], weakenedForms Lib.List[AST.Form]) (*GS3Sequent, []int) { - // Transform everything back to a proof struct & call makeProof on it. - // We need to have the right proofstructs here: the proofstructs of the branches that is not this one - // on the beta formulas. - // It should fit properly so it's good - // Just need to weaken tho - proof, childrenIndex := gs.rebuildProof(rulesApplied, rulesToApply, weakenedForms) - gs.lastNode = nil - return gs.makeProof(proof), childrenIndex -} - -func (gs *GS3Proof) rebuildProof(rulesApplied, rules []Glob.Pair[Rule, Search.ProofStruct], weakenedForms Lib.List[AST.Form]) ([]Search.ProofStruct, []int) { - rebuiltProof := make([]Search.ProofStruct, 0) - childrenIndex := make([]int, 0) - for i, rule := range rules { - // These rules correspond to a beta-rule. - if rule.Fst == NAND || rule.Fst == NEQU || rule.Fst == EQU || rule.Fst == OR || rule.Fst == IMP { - node := rule.Snd.Copy() - currentBranchChildId := gs.getCurrentBranchChildId(node.GetNodeId()) - for j := range node.Children { - if j == currentBranchChildId { - childrenIndex = append(childrenIndex, j) - if i+1 < len(rules) { - var children []int - node.Children[j], children = gs.rebuildProof(rulesApplied, rules[i+1:], weakenedForms) - childrenIndex = append(childrenIndex, children...) - } else { - node.Children[j] = make([]Search.ProofStruct, 0) - } - } else { - // Weaken the formulas that shouldn't be here, i.e. the ones generated after. - formsToWeaken := gs.getFormsToWeaken(rulesApplied, rules[i:]) - node.Children[j] = append(makeWeakeningProofStructs(formsToWeaken), node.Children[j]...) - } - } - // Put the child to the left, to make it easy to find it back later. - rebuiltProof = append(rebuiltProof, node) - break - } else { - rebuiltProof = append(rebuiltProof, rule.Snd) - } - } - return rebuiltProof, childrenIndex -} - -func (gs GS3Proof) getCurrentBranchChildId(id int) int { - for _, beta := range gs.betaHisto { - if beta.Snd == id { - return beta.Fst - } - } - return -1 -} - -func (gs GS3Proof) getFormsToWeaken(rulesApplied, rulesAlreadyWeakened []Glob.Pair[Rule, Search.ProofStruct]) Lib.List[AST.Form] { - formsToWeaken := Lib.NewList[AST.Form]() - rule := getFirstRuleAppliedAfter(gs.rulesApplied, rulesAlreadyWeakened[0]) - canBeAppending := false - for _, r := range gs.rulesApplied { - if equalRulePair(r, rule) { - canBeAppending = true - } - if canBeAppending { - if !Glob.IsPreInnerSko() || !(rule.Fst == EX || rule.Fst == NALL) { - formsToWeaken.Append( - gs.getIntersectionBetweenResultAndBranchForms(rule.Snd.GetResultFormulas()).GetSlice()...) - } - } - } - return formsToWeaken -} - -func getFirstRuleAppliedAfter(rulesApplied []Glob.Pair[Rule, Search.ProofStruct], firstRuleWeakened Glob.Pair[Rule, Search.ProofStruct]) Glob.Pair[Rule, Search.ProofStruct] { - for i, rule := range rulesApplied { - if equalRulePair(rule, firstRuleWeakened) && i < len(rulesApplied) { - return rulesApplied[i+1] - } - } - return Glob.Pair[Rule, Search.ProofStruct]{} -} - -func (gs GS3Proof) getIntersectionBetweenResultAndBranchForms(forms []Search.IntFormAndTermsList) Lib.List[AST.Form] { - fs := Lib.NewList[AST.Form]() - for _, fl := range forms { - for _, f := range fl.GetForms().GetSlice() { - if Lib.ListMem(f, gs.branchForms) { - fs.Append(f) - } - } - } - return fs -} - -func equalRulePair(a, b Glob.Pair[Rule, Search.ProofStruct]) bool { - return a.Fst == b.Fst && a.Snd.Formula.GetForm().Equals(b.Snd.Formula.GetForm()) -} - -func makeWeakeningProofStructs(forms Lib.List[AST.Form]) []Search.ProofStruct { - resultingProof := make([]Search.ProofStruct, 0) - for _, f := range forms.GetSlice() { - proofStruct := Search.MakeEmptyProofStruct() - proofStruct.SetFormulaProof(Core.MakeFormAndTerm( - f, - Lib.NewList[AST.Term]()), - ) - proofStruct.SetRuleNameProof("WEAKEN") - resultingProof = append(resultingProof, proofStruct) - } - return resultingProof -} - -func (gs *GS3Proof) getLastSequent(seq *GS3Sequent, childrenIndex []int) *GS3Sequent { - //PrintInfo("GETLASTSEQ", "") - i := 0 - for len(seq.children) > 0 { - if IsBetaRule(seq.rule) { - index := gs.findInBetaHist(seq.nodeId) - if index == -1 { - index = childrenIndex[i] - i++ - } - seq = seq.children[index] - } else { - seq = seq.children[0] - } - //PrintInfo("SEQ", fmt.Sprintf("%v", seq)) - } - *gs = seq.proof - return seq -} - -func (gs GS3Proof) findInBetaHist(id int) int { - for _, pair := range gs.betaHisto { - if pair.Snd == id { - return pair.Fst - } - } - return -1 -} - -func getAllFormulasDependantOn(term AST.Term, form AST.Form) Lib.List[AST.Form] { - switch f := form.(type) { - case AST.All: - return getSubformulas(term, f.GetVarList().At(0), f.GetForm()) - case AST.Not: - if ex, isEx := f.GetForm().(AST.Ex); isEx { - return getSubformulas(term, ex.GetVarList().At(0), AST.MakerNot(f.GetForm())) - } - } - return Lib.NewList[AST.Form]() -} - -func getSubformulas(term AST.Term, v AST.TypedVar, form AST.Form) Lib.List[AST.Form] { - subforms := form.GetSubFormulasRecur() - dependantSubforms := Lib.NewList[AST.Form]() - for _, f := range subforms.GetSlice() { - f, res := f.ReplaceTermByTerm(v.ToBoundVar(), term) - if res { - dependantSubforms.Append(f) - } - } - return dependantSubforms -} - -func (gs GS3Proof) findInDeltaHisto(term AST.Term, forms Lib.List[AST.Form]) (Lib.List[AST.Form], bool) { - for _, p := range gs.deltaHisto { - if p.Fst != nil && p.Fst.Equals(term) { - result := Lib.ListCpy(forms) - result.Append(p.Snd.Fst) - return result, true - } - } - return forms, false -} - -func (gs *GS3Proof) removeFromDeltaHisto(term AST.Term) { - for i, p := range gs.deltaHisto { - if p.Fst != nil && p.Fst.Equals(term) { - gs.deltaHisto = append(gs.deltaHisto[:i], gs.deltaHisto[i+1:]...) - } - } -} - -func (gs *GS3Proof) weakenAllFormsRelatedToTheTerm(term AST.Term) (Lib.List[AST.Form], []Glob.Pair[Rule, Search.ProofStruct]) { - rules := []Glob.Pair[Rule, Search.ProofStruct]{} - forms := Lib.NewList[AST.Form]() - for _, form := range gs.branchForms.GetSlice() { - if form.GetSubTerms().Contains(term, AST.TermEquals) { - // Get the rule to apply it back - for _, rule := range gs.rulesApplied { - f := rule.Snd.GetFormula().GetForm() - if f.Equals(form) { - rules = append(rules, rule) - } - } - forms.Append(form) - } - } - return forms, rules -} - -func (gs GS3Proof) termHasBeenIntroducedByBranch(term AST.Term, nodeId int) bool { - for _, p := range gs.deltaHisto { - if p.Fst.Equals(term) { - // DMT needs the nodeId here, as the same formula will produce the same skolem symbol in two different - // branches potentially. - return p.Snd.Snd == nodeId - } - } - // Term has not been introduced yet, as such it has been introduced by the current branch - return true -} diff --git a/src/Mods/gs3/sequent.go b/src/Mods/gs3/sequent.go deleted file mode 100644 index 36b6125b..00000000 --- a/src/Mods/gs3/sequent.go +++ /dev/null @@ -1,310 +0,0 @@ -/** -* Copyright 2022 by the authors (see AUTHORS). -* -* Goéland is an automated theorem prover for first order logic. -* -* This software is governed by the CeCILL license under French law and -* abiding by the rules of distribution of free software. You can use, -* modify and/ or redistribute the software under the terms of the CeCILL -* license as circulated by CEA, CNRS and INRIA at the following URL -* "http://www.cecill.info". -* -* As a counterpart to the access to the source code and rights to copy, -* modify and redistribute granted by the license, users are provided only -* with a limited warranty and the software's author, the holder of the -* economic rights, and the successive licensors have only limited -* liability. -* -* In this respect, the user's attention is drawn to the risks associated -* with loading, using, modifying and/or developing or reproducing the -* software by the user in light of its specific status of free software, -* that may mean that it is complicated to manipulate, and that also -* therefore means that it is reserved for developers and experienced -* professionals having in-depth computer knowledge. Users are therefore -* encouraged to load and test the software's suitability as regards their -* requirements in conditions enabling the security of their systems and/or -* data to be ensured and, more generally, to use and operate it in the -* same conditions as regards security. -* -* The fact that you are presently reading this means that you have had -* knowledge of the CeCILL license and that you accept its terms. -**/ -package gs3 - -import ( - "strings" - - "github.com/GoelandProver/Goeland/AST" - "github.com/GoelandProver/Goeland/Glob" - "github.com/GoelandProver/Goeland/Lib" - "github.com/GoelandProver/Goeland/Mods/dmt" -) - -type GS3Sequent struct { - rule Rule - appliedOn AST.Form - rewriteWith AST.Form - termGenerated AST.Term - formsGenerated []Lib.List[AST.Form] - children []*GS3Sequent - proof GS3Proof - nodeId int -} - -type Rule int - -// Rules -const ( - AX Rule = iota - W - NOT - IMP - AND - OR - EQU - EX - ALL - NNOT - NIMP - NAND - NOR - NEQU - NEX - NALL - R - REWRITE -) - -func MakeNewSequent() *GS3Sequent { - seq := new(GS3Sequent) - seq.children = make([]*GS3Sequent, 0) - return seq -} - -func IsGammaRule(rule Rule) bool { - return rule == ALL || rule == NEX -} - -func IsDeltaRule(rule Rule) bool { - return rule == NALL || rule == EX -} - -func IsBetaRule(rule Rule) bool { - return rule == NAND || rule == NEQU || rule == IMP || rule == EQU || rule == OR -} - -func IsAlphaRule(rule Rule) bool { - return rule == AND || rule == NOR || rule == NIMP || rule == NNOT -} - -// ---------------------------------------------------------------------------- -// Public methods -// ---------------------------------------------------------------------------- - -func (seq *GS3Sequent) GetTargetForm() AST.Form { - return seq.appliedOn -} - -func (seq *GS3Sequent) Child(i int) *GS3Sequent { - return seq.children[i] -} - -func (seq *GS3Sequent) Children() []*GS3Sequent { - return seq.children -} - -func (seq *GS3Sequent) Rule() Rule { - return seq.rule -} - -func (seq *GS3Sequent) GetResultFormulasOfChild(i int) Lib.List[AST.Form] { - return seq.formsGenerated[i] -} - -func (seq *GS3Sequent) GetResultFormulasOfChildren() []Lib.List[AST.Form] { - result := []Lib.List[AST.Form]{} - - for i := range seq.children { - result = append(result, seq.formsGenerated[i]) - } - - return result -} - -func (seq *GS3Sequent) TermGenerated() AST.Term { - return seq.termGenerated -} - -func (seq *GS3Sequent) IsEmpty() bool { - return seq.appliedOn == nil -} - -func (seq *GS3Sequent) ToString() string { - return seq.toStringAux(0) -} - -func (seq *GS3Sequent) GetRewriteWith() AST.Form { - return seq.rewriteWith -} - -func (seq *GS3Sequent) GetId() int { - return seq.nodeId -} - -func (seq *GS3Sequent) SetId(i int) { - seq.nodeId = i -} - -func (seq *GS3Sequent) SetFormGenerated(fg []Lib.List[AST.Form]) { - seq.formsGenerated = fg -} - -func (seq *GS3Sequent) SetChildren(c []*GS3Sequent) { - seq.children = c -} - -func (seq *GS3Sequent) SetTargetForm(f AST.Form) { - seq.appliedOn = f -} - -func (seq *GS3Sequent) SetTermGenerated(t AST.Term) { - seq.termGenerated = t -} - -// ---------------------------------------------------------------------------- -// Private methods & functions -// ---------------------------------------------------------------------------- - -func (seq *GS3Sequent) setAppliedRule(rule Rule) { - seq.rule = rule -} - -func (seq *GS3Sequent) setTermGenerated(t AST.Term) { - seq.termGenerated = t -} - -func (seq *GS3Sequent) addChild(oth ...*GS3Sequent) { - seq.children = append(seq.children, oth...) -} - -func (seq *GS3Sequent) toStringAux(i int) string { - identation := strings.Repeat(" ", i) - status := seq.ruleToString(seq.rule) + " on " + seq.appliedOn.ToString() - if seq.IsEmpty() { - status = "EMPTY" - } - childrenStrings := make([]string, len(seq.children)) - for j, child := range seq.children { - if child != nil { - childrenStrings[j] = child.toStringAux(i + 1) - } - } - return "\n" + identation + status + strings.Join(childrenStrings, "") -} - -func (seq *GS3Sequent) ruleToString(rule Rule) string { - mapping := map[Rule]string{ - NNOT: "NOT_NOT (alpha)", - NOR: "NOT_OR (alpha)", - NIMP: "NOT_IMPLY (alpha)", - AND: "AND (alpha)", - NAND: "NOT_AND (beta)", - NEQU: "NOT_EQUIV (beta)", - OR: "OR (beta)", - IMP: "IMPLY (beta)", - EQU: "EQUIV (beta)", - NEX: "NOT_EXISTS (gamma)", - ALL: "FORALL (gamma)", - NALL: "NOT_FORALL (delta)", - EX: "EXISTS (delta)", - AX: "AXIOM", - W: "WEAKEN", - } - return mapping[rule] -} - -func (seq *GS3Sequent) setFormsGenerated(forms []Lib.List[AST.Form]) { - seq.formsGenerated = forms -} - -func proofStructRuleToGS3Rule(rule string) Rule { - mapping := map[string]Rule{ - "ALPHA_NOT_NOT": NNOT, - "ALPHA_NOT_OR": NOR, - "ALPHA_NOT_IMPLY": NIMP, - "ALPHA_AND": AND, - "BETA_NOT_AND": NAND, - "BETA_NOT_EQUIV": NEQU, - "BETA_OR": OR, - "BETA_IMPLY": IMP, - "BETA_EQUIV": EQU, - "GAMMA_NOT_EXISTS": NEX, - "GAMMA_FORALL": ALL, - "DELTA_NOT_FORALL": NALL, - "DELTA_EXISTS": EX, - "CLOSURE": AX, - "WEAKEN": W, - "Reintroduction": R, - "Rewrite": REWRITE, - } - return mapping[rule] -} - -func (rule Rule) ToString() string { - mapping := map[Rule]string{ - NNOT: "ALPHA_NOT_NOT", - NOR: "ALPHA_NOT_OR", - NIMP: "ALPHA_NOT_IMPLY", - AND: "ALPHA_AND", - NAND: "BETA_NOT_AND", - NEQU: "BETA_NOT_EQUIV", - OR: "BETA_OR", - IMP: "BETA_IMPLY", - EQU: "BETA_EQUIV", - NEX: "GAMMA_NOT_EXISTS", - ALL: "GAMMA_FORALL", - NALL: "DELTA_NOT_FORALL", - EX: "DELTA_EXISTS", - AX: "CLOSURE", - W: "WEAKEN", - REWRITE: "REWRITE", - } - return mapping[rule] -} - -func (seq *GS3Sequent) setRewrittenWith(rewriteId int) { - axioms := dmt.GetRegisteredAxioms() - for _, h := range axioms.GetSlice() { - endForm := h - for Glob.Is[AST.All](endForm) { - endForm = endForm.(AST.All).GetForm() - } - endForm = getAtomic(endForm) - if endForm.GetIndex() == rewriteId { - seq.rewriteWith = h - return - } - } - - panic("Failure: tried to rewrite using a missing axiom") -} - -func getAtomic(f AST.Form) AST.Form { - switch nf := f.(type) { - case AST.Imp: - if pred, isPred := nf.GetF1().(AST.Pred); isPred { - return pred - } - if pred, isPred := nf.GetF2().(AST.Pred); isPred { - return pred - } - case AST.Equ: - if pred, isPred := nf.GetF1().(AST.Pred); isPred { - return pred - } - if pred, isPred := nf.GetF2().(AST.Pred); isPred { - return pred - } - } - return f -} diff --git a/src/Mods/lambdapi/output.go b/src/Mods/lambdapi/output.go index 0f891d6a..403bd9de 100644 --- a/src/Mods/lambdapi/output.go +++ b/src/Mods/lambdapi/output.go @@ -39,13 +39,18 @@ import ( "github.com/GoelandProver/Goeland/AST" "github.com/GoelandProver/Goeland/Glob" "github.com/GoelandProver/Goeland/Lib" - "github.com/GoelandProver/Goeland/Mods/gs3" + "github.com/GoelandProver/Goeland/Mods/desko" "github.com/GoelandProver/Goeland/Search" ) var contextEnabled bool = false var debug Glob.Debugger -var LambdapiOutputProofStruct = &Search.OutputProofStruct{ProofOutput: MakeLambdapiOutput, Name: "Lambdapi", Extension: ".lp"} + +var LambdapiOutputProofStruct = &Search.OutputProofStruct{ + ProofOutput: MakeLambdapiOutput, + Name: "Lambdapi", + Extension: ".lp", +} // ---------------------------------------------------------------------------- // Plugin initialisation and main function to call. @@ -60,17 +65,13 @@ func InitDebugger() { debug = Glob.CreateDebugger("LambdaPi") } -func MakeLambdapiOutput(prf []Search.ProofStruct, meta Lib.List[AST.Meta]) string { - if len(prf) == 0 { - Glob.Fatal("LambdaPi", "Nothing to output") - } - +func MakeLambdapiOutput(prf Search.IProof, meta Lib.List[AST.Meta]) string { connectives := LambdapiPrinterConnectives() printer := AST.Printer{PrinterAction: LambdapiPrinterAction(), PrinterConnective: &connectives} AST.SetPrinter(printer) // Transform tableaux's proof in GS3 proof - return MakeLambdaPiProof(gs3.MakeGS3Proof(prf), meta) + return MakeLambdaPiProof(desko.MakeDeskolemizedProof(prf), meta) } func LambdapiPrinterConnectives() AST.PrinterConnective { @@ -173,9 +174,9 @@ func LambdapiPrinterAction() AST.PrinterAction { return lambdapi_action.Compose(AST.RemoveSuperfluousParenthesesAction(connectives)) } -var MakeLambdaPiProof = func(proof *gs3.GS3Sequent, meta Lib.List[AST.Meta]) string { - contextString := makeContextIfNeeded(proof.GetTargetForm(), meta) - proofString := makeLambdaPiProofFromGS3(proof) +var MakeLambdaPiProof = func(proof Search.IProof, meta Lib.List[AST.Meta]) string { + contextString := makeContextIfNeeded(proof.AppliedOn(), meta) + proofString := makeLambdaPiProofFromIProof(proof) return contextString + "\n" + proofString } diff --git a/src/Mods/lambdapi/proof.go b/src/Mods/lambdapi/proof.go index d8dcc6f1..3455ae4b 100644 --- a/src/Mods/lambdapi/proof.go +++ b/src/Mods/lambdapi/proof.go @@ -39,11 +39,11 @@ import ( "github.com/GoelandProver/Goeland/Glob" "github.com/GoelandProver/Goeland/Lib" "github.com/GoelandProver/Goeland/Mods/CertifUtils" - "github.com/GoelandProver/Goeland/Mods/gs3" + "github.com/GoelandProver/Goeland/Search" ) -func makeLambdaPiProofFromGS3(proof *gs3.GS3Sequent) string { - formula := proof.GetTargetForm() +func makeLambdaPiProofFromIProof(proof Search.IProof) string { + formula := proof.AppliedOn() axioms, conjecture := processMainFormula(formula) resulting_string, to_introduce := makeTheorem(axioms, conjecture) @@ -51,44 +51,50 @@ func makeLambdaPiProofFromGS3(proof *gs3.GS3Sequent) string { resulting_string += "begin\n " str, local_context := assume(to_introduce, context) if to_introduce.Len() != 1 { - proof = proof.Child(0) + proof = proof.Children().At(0) } return resulting_string + str + makeProofStep(proof, local_context) + "end;\n" } -func makeProofStep(proof *gs3.GS3Sequent, context Lib.List[AST.Form]) string { +func makeProofStep(proof Search.IProof, context Lib.List[AST.Form]) string { var resultingString string - switch proof.Rule() { - case gs3.AX: + switch proof.RuleApplied() { + case Search.RuleClosure: resultingString = closureAxiom(proof, context) - case gs3.NNOT: + case Search.RuleNotNot: resultingString = alphaNotNot(proof, context) - case gs3.AND: + case Search.RuleAnd: resultingString = alphaAnd(proof, context) - case gs3.NOR: + case Search.RuleNotOr: resultingString = alphaNotOr(proof, context) - case gs3.NIMP: + case Search.RuleNotImp: resultingString = alphaNotImp(proof, context) - case gs3.OR: + case Search.RuleOr: resultingString = betaOr(proof, context) - case gs3.NAND: + case Search.RuleNotAnd: resultingString = betaNotAnd(proof, context) - case gs3.IMP: + case Search.RuleImp: resultingString = betaImp(proof, context) - case gs3.EQU: + case Search.RuleEqu: resultingString = betaEqu(proof, context) - case gs3.NEQU: + case Search.RuleNotEqu: resultingString = betaNotEqu(proof, context) - case gs3.EX: + case Search.RuleEx: resultingString = deltaEx(proof, context) - case gs3.NALL: + case Search.RuleNotAll: resultingString = deltaNotAll(proof, context) - case gs3.ALL: + case Search.RuleAll: resultingString = gammaAll(proof, context) - case gs3.NEX: + case Search.RuleNotEx: resultingString = gammaNotEx(proof, context) default: - Glob.Fatal("LambdaPi", fmt.Sprintf("Translation of rule %s not implemented yet", proof.Rule().ToString())) + Glob.Fatal( + "LambdaPi", + fmt.Sprintf( + "Translation of rule %s not implemented yet", + proof.RuleApplied().ToString(), + ), + ) } return resultingString @@ -110,12 +116,12 @@ func refine(lemma string, arguments Lib.List[string], in_con string, goals int) return fmt.Sprintf(" refine %s %s %s %s\n", lemma, arguments_string, goals_string, in_con) } -func closureAxiom(proof *gs3.GS3Sequent, context Lib.List[AST.Form]) string { - if CertifUtils.IsPredEqual(proof.GetTargetForm()) { +func closureAxiom(proof Search.IProof, context Lib.List[AST.Form]) string { + if CertifUtils.IsPredEqual(proof.AppliedOn()) { Glob.Fatal("LambdaPi", "congruence closure is not implemented yet") } - target, notTarget := getPosAndNeg(proof.GetTargetForm()) + target, notTarget := getPosAndNeg(proof.AppliedOn()) result := "" switch target.(type) { case AST.Pred: @@ -140,20 +146,34 @@ func getPosAndNeg(target AST.Form) (pos, neg AST.Form) { return target, AST.MakerNot(target) } -func refineGenericRule(lemma string, proof *gs3.GS3Sequent, remaining_goals int, context Lib.List[AST.Form]) string { +func refineGenericRule( + lemma string, + proof Search.IProof, + remaining_goals int, + context Lib.List[AST.Form], +) string { formulas_list := Lib.NewList[string]() // If a term was generated, get its type and place the stuff in the right order: the type of // the generated term, the formula and then the term. - if gs3.IsGammaRule(proof.Rule()) || gs3.IsDeltaRule(proof.Rule()) { - ty := getTypeOfFirstBoundVar(proof.GetTargetForm()) - formated_child := getFormattedChild(proof.GetTargetForm()) - formulas_list = Lib.MkListV("("+strings.ReplaceAll(ty.ToString(), "τ", "")+")", "("+formated_child+")") - if gs3.IsGammaRule(proof.Rule()) { - // FIXME: use an option type instead of nil - if proof.TermGenerated() != nil { - formulas_list.Append(getFormattedTerm(proof.TermGenerated())) - } else { + if Search.KindOfRule(proof.RuleApplied()) == Search.KindGamma || + Search.KindOfRule(proof.RuleApplied()) == Search.KindDelta { + ty := getTypeOfFirstBoundVar(proof.AppliedOn()) + formated_child := getFormattedChild(proof.AppliedOn()) + formulas_list = Lib.MkListV( + "("+strings.ReplaceAll(ty.ToString(), "τ", "")+")", + "("+formated_child+")", + ) + if Search.KindOfRule(proof.RuleApplied()) == Search.KindGamma { + switch t := proof.TermGenerated().(type) { + case Lib.Some[Lib.Either[AST.Ty, AST.Term]]: + switch t0 := t.Val.(type) { + case Lib.Left[AST.Ty, AST.Term]: + Glob.Fatal("LambdaPi", "Not yet implemented") + case Lib.Right[AST.Ty, AST.Term]: + formulas_list.Append(getFormattedTerm(t0.Val)) + } + default: // Try to find something in the global env, otherwise: fail // FIXME: we should also try to find something in the local (term) environment // (this does not exist yet) @@ -164,14 +184,14 @@ func refineGenericRule(lemma string, proof *gs3.GS3Sequent, remaining_goals int, Glob.Fatal("LambdaPi", fmt.Sprintf( "no term of type %s available to instantiate the universal formula %s.", ty.ToString(), - proof.GetTargetForm().ToString(), + proof.AppliedOn().ToString(), )) } } } } else { - child_formulas := proof.GetTargetForm().GetChildFormulas() - switch f := proof.GetTargetForm().(type) { + child_formulas := proof.AppliedOn().GetChildFormulas() + switch f := proof.AppliedOn().(type) { case AST.Not: child_formulas = f.GetForm().GetChildFormulas() } @@ -180,22 +200,44 @@ func refineGenericRule(lemma string, proof *gs3.GS3Sequent, remaining_goals int, } } - result_string := refine(lemma, formulas_list, getFromLocalContext(proof.GetTargetForm(), context), remaining_goals) + result_string := refine( + lemma, + formulas_list, + getFromLocalContext(proof.AppliedOn(), context), + remaining_goals, + ) if remaining_goals <= 1 { result_string = result_string[:len(result_string)-1] + ";\n" - assumptions, con := assume(proof.GetResultFormulasOfChild(0), Lib.ListCpy(context)) - if gs3.IsDeltaRule(proof.Rule()) { - assumptions = fmt.Sprintf("assume %s;", getFormattedTerm(proof.TermGenerated())) + assumptions + assumptions, con := assume(proof.ResultFormulas().At(0), Lib.ListCpy(context)) + if Search.KindOfRule(proof.RuleApplied()) == Search.KindDelta { + var tm AST.Term + + switch t := proof.TermGenerated().(type) { + case Lib.None[Lib.Either[AST.Ty, AST.Term]]: + Glob.Fatal("LambdaPi", "output does not manage assuming empty terms") + case Lib.Some[Lib.Either[AST.Ty, AST.Term]]: + switch t0 := t.Val.(type) { + case Lib.Left[AST.Ty, AST.Term]: + Glob.Fatal("LambdaPi", "output does not manage assuming types") + case Lib.Right[AST.Ty, AST.Term]: + tm = t0.Val + } + } + + assumptions = fmt.Sprintf( + "assume %s;", + getFormattedTerm(tm), + ) + assumptions } result_string += assumptions - result_string += makeProofStep(proof.Child(0), con) + result_string += makeProofStep(proof.Children().At(0), con) } else { for i := 0; i < remaining_goals; i++ { result_string += "{\n" - assumptions, con := assume(proof.GetResultFormulasOfChild(i), Lib.ListCpy(context)) + assumptions, con := assume(proof.ResultFormulas().At(i), Lib.ListCpy(context)) result_string += assumptions - result_string += makeProofStep(proof.Child(i), con) + result_string += makeProofStep(proof.Children().At(i), con) result_string += "}\n" } result_string = result_string[:len(result_string)-1] + ";\n" @@ -301,63 +343,63 @@ func getFormattedChild(form AST.Form) string { return "" } -func refineUnaryRule(lemma string, proof *gs3.GS3Sequent, context Lib.List[AST.Form]) string { +func refineUnaryRule(lemma string, proof Search.IProof, context Lib.List[AST.Form]) string { return refineGenericRule(lemma, proof, 1, context) } -func refineBinaryRule(lemma string, proof *gs3.GS3Sequent, context Lib.List[AST.Form]) string { +func refineBinaryRule(lemma string, proof Search.IProof, context Lib.List[AST.Form]) string { return refineGenericRule(lemma, proof, 2, context) } -func alphaNotNot(proof *gs3.GS3Sequent, context Lib.List[AST.Form]) string { +func alphaNotNot(proof Search.IProof, context Lib.List[AST.Form]) string { return refineUnaryRule("GS3nnot", proof, context) } -func alphaAnd(proof *gs3.GS3Sequent, context Lib.List[AST.Form]) string { +func alphaAnd(proof Search.IProof, context Lib.List[AST.Form]) string { return refineUnaryRule("GS3and", proof, context) } -func alphaNotOr(proof *gs3.GS3Sequent, context Lib.List[AST.Form]) string { +func alphaNotOr(proof Search.IProof, context Lib.List[AST.Form]) string { return refineUnaryRule("GS3nor", proof, context) } -func alphaNotImp(proof *gs3.GS3Sequent, context Lib.List[AST.Form]) string { +func alphaNotImp(proof Search.IProof, context Lib.List[AST.Form]) string { return refineUnaryRule("GS3nimp", proof, context) } -func betaOr(proof *gs3.GS3Sequent, context Lib.List[AST.Form]) string { +func betaOr(proof Search.IProof, context Lib.List[AST.Form]) string { return refineBinaryRule("GS3or", proof, context) } -func betaNotAnd(proof *gs3.GS3Sequent, context Lib.List[AST.Form]) string { +func betaNotAnd(proof Search.IProof, context Lib.List[AST.Form]) string { return refineBinaryRule("GS3nand", proof, context) } -func betaImp(proof *gs3.GS3Sequent, context Lib.List[AST.Form]) string { +func betaImp(proof Search.IProof, context Lib.List[AST.Form]) string { return refineBinaryRule("GS3imp", proof, context) } -func betaEqu(proof *gs3.GS3Sequent, context Lib.List[AST.Form]) string { +func betaEqu(proof Search.IProof, context Lib.List[AST.Form]) string { return refineBinaryRule("GS3equ", proof, context) } -func betaNotEqu(proof *gs3.GS3Sequent, context Lib.List[AST.Form]) string { +func betaNotEqu(proof Search.IProof, context Lib.List[AST.Form]) string { return refineBinaryRule("GS3nequ", proof, context) } -func deltaEx(proof *gs3.GS3Sequent, context Lib.List[AST.Form]) string { +func deltaEx(proof Search.IProof, context Lib.List[AST.Form]) string { return refineUnaryRule("GS3ex", proof, context) } -func deltaNotAll(proof *gs3.GS3Sequent, context Lib.List[AST.Form]) string { +func deltaNotAll(proof Search.IProof, context Lib.List[AST.Form]) string { return refineUnaryRule("GS3nall", proof, context) } -func gammaAll(proof *gs3.GS3Sequent, context Lib.List[AST.Form]) string { +func gammaAll(proof Search.IProof, context Lib.List[AST.Form]) string { return refineUnaryRule("GS3all", proof, context) } -func gammaNotEx(proof *gs3.GS3Sequent, context Lib.List[AST.Form]) string { +func gammaNotEx(proof Search.IProof, context Lib.List[AST.Form]) string { return refineUnaryRule("GS3nex", proof, context) } diff --git a/src/Mods/rocq/context.go b/src/Mods/rocq/context.go index 27d185e3..6a6fbd39 100644 --- a/src/Mods/rocq/context.go +++ b/src/Mods/rocq/context.go @@ -91,8 +91,9 @@ func makeContextIfNeeded(root AST.Form, metaList Lib.List[AST.Meta]) string { func contextPreamble() string { str := lemmas - str += "Parameter goeland_U : Set. (* goeland's universe *)\n" + str += "Parameter goeland_U : Type. (* goeland's universe *)\n" str += "Parameter goeland_I : goeland_U. (* an individual in the universe. *)\n\n" + str += "Parameter goeland_T : Type. (* a witness type. *)\n\n" return str } diff --git a/src/Mods/rocq/output.go b/src/Mods/rocq/output.go index bea023d6..15cc569c 100644 --- a/src/Mods/rocq/output.go +++ b/src/Mods/rocq/output.go @@ -43,30 +43,36 @@ import ( "github.com/GoelandProver/Goeland/AST" "github.com/GoelandProver/Goeland/Glob" "github.com/GoelandProver/Goeland/Lib" - "github.com/GoelandProver/Goeland/Mods/gs3" + "github.com/GoelandProver/Goeland/Mods/desko" "github.com/GoelandProver/Goeland/Search" ) var contextEnabled bool = false - -var RocqOutputProofStruct = &Search.OutputProofStruct{ProofOutput: MakeRocqOutput, Name: "Rocq", Extension: ".v"} +var label string = "rocq" +var raise_anomaly = func(msg string) { Glob.Anomaly(label, msg) } +var debug Glob.Debugger + +var RocqOutputProofStruct = &Search.OutputProofStruct{ + ProofOutput: MakeRocqOutput, + Name: "Rocq", + Extension: ".v", +} // ---------------------------------------------------------------------------- // Plugin initialisation and main function to call. -func MakeRocqOutput(prf []Search.ProofStruct, meta Lib.List[AST.Meta]) string { - if len(prf) == 0 { - Glob.PrintError("Rocq", "Nothing to output") - return "" - } +func Init() { + debug = Glob.CreateDebugger("rocq") +} +func MakeRocqOutput(prf Search.IProof, meta Lib.List[AST.Meta]) string { // Setup Rocq printer connectives := RocqPrinterConnectives() printer := AST.Printer{PrinterAction: RocqPrinterAction(), PrinterConnective: &connectives} AST.SetPrinter(printer) // Transform tableaux's proof in GS3 proof - return MakeRocqProof(gs3.MakeGS3Proof(prf), meta) + return MakeRocqProof(desko.MakeDeskolemizedProof(prf), meta) } func RocqPrinterConnectives() AST.PrinterConnective { @@ -127,9 +133,9 @@ func RocqPrinterAction() AST.PrinterAction { return rocq_action.Compose(AST.RemoveSuperfluousParenthesesAction(connectives)) } -var MakeRocqProof = func(proof *gs3.GS3Sequent, meta Lib.List[AST.Meta]) string { - contextString := makeContextIfNeeded(proof.GetTargetForm(), meta) - proofString := makeRocqProofFromGS3(proof) +var MakeRocqProof = func(proof Search.IProof, meta Lib.List[AST.Meta]) string { + contextString := makeContextIfNeeded(proof.AppliedOn(), meta) + proofString := makeRocqProofFromIProof(proof) return contextString + "\n" + proofString } diff --git a/src/Mods/rocq/proof.go b/src/Mods/rocq/proof.go index 9eec8f0d..f37cd22d 100644 --- a/src/Mods/rocq/proof.go +++ b/src/Mods/rocq/proof.go @@ -45,14 +45,14 @@ import ( "github.com/GoelandProver/Goeland/Lib" "github.com/GoelandProver/Goeland/Mods/CertifUtils" "github.com/GoelandProver/Goeland/Mods/dmt" - "github.com/GoelandProver/Goeland/Mods/gs3" + "github.com/GoelandProver/Goeland/Search" ) var dummy int -func makeRocqProofFromGS3(proof *gs3.GS3Sequent) string { +func makeRocqProofFromIProof(proof Search.IProof) string { dummy = 0 - axioms, conjecture := processMainFormula(proof.GetTargetForm()) + axioms, conjecture := CertifUtils.ProcessMainFormula(proof.AppliedOn()) totalAxioms := axioms.Len() if Glob.IsLoaded("dmt") { axioms.Append(dmt.GetRegisteredAxioms().GetSlice()...) @@ -66,134 +66,255 @@ func makeRocqProofFromGS3(proof *gs3.GS3Sequent) string { for i, form := range axioms.GetSlice() { indices[i], hypotheses = introduce(form, hypotheses) } - resultingString += "intros " + strings.Join(Glob.MapTo(indices, func(_ int, index int) string { return introName(index) }), " ") + ". " + resultingString += "intros " + strings.Join( + Glob.MapTo(indices, func(_ int, index int) string { return introName(index) }), + " ", + ) + ". " if totalAxioms > 0 { - proof = proof.Child(0) + proof = proof.Children().At(0) } } index, hypotheses := introduce(AST.MakerNot(conjecture), hypotheses) resultingString += "intro " + introName(index) + ". " - resultingString += followProofSteps(proof, hypotheses, make([]AST.Term, 0)) + + debug( + Lib.MkLazy( + func() string { + return fmt.Sprintf("Conjecture: %s, terms:\n%s", + proof.AppliedOn().ToString(), + Lib.ListToString(proof.AppliedOn().GetSubTerms().Elements(), "\n", "{}"), + ) + })) + + resultingString += followProofSteps(proof, hypotheses, CertifUtils.EmptyEpsilon( + proof.AppliedOn().GetSubTerms(), + func(t AST.Term) AST.Term { + switch id := AST.GetSymbol(t).(type) { + case Lib.Some[AST.Id]: + return AST.MakerConst(id.Val) + } + raise_anomaly(fmt.Sprintf("Expected %s to be a Skolem term", t.ToString())) + return nil + }, + func(t AST.Ty) AST.Ty { + switch id := AST.GetTySymbol(t).(type) { + case Lib.Some[AST.TyConstr]: + return id.Val + } + raise_anomaly(fmt.Sprintf("Expected %s to be a Skolem type", t.ToString())) + return nil + }, + getConstantName, + )) return resultingString + "\nQed.\n" } -func followProofSteps(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], constantsCreated []AST.Term) string { +func followProofSteps( + proof Search.IProof, + hypotheses Lib.List[AST.Form], + epsilon CertifUtils.Epsilon, +) string { var resultingString string var childrenHypotheses []Lib.List[AST.Form] - if !proof.IsEmpty() { - resultingString, childrenHypotheses, constantsCreated = makeProofStep(proof, hypotheses, constantsCreated) - } - for i, child := range proof.Children() { - if proof.IsEmpty() { - resultingString += "\n" + followProofSteps(child, Lib.ListCpy(hypotheses), cp(constantsCreated)) - } else { - resultingString += "\n" + followProofSteps(child, Lib.ListCpy(childrenHypotheses[i]), cp(constantsCreated)) - } + resultingString, childrenHypotheses, epsilon = makeStep( + proof, + hypotheses, + epsilon, + ) + for i, child := range proof.Children().GetSlice() { + resultingString += "\n" + followProofSteps( + child, + Lib.ListCpy(childrenHypotheses[i]), + epsilon.Copy(), + ) } return resultingString } -func makeProofStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], constantsCreated []AST.Term) (string, []Lib.List[AST.Form], []AST.Term) { - stepResult, childrenHypotheses, constantsCreated := makeStep(proof, hypotheses, constantsCreated) - return stepResult, childrenHypotheses, constantsCreated -} - -func makeStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], constantsCreated []AST.Term) (string, []Lib.List[AST.Form], []AST.Term) { +func makeStep( + proof Search.IProof, + hypotheses Lib.List[AST.Form], + epsilon CertifUtils.Epsilon, +) (string, []Lib.List[AST.Form], CertifUtils.Epsilon) { var resultingString string childrenHypotheses := []Lib.List[AST.Form]{hypotheses} - target := Lib.ListIndexOf(proof.GetTargetForm(), hypotheses) - var actualTarget int - switch t := target.(type) { - case Lib.Some[int]: - actualTarget = t.Val - case Lib.None[int]: - // If the target formula is an equality, it _does not_ target any formula of the context, - // it simply tells us to close by congruence. Hence, we don't raise an anomaly if the - // target form is an equality. - if !CertifUtils.IsPredEqual(proof.GetTargetForm()) { - Glob.Anomaly("rocq", fmt.Sprintf( - "Index of %s not found in { %s }", - proof.GetTargetForm().ToString(), - Lib.ListToString(hypotheses, " ;; ", ""), - )) + target := CertifUtils.GetTargetFormIndex(proof.AppliedOn(), hypotheses) + switch Search.KindOfRule(proof.RuleApplied()) { + case Search.KindAlpha, Search.KindBeta, Search.KindDelta, Search.KindGamma: + if target == CertifUtils.INVALID_INDEX { + raise_anomaly("Non closure rule targets an equality.") } } - switch proof.Rule() { + switch proof.RuleApplied() { // Closure. - case gs3.AX: - if CertifUtils.IsPredEqual(proof.GetTargetForm()) { + case Search.RuleClosure: + if CertifUtils.IsPredEqual(proof.AppliedOn()) { resultingString = "congruence." } else { resultingString = "auto." } // Alpha rules - case gs3.NNOT: - resultingString, childrenHypotheses = alphaStep(proof, hypotheses, actualTarget, "%s") - case gs3.AND: - resultingString, childrenHypotheses = alphaStep(proof, hypotheses, actualTarget, "(goeland_and_s _ _ %s)") - case gs3.NOR: - resultingString, childrenHypotheses = alphaStep(proof, hypotheses, actualTarget, "(goeland_notor_s _ _ %s)") - case gs3.NIMP: - resultingString, childrenHypotheses = alphaStep(proof, hypotheses, actualTarget, "(goeland_notimply_s _ _ %s)") + case Search.RuleNotNot: + resultingString, childrenHypotheses = alphaStep(proof, hypotheses, target, "%s") + case Search.RuleAnd: + resultingString, childrenHypotheses = alphaStep( + proof, + hypotheses, + target, + "(goeland_and_s _ _ %s)", + ) + case Search.RuleNotOr: + resultingString, childrenHypotheses = alphaStep( + proof, + hypotheses, + target, + "(goeland_notor_s _ _ %s)", + ) + case Search.RuleNotImp: + resultingString, childrenHypotheses = alphaStep( + proof, + hypotheses, + target, + "(goeland_notimply_s _ _ %s)", + ) // Beta rules - case gs3.NAND: - resultingString, childrenHypotheses = betaStep(proof, hypotheses, actualTarget, "(goeland_notand_s _ _ %s)") - case gs3.NEQU: - resultingString, childrenHypotheses = betaStep(proof, hypotheses, actualTarget, "(goeland_notequiv_s _ _ %s)") - case gs3.OR: - resultingString, childrenHypotheses = betaStep(proof, hypotheses, actualTarget, "(goeland_or_s _ _ %s)") - case gs3.IMP: - resultingString, childrenHypotheses = betaStep(proof, hypotheses, actualTarget, "(goeland_imply_s _ _ %s)") - case gs3.EQU: - resultingString, childrenHypotheses = betaStep(proof, hypotheses, actualTarget, "(goeland_equiv_s _ _ %s)") + case Search.RuleNotAnd: + resultingString, childrenHypotheses = betaStep( + proof, + hypotheses, + target, + "(goeland_notand_s _ _ %s)", + ) + case Search.RuleNotEqu: + resultingString, childrenHypotheses = betaStep( + proof, + hypotheses, + target, + "(goeland_notequiv_s _ _ %s)", + ) + case Search.RuleOr: + resultingString, childrenHypotheses = betaStep( + proof, + hypotheses, + target, + "(goeland_or_s _ _ %s)", + ) + case Search.RuleImp: + resultingString, childrenHypotheses = betaStep( + proof, + hypotheses, + target, + "(goeland_imply_s _ _ %s)", + ) + case Search.RuleEqu: + resultingString, childrenHypotheses = betaStep( + proof, + hypotheses, + target, + "(goeland_equiv_s _ _ %s)", + ) // Delta rules - case gs3.NALL: - resultingString, childrenHypotheses, constantsCreated = deltaStep(proof, hypotheses, actualTarget, "apply %s. intros %s. apply NNPP. intros %s. ", constantsCreated) - case gs3.EX: - resultingString, childrenHypotheses, constantsCreated = deltaStep(proof, hypotheses, actualTarget, "elim %s. intros %s. intros %s. ", constantsCreated) + case Search.RuleNotAll: + resultingString, childrenHypotheses, epsilon = deltaStep( + proof, + hypotheses, + target, + "apply %s. intros %s. apply NNPP. intros %s. ", + epsilon, + ) + case Search.RuleEx: + resultingString, childrenHypotheses, epsilon = deltaStep( + proof, + hypotheses, + target, + "elim %s. intros %s. intros %s. ", + epsilon, + ) // Gamma rules - case gs3.ALL: - resultingString, childrenHypotheses = gammaStep(proof, hypotheses, actualTarget, "generalize (%s %s). intros %s. ", constantsCreated) - case gs3.NEX: - resultingString, childrenHypotheses = gammaStep(proof, hypotheses, actualTarget, "apply %s. exists %s. apply NNPP. intros %s. ", constantsCreated) - - // Weakening rule - case gs3.W: - if proof.TermGenerated() != nil { - resultingString = fmt.Sprintf("clear %s.", getConstantName(proof.TermGenerated().(AST.Fun).GetID())) - } else { - resultingString, childrenHypotheses = cleanHypotheses(hypotheses, proof.GetTargetForm()) + case Search.RuleAll: + resultingString, childrenHypotheses = gammaStep( + proof, + hypotheses, + target, + "generalize (%s %s). intros %s. ", + epsilon, + ) + case Search.RuleNotEx: + resultingString, childrenHypotheses = gammaStep( + proof, + hypotheses, + target, + "apply %s. exists %s. apply NNPP. intros %s. ", + epsilon, + ) + + case Search.RuleWeaken: + switch tm := proof.TermGenerated().(type) { + case Lib.Some[Lib.Either[AST.Ty, AST.Term]]: + if epsilon.Introduced(tm.Val) { + resultingString = fmt.Sprintf( + "clear %s.", + getConstantName(tm.Val), + ) + } + case Lib.None[Lib.Either[AST.Ty, AST.Term]]: + resultingString, childrenHypotheses = cleanHypotheses(hypotheses, proof.AppliedOn()) } - case gs3.REWRITE: - resultingString, childrenHypotheses = rewriteStep(proof.GetRewriteWith(), hypotheses, actualTarget, proof.GetResultFormulasOfChild(0).At(0)) + case Search.RuleRew: + resultingString, childrenHypotheses = rewriteStep( + proof.RewrittenWith(), + hypotheses, + target, + proof.ResultFormulas().At(0).At(0), + ) + + default: + Glob.Fatal( + label, + fmt.Sprintf("The rule %s has not yet been implemented", proof.RuleApplied().ToString()), + ) } - return resultingString, childrenHypotheses, constantsCreated + return resultingString, childrenHypotheses, epsilon } -func alphaStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], target int, format string) (string, []Lib.List[AST.Form]) { +func alphaStep( + proof Search.IProof, + hypotheses Lib.List[AST.Form], + target int, + format string, +) (string, []Lib.List[AST.Form]) { var indices []int - indices, hypotheses = introduceList(proof.GetResultFormulasOfChild(0), hypotheses) - resultingString := fmt.Sprintf("apply "+format+". intros %s. ", introName(target), introNames(indices)) + indices, hypotheses = introduceList(proof.ResultFormulas().At(0), hypotheses) + resultingString := fmt.Sprintf( + "apply "+format+". intros %s. ", + introName(target), + introNames(indices), + ) return resultingString, []Lib.List[AST.Form]{hypotheses} } -func betaStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], target int, format string) (string, []Lib.List[AST.Form]) { +func betaStep( + proof Search.IProof, + hypotheses Lib.List[AST.Form], + target int, + format string, +) (string, []Lib.List[AST.Form]) { resultHyps := []Lib.List[AST.Form]{} var indices []int resultingString := fmt.Sprintf("apply "+format+"; ", introName(target)) introducedNames := make([]string, 0) - for i := range proof.Children() { + for _, formulas := range proof.ResultFormulas().GetSlice() { hypoCopy := Lib.ListCpy(hypotheses) - indices, hypoCopy = introduceList(proof.GetResultFormulasOfChild(i), hypoCopy) + indices, hypoCopy = introduceList(formulas, hypoCopy) introducedNames = append(introducedNames, "intros "+introNames(indices, " ")) resultHyps = append(resultHyps, hypoCopy) } @@ -201,34 +322,58 @@ func betaStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], target int, return resultingString + "[ " + strings.Join(introducedNames, " | ") + " ].", resultHyps } -func deltaStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], target int, format string, constantsCreated []AST.Term) (string, []Lib.List[AST.Form], []AST.Term) { +func deltaStep( + proof Search.IProof, + hypotheses Lib.List[AST.Form], + target int, + format string, + epsilon CertifUtils.Epsilon, +) (string, []Lib.List[AST.Form], CertifUtils.Epsilon) { var indices []int var name string - //PrintInfo("DELTA", fmt.Sprintf("%s\n%s", hypotheses[target].ToString(), proof.GetResultFormulasOfChild(0).ToString())) - indices, hypotheses = introduceList(proof.GetResultFormulasOfChild(0), hypotheses) - constantsCreated, name = addTermGenerated(constantsCreated, proof.TermGenerated()) + indices, hypotheses = introduceList(proof.ResultFormulas().At(0), hypotheses) + epsilon, name = addTermGenerated(epsilon, proof.TermGenerated()) resultingString := fmt.Sprintf(format, introName(target), name, introNames(indices)) - return resultingString, []Lib.List[AST.Form]{hypotheses}, constantsCreated + return resultingString, []Lib.List[AST.Form]{hypotheses}, epsilon } -func gammaStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], target int, format string, constantsCreated []AST.Term) (string, []Lib.List[AST.Form]) { +func gammaStep( + proof Search.IProof, + hypotheses Lib.List[AST.Form], + target int, + format string, + epsilon CertifUtils.Epsilon, +) (string, []Lib.List[AST.Form]) { var indices []int - indices, hypotheses = introduceList(proof.GetResultFormulasOfChild(0), hypotheses) - name := "(" + getRealConstantName(constantsCreated, proof.TermGenerated()) + ")" + indices, hypotheses = introduceList(proof.ResultFormulas().At(0), hypotheses) + name := "(" + epsilon.Instantiate("goeland_T", "goeland_I", proof.TermGenerated()) + ")" resultingString := fmt.Sprintf(format, introName(target), name, introNames(indices)) return resultingString, []Lib.List[AST.Form]{hypotheses} } -func rewriteStep(rewriteRule AST.Form, hypotheses Lib.List[AST.Form], target int, replacementForm AST.Form) (string, []Lib.List[AST.Form]) { - index := Lib.ListIndexOf(rewriteRule, hypotheses) +func rewriteStep( + rewriteRule Lib.Option[AST.Form], + hypotheses Lib.List[AST.Form], + target int, + replacementForm AST.Form, +) (string, []Lib.List[AST.Form]) { + var rewriteForm AST.Form + switch f := rewriteRule.(type) { + case Lib.Some[AST.Form]: + rewriteForm = f.Val + default: + raise_anomaly("Trying to rewrite using an empty rule") + } + + index := Lib.ListIndexOf(rewriteForm, hypotheses) var actualIndex int switch i := index.(type) { case Lib.Some[int]: actualIndex = i.Val case Lib.None[int]: - Glob.Anomaly("rocq", fmt.Sprintf( + raise_anomaly(fmt.Sprintf( "Index of %s not found in %s", - rewriteRule.ToString(), + rewriteForm.ToString(), Lib.ListToString(hypotheses, ", ", "[]"), )) } @@ -238,20 +383,6 @@ func rewriteStep(rewriteRule AST.Form, hypotheses Lib.List[AST.Form], target int return resultingString, []Lib.List[AST.Form]{hypotheses} } -// Processes the formula that was proven by Goéland. -func processMainFormula(form AST.Form) (Lib.List[AST.Form], AST.Form) { - formList := Lib.NewList[AST.Form]() - switch nf := form.(type) { - case AST.Not: - form = nf.GetForm() - case AST.And: - last := nf.GetChildFormulas().Len() - 1 - formList = Lib.MkListV(nf.GetChildFormulas().Get(0, last)...) - form = nf.GetChildFormulas().At(last).(AST.Not).GetForm() - } - return formList, form -} - // Prints the theorem's name & properly formats the first formula. func makeTheorem(axioms Lib.List[AST.Form], conjecture AST.Form) string { problemName := CertifUtils.SanitizedTheoremName() @@ -301,49 +432,17 @@ func introNames(il []int, sep ...string) string { return strings.Join(Glob.MapTo(il, func(_ int, f int) string { return introName(f) }), s) } -func addTermGenerated(constantsCreated []AST.Term, term AST.Term) ([]AST.Term, string) { - if term == nil { +func addTermGenerated( + epsilon CertifUtils.Epsilon, + term Lib.Option[Lib.Either[AST.Ty, AST.Term]], +) (CertifUtils.Epsilon, string) { + switch tm := epsilon.Generate(term).(type) { + case Lib.Some[Lib.Either[AST.Ty, AST.Term]]: + return epsilon, getConstantName(tm.Val) + default: dummy++ - return constantsCreated, fmt.Sprintf("x%d", dummy-1) + return epsilon, fmt.Sprintf("x%d", dummy-1) } - constantsCreated = append(constantsCreated, term) - return constantsCreated, getConstantName(term.(AST.Fun).GetID()) -} - -func getRealConstantName(constantsCreated []AST.Term, term AST.Term) string { - if term == nil { - return "goeland_I" - } - if fun, isFun := term.(AST.Fun); isFun { - res := "" - if isGroundTerm(fun.GetID()) { - res = fun.GetID().ToString() - subterms := make([]string, 0) - for _, t := range fun.GetArgs().GetSlice() { - subterms = append(subterms, getRealConstantName(constantsCreated, t)) - } - if len(subterms) > 0 { - res += "(" + strings.Join(subterms, ", ") + ")" - } - } else { - res = findInConstants(constantsCreated, term) - } - return res - } - return findInConstants(constantsCreated, term) -} - -func findInConstants(constantsCreated []AST.Term, term AST.Term) string { - if term == nil { - return "goeland_I" - } - if hasBeenCreated(constantsCreated, term) { - return getConstantName(term.(AST.Fun).GetID()) - } - if isGroundTerm(term) { - return "(" + term.ToString() + ")" - } - return "goeland_I" } func cp[T any](source []T) []T { @@ -360,7 +459,7 @@ func cleanHypotheses(hypotheses Lib.List[AST.Form], form AST.Form) (string, []Li case Lib.Some[int]: actualIndex = i.Val case Lib.None[int]: - Glob.Anomaly("rocq", fmt.Sprintf( + raise_anomaly(fmt.Sprintf( "Index of %s not found in %s", form.ToString(), Lib.ListToString(hypotheses, ", ", "[]"), @@ -372,19 +471,22 @@ func cleanHypotheses(hypotheses Lib.List[AST.Form], form AST.Form) (string, []Li return result, []Lib.List[AST.Form]{hypotheses} } -func getConstantName(id AST.Id) string { - return id.ToString() -} +func getConstantName(x Lib.Either[AST.Ty, AST.Term]) string { + var str Lib.Option[string] -func hasBeenCreated(constantsCreated []AST.Term, term AST.Term) bool { - for _, t := range constantsCreated { - if t.Equals(term) { - return true - } + switch t := x.(type) { + case Lib.Left[AST.Ty, AST.Term]: + str = AST.GetTySymbol(t.Val) + case Lib.Right[AST.Ty, AST.Term]: + str = Lib.OptBind(AST.GetSymbol(t.Val), + func(id AST.Id) Lib.Option[string] { return Lib.MkSome(id.ToString()) }) + } + + switch res := str.(type) { + case Lib.Some[string]: + return res.Val } - return false -} -func isGroundTerm(term AST.Term) bool { - return !strings.Contains(term.ToString(), "sko") + raise_anomaly("Skolemized term/type is not a functional symbol") + return "" } diff --git a/src/Mods/tptp/output.go b/src/Mods/tptp/output.go index f27acd44..ba2802db 100644 --- a/src/Mods/tptp/output.go +++ b/src/Mods/tptp/output.go @@ -40,11 +40,17 @@ import ( "github.com/GoelandProver/Goeland/AST" "github.com/GoelandProver/Goeland/Glob" "github.com/GoelandProver/Goeland/Lib" - "github.com/GoelandProver/Goeland/Mods/gs3" + "github.com/GoelandProver/Goeland/Mods/desko" "github.com/GoelandProver/Goeland/Search" ) -var TptpOutputProofStruct = &Search.OutputProofStruct{ProofOutput: MakeTptpOutput, Name: "TPTP", Extension: ".p"} +var raise_anomaly = func(msg string) { Glob.Anomaly("TPTP", msg) } + +var TptpOutputProofStruct = &Search.OutputProofStruct{ + ProofOutput: MakeTptpOutput, + Name: "TPTP", + Extension: ".p", +} // ---------------------------------------------------------------------------- // Plugin initialisation and main function to call. @@ -53,12 +59,7 @@ var TptpOutputProofStruct = &Search.OutputProofStruct{ProofOutput: MakeTptpOutpu // Functions: MakeTptpOutput // Main functions of the TPTP module. -func MakeTptpOutput(prf []Search.ProofStruct, meta Lib.List[AST.Meta]) string { - if len(prf) == 0 { - Glob.PrintError("TPTP", "Nothing to output") - return "" - } - +func MakeTptpOutput(prf Search.IProof, meta Lib.List[AST.Meta]) string { // FIXME: set AST's printer to be the one of TPTP if Glob.IsSCTPTPOutput() { @@ -67,10 +68,10 @@ func MakeTptpOutput(prf []Search.ProofStruct, meta Lib.List[AST.Meta]) string { } // Transform tableaux's proof in GS3 proof - return MakeTptpProof(gs3.MakeGS3Proof(prf), meta) + return MakeTptpProof(desko.MakeDeskolemizedProof(prf), meta) } -var MakeTptpProof = func(proof *gs3.GS3Sequent, meta Lib.List[AST.Meta]) string { - proofString := makeTptpProofFromGS3(proof) +var MakeTptpProof = func(proof Search.IProof, meta Lib.List[AST.Meta]) string { + proofString := makeTPTPProofFromIProof(proof) return proofString } diff --git a/src/Mods/tptp/proof.go b/src/Mods/tptp/proof.go index 6d28f59c..57cafe0d 100644 --- a/src/Mods/tptp/proof.go +++ b/src/Mods/tptp/proof.go @@ -34,661 +34,701 @@ * This file provides a TPTP proof from Goéland's proof. **/ -// TODO : -// Equality -// unbound variables - package tptp import ( "fmt" - "strconv" "strings" - "sync" "github.com/GoelandProver/Goeland/AST" "github.com/GoelandProver/Goeland/Glob" "github.com/GoelandProver/Goeland/Lib" - "github.com/GoelandProver/Goeland/Mods/gs3" + "github.com/GoelandProver/Goeland/Mods/CertifUtils" + "github.com/GoelandProver/Goeland/Search" ) -var mutex_proof_step sync.Mutex -var id_proof_step = 0 -var mutex_constant sync.Mutex -var original_term = make([]AST.Term, 0) -var constant_created = make([]AST.Term, 0) +type proof_with_id struct { + id int + proof Search.IProof +} + +var original_terms = Lib.NewList[Lib.Either[AST.Ty, AST.Term]]() var prefix_step = "f" var prefix_axiom_cut = "ac" var prefix_const = "sko_" var dummyTerm = AST.MakerConst(AST.MakerId("Goeland_I")) +var dummyType = AST.MkTyConst("Goeland_T") +var epsilon CertifUtils.Epsilon +var current_id = 0 -func makeTptpProofFromGS3(proof *gs3.GS3Sequent) string { - axioms, conjecture := processMainFormula(proof.GetTargetForm()) +func makeTPTPProofFromIProof(proof Search.IProof) string { + axioms, conjecture := CertifUtils.ProcessMainFormula(proof.AppliedOn()) resultingString := makeTheorem(axioms, conjecture) - hypotheses := Lib.ListCpy(axioms) - hypotheses.Append(AST.MakerNot(conjecture.Copy())) - - AxiomCut := performCutAxiomStep(axioms, conjecture) - - firstStep, nextId := performFirstStep(axioms, conjecture, hypotheses, 0) + hypotheses := Lib.ListCpy(axioms).Push(AST.MakerNot(conjecture)) + cut_hypotheses := performCutAxiomStep(axioms, conjecture) + first_steps, next_id := performFirstStep(axioms, conjecture) + + epsilon = CertifUtils.EmptyEpsilon( + proof.AppliedOn().GetSubTerms(), + func(term AST.Term) AST.Term { + new_term_name := fmt.Sprintf("%s%d", prefix_const, original_terms.Len()) + new_term := AST.MakerConst(AST.MakerNewId(new_term_name)) + original_terms.Append(Lib.MkRight[AST.Ty, AST.Term](term)) + return new_term + }, + func(ty AST.Ty) AST.Ty { + new_ty_name := fmt.Sprintf("%s%d", prefix_const, original_terms.Len()) + new_ty := AST.MkTyConst(new_ty_name) + original_terms.Append(Lib.MkLeft[AST.Ty, AST.Term](ty)) + return new_ty + }, + func(t Lib.Either[AST.Ty, AST.Term]) string { + switch index := original_terms.IndexOf(t, Lib.EitherEquals).(type) { + case Lib.Some[int]: + return fmt.Sprintf("%s%d", prefix_const, index.Val) + } + Glob.Anomaly("tptp", "introduced constant not found") + return "" + }, + ) + + annotated_proof := proof_with_id{id: next_id, proof: proof} + current_id = next_id if axioms.Len() == 0 { - resultingString += followProofSteps(proof, hypotheses, nextId) + resultingString += followProofSteps(annotated_proof, hypotheses) } else { - resultingString += followProofSteps(proof.Child(0), hypotheses, nextId) + annotated_proof.proof = proof.Children().At(0) + resultingString += followProofSteps(annotated_proof, hypotheses) } - res := resultingString + "\n" + firstStep + AxiomCut + return resultingString + "\n" + first_steps + "\n\n" + cut_hypotheses +} + +func fofInference( + node_id, inference_type string, + sequent_lhs, sequent_rhs Lib.List[AST.Form], + rule string, + additional_infos string, + next_steps Lib.List[Lib.String], +) string { + if additional_infos != "" { + additional_infos = ", " + additional_infos + } - return res + return fmt.Sprintf( + "fof(%s, %s, [%s] --> [%s], inference(%s, [status(thm)%s], [%s])).", + node_id, + inference_type, + Lib.ListToString(sequent_lhs, ", ", ""), + Lib.ListToString(sequent_rhs, ", ", ""), + rule, + additional_infos, + Lib.ListToString(next_steps, ", ", ""), + ) } -/*** Proof Steps ***/ +func performCutAxiomStep(axioms Lib.List[AST.Form], conjecture AST.Form) string { + axiom_steps := []string{} -func followProofSteps(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], new_current_id int) string { - var resultingString string - var resultingStringParent string - var childrenHypotheses []Lib.List[AST.Form] - if !proof.IsEmpty() { - resultingStringParent, childrenHypotheses, new_current_id = makeProofStep(proof, hypotheses, new_current_id) - } - for i, child := range proof.Children() { - if proof.IsEmpty() { - resultingString += followProofSteps(child, Lib.ListCpy(hypotheses), new_current_id) + "\n" + for i, ax := range axioms.GetSlice() { + var nextStep string + if i == axioms.Len()-1 { + nextStep = prefix_step + "0" } else { - newHypotheses := Lib.ListCpy(hypotheses) - newHypotheses = Lib.ListAdd(newHypotheses, childrenHypotheses[i].GetSlice()...) - resultingString += followProofSteps(child, newHypotheses, new_current_id) + "\n" + nextStep = fmt.Sprintf("%s%d", prefix_axiom_cut, i+1) } + + cut_axiom_step := fofInference( + fmt.Sprintf("%s%d", prefix_axiom_cut, i), + "plain", + Lib.MkListV(axioms.Get(0, i)...), + Lib.MkListV(conjecture), + "cut", + "0", + Lib.MkListV( + Lib.MkString(fmt.Sprintf("ax%d", ax.GetIndex())), + Lib.MkString(nextStep), + ), + ) + + axiom_steps = append(axiom_steps, cut_axiom_step) } - return resultingString + resultingStringParent -} -func makeProofStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], new_current_id int) (string, []Lib.List[AST.Form], int) { - stepResult, childrenHypotheses, next_child_weakened_id := makeStep(proof, hypotheses, new_current_id) - return stepResult, childrenHypotheses, next_child_weakened_id + return strings.Join(axiom_steps, "\n") } -func findIndexPos(f AST.Form, hypotheses Lib.List[AST.Form], target int) int { - targetPos := -1 +/*** Proof Steps ***/ - switch initial_formula := f.(type) { - case AST.Not: - targetPos = get(initial_formula.GetForm(), hypotheses) - default: - targetPos = target +func followProofSteps( + proof proof_with_id, + hypotheses Lib.List[AST.Form], +) string { + var resultingString string + resultingStringParent, childrenHypotheses, childrenAnnotated := makeStep( + proof, + hypotheses, + ) + for i, child := range childrenAnnotated { + newHypotheses := Lib.ListCpy(hypotheses) + newHypotheses = Lib.ListAdd(newHypotheses, childrenHypotheses[i].GetSlice()...) + resultingString += followProofSteps(child, newHypotheses) + "\n" } + return resultingString + resultingStringParent +} + +func find_index_of_pos(f AST.Form, hypotheses Lib.List[AST.Form], target int) int { + if form, is_not := f.(AST.Not); is_not { + target = CertifUtils.GetTargetFormIndex(form, hypotheses) - if targetPos == -1 { - Glob.Anomaly("TPTP - makeStep", "complementary literal not found") + if target == CertifUtils.INVALID_INDEX { + raise_anomaly("Complementary litteral not found") + } } - return targetPos + return target } -func makeStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], new_current_id int) (string, []Lib.List[AST.Form], int) { +func makeStep( + annotated_proof proof_with_id, + hypotheses Lib.List[AST.Form], +) (string, []Lib.List[AST.Form], []proof_with_id) { var resultingString string childrenHypotheses := []Lib.List[AST.Form]{hypotheses} - next_child_weakened_id := -1 - - updateId(proof, new_current_id) - target := get(proof.GetTargetForm(), hypotheses) + childrenAnnotated := []proof_with_id{} - switch proof.Rule() { + proof := annotated_proof.proof + assigned_id := annotated_proof.id - // Closure. - case gs3.AX: - if isPredEqual(proof.GetTargetForm()) { - resultingString = fmt.Sprintf("fof("+prefix_step+"%d, plain, [%s] --> [], inference(%s, [status(thm)], [%s])).", - proof.GetId(), - Lib.ListToString(hypotheses, ", ", ""), - "congruence", - "") - } else { - targetPos := findIndexPos(proof.GetTargetForm(), hypotheses, target) - - resultingString = fmt.Sprintf("fof("+prefix_step+"%d, plain, [%s] --> [], inference(%s, [status(thm), %d], [%s])).", - proof.GetId(), - Lib.ListToString(hypotheses, ", ", ""), - "leftHyp", - targetPos, - "") + target_form := epsilon.Substitute(dummyTerm, proof.AppliedOn()) + target := CertifUtils.GetTargetFormIndex(target_form, hypotheses) + switch Search.KindOfRule(proof.RuleApplied()) { + case Search.KindAlpha, Search.KindBeta, Search.KindDelta, Search.KindGamma: + if target == CertifUtils.INVALID_INDEX { + raise_anomaly("Non closure rule targets an equality.") } + } - // Alpha rules - case gs3.NNOT: - resultingString, childrenHypotheses = alphaStep(proof, hypotheses, target, "leftNotNot") - case gs3.AND: - resultingString, childrenHypotheses = alphaStep(proof, hypotheses, target, "leftAnd") - case gs3.NOR: - resultingString, childrenHypotheses = alphaStep(proof, hypotheses, target, "leftNotOr") - case gs3.NIMP: - resultingString, childrenHypotheses = alphaStep(proof, hypotheses, target, "leftNotImplies") - - // Beta rules - case gs3.NAND: - resultingString, childrenHypotheses = betaStep(proof, hypotheses, target, "leftNotAnd") - case gs3.NEQU: - resultingString, childrenHypotheses = NotEquStep(proof, hypotheses, target) - case gs3.OR: - resultingString, childrenHypotheses = betaStep(proof, hypotheses, target, "leftOr") - case gs3.IMP: - resultingString, childrenHypotheses = betaStep(proof, hypotheses, target, "leftImp2") - case gs3.EQU: - resultingString, childrenHypotheses = EquStep(proof, hypotheses, target) - - // Delta rules - case gs3.NALL: - resultingString, childrenHypotheses = deltaStep(proof, hypotheses, target, "leftNotAll") - case gs3.EX: - resultingString, childrenHypotheses = deltaStep(proof, hypotheses, target, "leftExists") - - // Gamma rules - case gs3.ALL: - resultingString, childrenHypotheses = gammaStep(proof, hypotheses, target, "leftForall") - case gs3.NEX: - resultingString, childrenHypotheses = gammaStep(proof, hypotheses, target, "leftNotEx") + closure_rule := func(rule string, target string) string { + return fofInference( + fmt.Sprintf("%s%d", prefix_step, assigned_id), + "plain", + hypotheses, + Lib.NewList[AST.Form](), + rule, + target, + Lib.NewList[Lib.String](), + ) + } + alpha_rule := func(rule string) (string, []Lib.List[AST.Form], []proof_with_id) { + return alphaStep( + annotated_proof, + hypotheses, + target, + rule, + ) + } + beta_rule := func(rule string) (string, []Lib.List[AST.Form], []proof_with_id) { + return betaStep( + annotated_proof, + hypotheses, + target, + rule, + ) + } + delta_rule := func(rule string) (string, []Lib.List[AST.Form], []proof_with_id) { + return deltaStep( + annotated_proof, + hypotheses, + target, + rule, + ) + } + gamma_rule := func(rule string) (string, []Lib.List[AST.Form], []proof_with_id) { + return gammaStep( + annotated_proof, + hypotheses, + target, + rule, + ) + } - // Weakening rule - case gs3.W: - if proof.TermGenerated() != nil { - resultingString = fmt.Sprintf("leftWeaken %s", findInConstants(proof.TermGenerated()).ToString()) + switch proof.RuleApplied() { + + case Search.RuleClosure: + if CertifUtils.IsPredEqual(proof.AppliedOn()) { + resultingString = closure_rule("congruence", "") } else { - resultingString, childrenHypotheses, next_child_weakened_id = weakenStep(proof, hypotheses, target, "leftWeaken") + target_positive := find_index_of_pos(target_form, hypotheses, target) + resultingString = closure_rule("leftHyp", fmt.Sprintf("%d", target_positive)) } - case gs3.REWRITE: - resultingString, childrenHypotheses = rewriteStep(proof.GetRewriteWith(), hypotheses, target, proof.GetResultFormulasOfChild(0).At(0)) - } - - return resultingString + "\n", childrenHypotheses, next_child_weakened_id -} + case Search.RuleNotNot: + resultingString, childrenHypotheses, childrenAnnotated = alpha_rule("leftNotNot") + case Search.RuleAnd: + resultingString, childrenHypotheses, childrenAnnotated = alpha_rule("leftAnd") + case Search.RuleNotOr: + resultingString, childrenHypotheses, childrenAnnotated = alpha_rule("leftNotOr") + case Search.RuleNotImp: + resultingString, childrenHypotheses, childrenAnnotated = alpha_rule("leftNotImplies") + + case Search.RuleNotAnd: + resultingString, childrenHypotheses, childrenAnnotated = beta_rule("leftNotAnd") + case Search.RuleOr: + resultingString, childrenHypotheses, childrenAnnotated = beta_rule("leftOr") + case Search.RuleImp: + resultingString, childrenHypotheses, childrenAnnotated = beta_rule("leftImp2") + case Search.RuleNotEqu: + resultingString, childrenHypotheses, childrenAnnotated = notEquStep( + annotated_proof, + hypotheses, + target, + ) + case Search.RuleEqu: + resultingString, childrenHypotheses, childrenAnnotated = equStep( + annotated_proof, + hypotheses, + target, + ) -func alphaStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], target int, format string) (string, []Lib.List[AST.Form]) { + case Search.RuleNotAll: + resultingString, childrenHypotheses, childrenAnnotated = delta_rule("leftNotAll") + case Search.RuleEx: + resultingString, childrenHypotheses, childrenAnnotated = delta_rule("leftExists") - children_id := []int{} - for _, c := range proof.Children() { - new_id := incrByOne(&id_proof_step, &mutex_proof_step) - children_id = append(children_id, new_id) - c.SetId(new_id) - } + case Search.RuleAll: + resultingString, childrenHypotheses, childrenAnnotated = gamma_rule("leftForall") + case Search.RuleNotEx: + resultingString, childrenHypotheses, childrenAnnotated = gamma_rule("leftNotEx") - resultingString := fmt.Sprintf("fof(%s%d, plain, [%s] --> [], inference(%s, [status(thm), %d], [%s])).", - prefix_step, - proof.GetId(), - Lib.ListToString(hypotheses, ", ", ""), - format, - target, - Glob.IntListToString(children_id, prefix_step)) - - newHypotheses := Lib.ListCpy(hypotheses) - newHypotheses = Lib.ListAdd(newHypotheses, proof.GetResultFormulasOfChild(0).GetSlice()...) - return resultingString, []Lib.List[AST.Form]{newHypotheses} -} - -func betaStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], target int, format string) (string, []Lib.List[AST.Form]) { - resultHyps := []Lib.List[AST.Form]{} - children_id := []int{} + // Weakening rule + case Search.RuleWeaken: + resultingString, childrenHypotheses, childrenAnnotated = weakenStep( + annotated_proof, + hypotheses, + target, + ) - for i, c := range proof.Children() { - new_id := incrByOne(&id_proof_step, &mutex_proof_step) - children_id = append(children_id, new_id) - c.SetId(new_id) - newHypotheses := Lib.ListCpy(hypotheses) - newHypotheses = Lib.ListAdd(newHypotheses, proof.GetResultFormulasOfChild(i).GetSlice()...) - resultHyps = append(resultHyps, newHypotheses) + case Search.RuleRew: + Glob.Fatal("tptp", "rewrite rules not yet implemented") } - resultingString := fmt.Sprintf("fof(%s%d, plain, [%s] --> [], inference(%s, [status(thm), %d], [%s])).", - prefix_step, - proof.GetId(), - Lib.ListToString(hypotheses, ", ", ""), - format, - target, - Glob.IntListToString(children_id, prefix_step)) + return resultingString + "\n", childrenHypotheses, childrenAnnotated +} - return resultingString, resultHyps +func alphaStep( + annotated_proof proof_with_id, + hypotheses Lib.List[AST.Form], + target int, + rule string, +) (string, []Lib.List[AST.Form], []proof_with_id) { + result_hyps, children_id, annotated_children := genAnnotateChildren(annotated_proof, hypotheses) + + resultingString := fofInference( + fmt.Sprintf("%s%d", prefix_step, annotated_proof.id), + "plain", + hypotheses, + Lib.NewList[AST.Form](), + rule, + fmt.Sprintf("%d", target), + children_id, + ) + + return resultingString, result_hyps, annotated_children } -func deltaStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], target int, format string) (string, []Lib.List[AST.Form]) { - children_id := []int{} - for _, c := range proof.Children() { - new_id := incrByOne(&id_proof_step, &mutex_proof_step) - children_id = append(children_id, new_id) - c.SetId(new_id) +func genAnnotateChildren( + annotated_proof proof_with_id, + hypotheses Lib.List[AST.Form], +) ([]Lib.List[AST.Form], Lib.List[Lib.String], []proof_with_id) { + result_hyps := []Lib.List[AST.Form]{} + annotated_children := []proof_with_id{} + proof := annotated_proof.proof + children_id := Lib.NewList[Lib.String]() + + for i, c := range proof.Children().GetSlice() { + current_id++ + annotated_children = append(annotated_children, + proof_with_id{id: current_id, proof: c}, + ) + child_hyps := Lib.ListMap(proof.ResultFormulas().At(i), + func(f AST.Form) AST.Form { return epsilon.Substitute(dummyTerm, f) }, + ) + result_hyps = append( + result_hyps, + Lib.ListCpy(hypotheses).Push(child_hyps.GetSlice()...), + ) + children_id = children_id.Push( + Lib.MkString(fmt.Sprintf("%s%d", prefix_step, current_id)), + ) } - new_term := createNewConstant(proof.TermGenerated()) - - proof = updateSkolemSymbol(proof.TermGenerated(), new_term, proof) - - resultingString := fmt.Sprintf("fof(%s%d, plain, [%s] --> [], inference(%s, [status(thm), %d, '%s'], [%s])).", - prefix_step, - proof.GetId(), - Lib.ListToString(hypotheses, ", ", ""), - format, - target, - new_term.ToString(), - Glob.IntListToString(children_id, prefix_step)) - - newHypotheses := Lib.ListCpy(hypotheses) - newHypotheses = Lib.ListAdd(newHypotheses, proof.GetResultFormulasOfChild(0).GetSlice()...) + return result_hyps, children_id, annotated_children +} - return resultingString, []Lib.List[AST.Form]{newHypotheses} +func betaStep( + annotated_proof proof_with_id, + hypotheses Lib.List[AST.Form], + target int, + rule string, +) (string, []Lib.List[AST.Form], []proof_with_id) { + result_hyps, children_id, annotated_children := genAnnotateChildren(annotated_proof, hypotheses) + + resulting_string := fofInference( + fmt.Sprintf("%s%d", prefix_step, annotated_proof.id), + "plain", + hypotheses, + Lib.NewList[AST.Form](), + rule, + fmt.Sprintf("%d", target), + children_id, + ) + + return resulting_string, result_hyps, annotated_children } -func gammaStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], target int, format string) (string, []Lib.List[AST.Form]) { - children_id := []int{} - for _, c := range proof.Children() { - new_id := incrByOne(&id_proof_step, &mutex_proof_step) - children_id = append(children_id, new_id) - c.SetId(new_id) +func deltaStep( + annotated_proof proof_with_id, + hypotheses Lib.List[AST.Form], + target int, + rule string, +) (string, []Lib.List[AST.Form], []proof_with_id) { + var generated_term string + switch tm := epsilon.Generate(annotated_proof.proof.TermGenerated()).(type) { + case Lib.Some[Lib.Either[AST.Ty, AST.Term]]: + switch t := tm.Val.(type) { + case Lib.Left[AST.Ty, AST.Term]: + generated_term = t.Val.ToString() + case Lib.Right[AST.Ty, AST.Term]: + generated_term = t.Val.ToString() + } + default: + generated_term = dummyTerm.ToString() } - get(proof.GetTargetForm(), hypotheses) + result_hyps, children_id, annotated_children := genAnnotateChildren(annotated_proof, hypotheses) - resultingString := fmt.Sprintf("fof(%s%d, plain, [%s] --> [], inference(%s, [status(thm), %d, $fot(%s)], [%s])).", - prefix_step, - proof.GetId(), - Lib.ListToString(hypotheses, ", ", ""), - format, - target, - findInConstants(proof.TermGenerated()).ToString(), - Glob.IntListToString(children_id, prefix_step)) + resulting_string := fofInference( + fmt.Sprintf("%s%d", prefix_step, annotated_proof.id), + "plain", + hypotheses, + Lib.NewList[AST.Form](), + rule, + fmt.Sprintf("%d, '%s'", target, generated_term), + children_id, + ) - newHypotheses := Lib.ListCpy(hypotheses) - newHypotheses = Lib.ListAdd(newHypotheses, proof.GetResultFormulasOfChild(0).GetSlice()...) + return resulting_string, result_hyps, annotated_children +} - return resultingString, []Lib.List[AST.Form]{newHypotheses} +func gammaStep( + annotated_proof proof_with_id, + hypotheses Lib.List[AST.Form], + target int, + rule string, +) (string, []Lib.List[AST.Form], []proof_with_id) { + result_hyps, children_id, annotated_children := genAnnotateChildren(annotated_proof, hypotheses) + + resulting_string := fofInference( + fmt.Sprintf("%s%d", prefix_step, annotated_proof.id), + "plain", + hypotheses, + Lib.NewList[AST.Form](), + rule, + fmt.Sprintf( + "%d, $fot(%s)", + target, + epsilon.Instantiate( + dummyType.ToString(), + dummyTerm.ToString(), + annotated_proof.proof.TermGenerated(), + ), + ), + children_id, + ) + + return resulting_string, result_hyps, annotated_children } -func weakenStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], target int, format string) (string, []Lib.List[AST.Form], int) { - child_id := incrByOne(&id_proof_step, &mutex_proof_step) +func weakenStep( + annotated_proof proof_with_id, + hypotheses Lib.List[AST.Form], + target int, +) (string, []Lib.List[AST.Form], []proof_with_id) { + _, children_id, annotated_children := genAnnotateChildren(annotated_proof, hypotheses) - if target != -1 { + var additional_infos string + + switch t := annotated_proof.proof.TermGenerated().(type) { + case Lib.Some[Lib.Either[AST.Ty, AST.Term]]: + additional_infos = fmt.Sprintf("'%s'", epsilon.Instantiate(dummyTerm.ToString(), dummyType.ToString(), t)) + default: + additional_infos = fmt.Sprintf("%d", target) hypotheses = hypotheses.RemoveAt(target) } - resultingString := fmt.Sprintf("fof(%s%d, plain, [%s] --> [], inference(%s, [status(thm), %d], [%s%d])).", - prefix_step, - proof.GetId(), - Lib.ListToString(hypotheses, ", ", ""), - format, - target, - prefix_step, - child_id) - - return resultingString, []Lib.List[AST.Form]{hypotheses}, child_id -} - -func rewriteStep(rewriteRule AST.Form, hypotheses Lib.List[AST.Form], target int, replacementForm AST.Form) (string, []Lib.List[AST.Form]) { - // resultingString := fmt.Sprintf("rewrite %s in %s.", introName(get(rewriteRule, hypotheses)), introName(target)) - // hypotheses[target] = replacementForm - // return resultingString, []Lib.List[AST.Form]{hypotheses} - return "", []Lib.List[AST.Form]{} + resulting_string := fofInference( + fmt.Sprintf("%s%d", prefix_step, annotated_proof.id), + "plain", + hypotheses, + Lib.NewList[AST.Form](), + "leftWeaken", + additional_infos, + children_id, + ) + return resulting_string, []Lib.List[AST.Form]{hypotheses}, annotated_children } -func EquStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], target int) (string, []Lib.List[AST.Form]) { - resultingString := "" - resultHyps := []Lib.List[AST.Form]{} - children_id := []int{} +func equStep( + annotated_proof proof_with_id, + hypotheses Lib.List[AST.Form], + target int, +) (string, []Lib.List[AST.Form], []proof_with_id) { + result_hyps, children_id, annotated_children := genAnnotateChildren(annotated_proof, hypotheses) + + var A, B, notA, notB, A_imp_B, B_imp_A AST.Form + switch form := hypotheses.At(target).(type) { + case AST.Equ: + A = form.GetF1() + B = form.GetF2() + notA = AST.MakerNot(A) + notB = AST.MakerNot(B) + A_imp_B = AST.MakerImp(A, B) + B_imp_A = AST.MakerImp(B, A) - for i, c := range proof.Children() { - new_id := incrByOne(&id_proof_step, &mutex_proof_step) - children_id = append(children_id, new_id) - c.SetId(new_id) - newHypotheses := Lib.ListCpy(hypotheses) - newHypotheses = Lib.ListAdd(newHypotheses, proof.GetResultFormulasOfChild(i).GetSlice()...) - resultHyps = append(resultHyps, newHypotheses) + default: + raise_anomaly(fmt.Sprintf("Expected %s to be an equivalence.", form.ToString())) } - // Sub-formulas - A := hypotheses.At(target).(AST.Equ).GetF1() - B := hypotheses.At(target).(AST.Equ).GetF2() - notA := AST.MakerNot(A) - notB := AST.MakerNot(B) - A_imp_B := AST.MakerImp(A, B) - B_imp_A := AST.MakerImp(B, A) - - // from A <=> B to A => B, B => A (unary) - s1_id := fmt.Sprintf("%s%dext1", prefix_step, proof.GetId()) - resultingString = fmt.Sprintf("fof(%s%d, plain, [%s] --> [], inference(%s, [status(thm), %d], [%s])).", - prefix_step, - proof.GetId(), - Lib.ListToString(hypotheses, ", ", ""), + // Expansion of the tableau rules to match TPTP rules. + // 1. apply the rule [leftIff] to generate one branch [Gamma, A_imp_B, B_imp_A |-]. + // 2. do 2 applications of the rule [leftImp2] to get 4 branches: + // - [Gamma, A_imp_B, B_imp_A, ~A, ~B |-] + // - [Gamma, A_imp_B, B_imp_A, ~A, A |-] + // - [Gamma, A_imp_B, B_imp_A, B, ~B |-] + // - [Gamma, A_imp_B, B_imp_A, B, A |-] + // 3. conclude on the children 2 & 3 and continue outputing the proof for the others. + + // 1. + child1_ext_id := fmt.Sprintf("%s%dext1", prefix_step, annotated_proof.id) + first_inference := fofInference( + fmt.Sprintf("%s%d", prefix_step, annotated_proof.id), + "plain", + hypotheses, + Lib.NewList[AST.Form](), "leftIff", - target, - s1_id) + resultingString - - // from A => B, B => A to ~A, B => A | B, B => A (binary) - s2_id := fmt.Sprintf("%s%dext2", prefix_step, proof.GetId()) - s3_id := fmt.Sprintf("%s%dext3", prefix_step, proof.GetId()) - newHyp := Lib.ListCpy(hypotheses) - newHyp = Lib.ListAdd(newHyp, []AST.Form{A_imp_B, B_imp_A}...) - resultingString = fmt.Sprintf("fof(%s, plain, [%s] --> [], inference(%s, [status(thm), %d], [%s, %s])).\n\n", - s1_id, - Lib.ListToString(newHyp, ", ", ""), + fmt.Sprintf("%d", target), + Lib.MkListV(Lib.MkString(child1_ext_id)), + ) + + // 2. + child2_ext_id := fmt.Sprintf("%s%dext2", prefix_step, annotated_proof.id) + child3_ext_id := fmt.Sprintf("%s%dext3", prefix_step, annotated_proof.id) + child2_closure_rule_id := fmt.Sprintf("%sext1", child2_ext_id) + child3_closure_rule_id := fmt.Sprintf("%sext1", child3_ext_id) + + child1_inference := fofInference( + child1_ext_id, + "plain", + Lib.ListCpy(hypotheses).Push(A_imp_B, B_imp_A), + Lib.NewList[AST.Form](), "leftImp2", - get(A_imp_B, newHyp), - s2_id, - s3_id) + resultingString - - // Branch s2 : from ~A, B => A to ~A, ~B | ~A, A - s2_closure_id := fmt.Sprintf("%sext1", s2_id) - newHypS2 := Lib.ListCpy(newHyp) - newHypS2 = Lib.ListAdd(newHypS2, notA.Copy()) - resultingString = fmt.Sprintf("fof(%s, plain, [%s] --> [], inference(%s, [status(thm), %d], [%s%d, %s])).\n\n", - s2_id, - Lib.ListToString(newHypS2, ", ", ""), + fmt.Sprintf("%d", hypotheses.Len()), + Lib.MkListV(Lib.MkString(child2_ext_id), Lib.MkString(child3_ext_id)), + ) + + child2_inference := fofInference( + child2_ext_id, + "plain", + Lib.ListCpy(hypotheses).Push(A_imp_B, B_imp_A, notA), + Lib.NewList[AST.Form](), "leftImp2", - get(B_imp_A, newHypS2), - prefix_step, - children_id[0], - s2_closure_id) + resultingString - resultHyps[0] = Lib.ListAdd(resultHyps[0], newHypS2.GetSlice()...) - - // Branch 2.closure : from ~A, A closure - check polarity before - newHypS2Closure := Lib.ListCpy(newHypS2) - newHypS2Closure = Lib.ListAdd(newHypS2Closure, A) - targetPosS2 := findIndexPos(A, newHypS2Closure, get(A, newHypS2Closure)) - resultingString = fmt.Sprintf("fof(%s, plain, [%s] --> [], inference(%s, [status(thm), %d], [%s])).\n\n", - s2_closure_id, - Lib.ListToString(newHypS2Closure, ", ", ""), + fmt.Sprintf("%d", hypotheses.Len()+1), + Lib.MkListV( + children_id.At(0), + Lib.MkString(child2_closure_rule_id), + ), + ) + result_hyps[0] = result_hyps[0].Push(A_imp_B, B_imp_A, notA, notB) + + child2_closure := fofInference( + child2_closure_rule_id, + "plain", + Lib.ListCpy(hypotheses).Push(A_imp_B, B_imp_A, notA, A), + Lib.NewList[AST.Form](), "leftHyp", - targetPosS2, - "") + resultingString - - // Branch s3: from B, B => A to B, ~B | B, A - s3_closure_id := fmt.Sprintf("%sext1", s3_id) - newHypS3 := Lib.ListCpy(newHyp) - newHypS3 = Lib.ListAdd(newHypS3, B) - resultingString = fmt.Sprintf("fof(%s, plain, [%s] --> [], inference(%s, [status(thm), %d], [%s, %s%d])).\n\n", - s3_id, - Lib.ListToString(newHypS3, ", ", ""), + fmt.Sprintf("%d", hypotheses.Len()+3), + Lib.NewList[Lib.String](), + ) + + child3_inference := fofInference( + child3_ext_id, + "plain", + Lib.ListCpy(hypotheses).Push(A_imp_B, B_imp_A, B), + Lib.NewList[AST.Form](), "leftImp2", - get(B_imp_A, newHypS3), - s3_closure_id, - prefix_step, - children_id[1]) + resultingString - resultHyps[1] = Lib.ListAdd(resultHyps[1], newHypS3.GetSlice()...) - - // Branch 3.closure : from B, ~B closure - check polarity before - newHypS3Closure := Lib.ListCpy(newHypS3) - newHypS3Closure = Lib.ListAdd(newHypS3Closure, notB.Copy()) - targetPosS3 := findIndexPos(B, newHypS3Closure, get(B, newHypS3Closure)) - resultingString = fmt.Sprintf("fof(%s, plain, [%s] --> [], inference(%s, [status(thm), %d], [%s])).\n\n", - s3_closure_id, - Lib.ListToString(newHypS3Closure, ", ", ""), + fmt.Sprintf("%d", hypotheses.Len()+1), + Lib.MkListV( + Lib.MkString(child3_closure_rule_id), + children_id.At(1), + ), + ) + result_hyps[1] = result_hyps[1].Push(A_imp_B, B_imp_A, B, A) + + child3_closure := fofInference( + child3_closure_rule_id, + "plain", + Lib.ListCpy(hypotheses).Push(A_imp_B, B_imp_A, B, notB), + Lib.NewList[AST.Form](), "leftHyp", - targetPosS3, - "") + resultingString + fmt.Sprintf("%d", hypotheses.Len()+2), + Lib.NewList[Lib.String](), + ) - return resultingString, resultHyps + return child3_closure + "\n\n" + child3_inference + "\n\n" + child2_closure + "\n\n" + child2_inference + "\n\n" + + child1_inference + "\n\n" + first_inference, result_hyps, annotated_children } -func NotEquStep(proof *gs3.GS3Sequent, hypotheses Lib.List[AST.Form], target int) (string, []Lib.List[AST.Form]) { - resultingString := "" - resultHyps := []Lib.List[AST.Form]{} - children_id := []int{} +func notEquStep( + annotated_proof proof_with_id, + hypotheses Lib.List[AST.Form], + target int, +) (string, []Lib.List[AST.Form], []proof_with_id) { + result_hyps, children_id, annotated_children := genAnnotateChildren(annotated_proof, hypotheses) - for i, c := range proof.Children() { - new_id := incrByOne(&id_proof_step, &mutex_proof_step) - children_id = append(children_id, new_id) - c.SetId(new_id) - newHypotheses := Lib.ListCpy(hypotheses) - newHypotheses = Lib.ListAdd(newHypotheses, proof.GetResultFormulasOfChild(i).GetSlice()...) - resultHyps = append(resultHyps, newHypotheses) + var A, B, not_A_imp_B, not_B_imp_A AST.Form + + switch formula := hypotheses.At(target).(type) { + case AST.Not: + switch f := formula.GetForm().(type) { + case AST.Equ: + A = f.GetF1() + B = f.GetF2() + not_A_imp_B = AST.MakerNot(AST.MakerImp(A, B)) + not_B_imp_A = AST.MakerNot(AST.MakerImp(B, A)) + + default: + raise_anomaly(fmt.Sprintf("Expected formula %s to be an equivalence", f.ToString())) + } + + default: + raise_anomaly(fmt.Sprintf("Expected formula %s to be a negation", formula.ToString())) } - // Sub-formulas - equ := hypotheses.At(target).(AST.Not).GetForm().(AST.Equ) - A := equ.GetF1() - B := equ.GetF2() - not_A_imp_B := AST.MakerNot(AST.MakerImp(A, B)) - not_B_imp_A := AST.MakerNot(AST.MakerImp(B, A)) - - // from ~(A <=> B) to ~(A => B) | ~(B => A) (binary) - s1_id := fmt.Sprintf("%s%dext1", prefix_step, proof.GetId()) - s2_id := fmt.Sprintf("%s%dext2", prefix_step, proof.GetId()) - resultingString = fmt.Sprintf("fof(%s%d, plain, [%s] --> [], inference(%s, [status(thm), %d], [%s, %s])).", - prefix_step, - proof.GetId(), - Lib.ListToString(hypotheses, ", ", ""), + // Expansion of the tableau rules to match TPTP rules. + // 1. apply the rule [leftNotIff] to generate two branches [Gamma, not_A_imp_B |-] and [Gamma, not_B_imp_A |-] + // 2. apply the rule [leftNotImplies] in both branches to get [Gamma, A, ~B |-] and [Gamma, B, ~A |-]. + + // 1. + ext_child1_id := fmt.Sprintf("%s%dext1", prefix_step, annotated_proof.id) + ext_child2_id := fmt.Sprintf("%s%dext2", prefix_step, annotated_proof.id) + first_inference := fofInference( + fmt.Sprintf("%s%d", prefix_step, annotated_proof.id), + "plain", + hypotheses, + Lib.NewList[AST.Form](), "leftNotIff", - target, - s1_id, - s2_id) + resultingString - - // from ~(A => B) to A, ~B - newHyp1 := Lib.ListCpy(hypotheses) - newHyp1 = Lib.ListAdd(newHyp1, not_A_imp_B.Copy()) - resultingString = fmt.Sprintf("fof(%s, plain, [%s] --> [], inference(%s, [status(thm), %d], [%s%d])).\n\n", - s1_id, - Lib.ListToString(newHyp1, ", ", ""), + fmt.Sprintf("%d", target), + Lib.MkListV(Lib.MkString(ext_child1_id), Lib.MkString(ext_child2_id)), + ) + + // 2. + child1_inference := fofInference( + ext_child1_id, + "plain", + Lib.ListCpy(hypotheses).Push(not_A_imp_B), + Lib.NewList[AST.Form](), "leftNotImplies", - get(not_A_imp_B, newHyp1), - prefix_step, - children_id[1]) + resultingString - resultHyps[1] = Lib.ListAdd(resultHyps[1], newHyp1.GetSlice()...) - - // from ~(B => A) to B, ~A - newHyp2 := Lib.ListCpy(hypotheses) - newHyp2 = Lib.ListAdd(newHyp2, not_B_imp_A.Copy()) - resultingString = fmt.Sprintf("fof(%s, plain, [%s] --> [], inference(%s, [status(thm), %d], [%s%d])).\n\n", - s2_id, - Lib.ListToString(newHyp2, ", ", ""), + fmt.Sprintf("%d", hypotheses.Len()), + Lib.MkListV(children_id.At(1)), + ) + result_hyps[1] = result_hyps[1].Push(not_A_imp_B) + + child2_inference := fofInference( + ext_child2_id, + "plain", + Lib.ListCpy(hypotheses).Push(not_B_imp_A), + Lib.NewList[AST.Form](), "leftNotImplies", - get(not_B_imp_A, newHyp2), - prefix_step, - children_id[0]) + resultingString - resultHyps[0] = Lib.ListAdd(resultHyps[0], newHyp2.GetSlice()...) + fmt.Sprintf("%d", hypotheses.Len()), + Lib.MkListV(children_id.At(0)), + ) + result_hyps[0] = result_hyps[0].Push(not_B_imp_A) - return resultingString, resultHyps + return child2_inference + "\n\n" + child1_inference + "\n\n" + first_inference, result_hyps, annotated_children } /*** Initial Formula Management ***/ -// Processes the formula that was proven by Goéland. -func processMainFormula(form AST.Form) (Lib.List[AST.Form], AST.Form) { - formList := Lib.NewList[AST.Form]() - switch nf := form.(type) { - case AST.Not: - form = nf.GetForm() - case AST.And: - last := nf.GetChildFormulas().Len() - 1 - formList = Lib.MkListV(nf.GetChildFormulas().Get(0, last)...) - form = nf.GetChildFormulas().At(last).(AST.Not).GetForm() - } - return formList, form -} - -// Prints the theorem's name & properly formats the first formula. +// TPTP-style first formula declaration: +// 1. declare all the hypotheses of the theorem as axioms +// 2. declare the base formula func makeTheorem(axioms Lib.List[AST.Form], conjecture AST.Form) string { - var resulting_string string - problemName := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(Glob.GetProblemName(), ".", "_"), "=", "_"), "+", "_") + problemName := CertifUtils.SanitizedTheoremName() + declared_axioms := []string{} for _, ax := range axioms.GetSlice() { - resulting_string = resulting_string + "fof(" + fmt.Sprintf("ax%d", ax.GetIndex()) + ", axiom, " + - ax.ToString() + ").\n\n" - } - - resulting_string = resulting_string + "fof(c_" + problemName + ", conjecture, " + conjecture.ToString() + ").\n\n" - return resulting_string -} - -// Perform the first step to go from ax |- c to ax, ~c |- -func performFirstStep(axioms Lib.List[AST.Form], conjecture AST.Form, hypothesis Lib.List[AST.Form], nextId int) (string, int) { - cutFormNotId := incrByOne(&id_proof_step, &mutex_proof_step) - cutFormHypId := incrByOne(&id_proof_step, &mutex_proof_step) - nextFormId := incrByOne(&id_proof_step, &mutex_proof_step) - - // Cut initial formula, |- ~c, c step - cutFormNot := fmt.Sprintf("fof("+prefix_step+"%d, plain, [%s] --> [%s, %s], inference(%s, [status(thm), %d], [%s])).", - cutFormNotId, - Lib.ListToString(axioms, ", ", ""), - conjecture.ToString(), - AST.MakerNot(conjecture).ToString(), - "rightNot", - 1, - prefix_step+strconv.Itoa(cutFormHypId)) - - // Cut initial formula, c |- c step - cutFormHyp := fmt.Sprintf("fof("+prefix_step+"%d, plain, [%s] --> [%s], inference(%s, [status(thm), %d], [%s])).", - cutFormHypId, - Lib.ListToString(Lib.MkListV(append(axioms.GetSlice(), conjecture)...), ", ", ""), - conjecture.ToString(), - "hyp", - axioms.Len(), - // 0, - "") - - // Actual start of the formula with H |- C - // indexHyp, _ := hypothesis.GetIndexOf(AST.MakerNot(conjecture)) - startForm := fmt.Sprintf("fof(f%d, plain, [%s] --> [%s], inference(cut, [status(thm), %d], [%s%d, %s%d])).\n\n", - nextId, - Lib.ListToString(axioms, ", ", ""), - conjecture.ToString(), - 1, - //indexHyp, - prefix_step, - cutFormNotId, - prefix_step, - nextFormId) - - return cutFormHyp + "\n\n" + cutFormNot + "\n\n" + startForm, nextFormId -} - -// Perform the cut axiom steps -func performCutAxiomStep(axioms Lib.List[AST.Form], conjecture AST.Form) string { - - resultString := "" - - // Loop on axioms - for i, ax := range axioms.GetSlice() { - var nextStep string - if i == axioms.Len()-1 { - nextStep = "f0" - } else { - nextStep = prefix_axiom_cut + strconv.Itoa(i+1) - } - - cutAxiomStep := fmt.Sprintf("fof(%s%d, plain, [%s] --> [%s], inference(cut, [status(thm), %d], [%s%d, %s])).\n", - prefix_axiom_cut, - i, - // AST.ListToMappedString(axioms.GetElements(0, i), ", ", "", tptpMapConnectors(), GetTypeProof()), - Lib.ListToString(Lib.MkListV(axioms.Get(0, i)...), ", ", ""), - conjecture.ToString(), - 0, - //i, - "ax", - ax.GetIndex(), - nextStep) - - resultString = cutAxiomStep + "\n" + resultString - } - return resultString + "\n" -} - -/*** Utility Functions ***/ - -func get(f AST.Form, fl Lib.List[AST.Form]) int { - switch index := Lib.ListIndexOf(f, fl).(type) { - case Lib.Some[int]: - return index.Val - case Lib.None[int]: - Glob.Anomaly( - "TPTP", - fmt.Sprintf("Formula %s not found in context", f.ToString()), + declared_axioms = append( + declared_axioms, + fmt.Sprintf("fof(ax%d, axiom, %s).", ax.GetIndex(), ax.ToString()), ) } - return -1 -} -func isPredEqual(f AST.Form) bool { - if not, isNot := f.(AST.Not); isNot { - f = not.GetForm() - } - if p, isPred := f.(AST.Pred); isPred { - return p.GetID().Equals(AST.Id_eq) - } - return false -} + declared_axioms = append( + declared_axioms, + fmt.Sprintf("fof(c_%s, conjecture, %s).", problemName, conjecture.ToString()), + ) -func incrByOne(cpt *int, mutex *sync.Mutex) int { - res := -1 - mutex.Lock() - *cpt = (*cpt) + 1 - res = *cpt - mutex.Unlock() - return res + return strings.Join(declared_axioms, "\n\n") + "\n\n" } -func updateId(proof *gs3.GS3Sequent, i int) { - if i != -1 { - proof.SetId(i) - } -} - -func updateSkolemSymbol(old, new AST.Term, proof *gs3.GS3Sequent) *gs3.GS3Sequent { - - // Update Target Form - new_target_form, _ := proof.GetTargetForm().ReplaceTermByTerm(old, new) - proof.SetTargetForm(new_target_form) - - // Update generated term - if proof.TermGenerated() != nil { - new_generated_term := proof.TermGenerated().ReplaceSubTermBy(old, new) - proof.SetTermGenerated(new_generated_term) - } - - new_forms_generated := make([]Lib.List[AST.Form], len(proof.GetResultFormulasOfChildren())) - for i, fg := range proof.GetResultFormulasOfChildren() { - new_forms_generated_bis := Lib.NewList[AST.Form]() - for _, fg_bis := range fg.GetSlice() { - new_term, _ := fg_bis.ReplaceTermByTerm(old, new) - new_forms_generated_bis.Append(new_term) - } - new_forms_generated[i] = new_forms_generated_bis - } - proof.SetFormGenerated(new_forms_generated) - - // Update Children - new_children := make([]*gs3.GS3Sequent, len(proof.Children())) - for i, child := range proof.Children() { - new_children[i] = updateSkolemSymbol(old, new, child) - } - - proof.SetChildren(new_children) - - return proof -} - -/*** Constant created Management ***/ - -func createNewConstant(term AST.Term) AST.Term { - mutex_constant.Lock() - new_id := len(constant_created) - new_term_name := fmt.Sprintf("%s%d", prefix_const, new_id) - new_term := AST.MakerConst(AST.MakerNewId(new_term_name)) - original_term = append(original_term, term) - constant_created = append(constant_created, new_term) - mutex_constant.Unlock() - return new_term -} - -func findInConstants(term AST.Term) AST.Term { - if term == nil { - return dummyTerm - } else { - return getCreatedFromOriginal(term) - } -} +// Use DNE to perform the first step to go from [ax |- c] to [ax, ~c |-]. +func performFirstStep( + axioms Lib.List[AST.Form], + conjecture AST.Form, +) (string, int) { + cut_form_not_id := 1 + cut_form_hyp_id := 2 + next_form_id := 3 + + // From a sequent [H1, ..., Hn |- c], cut ~c to get two chidren: [H1, ..., Hn, ~c |-] and [H1, ..., Hn |- ~c, c]. + start := fofInference( + fmt.Sprintf("%s%d", prefix_step, 0), + "plain", + axioms, + Lib.MkListV(conjecture), + "cut", + "1", + Lib.MkListV( + Lib.MkString(fmt.Sprintf("%s%d", prefix_step, cut_form_not_id)), + Lib.MkString(fmt.Sprintf("%s%d", prefix_step, next_form_id)), + ), + ) + + // On the branch [H1, ..., Hn |- ~c, c], apply [rightNot] to get [H1, ..., Hn, c |- c]. + cut_form_not := fofInference( + fmt.Sprintf("%s%d", prefix_step, cut_form_not_id), + "plain", + axioms, + Lib.MkListV[AST.Form](conjecture, AST.MakerNot(conjecture)), + "rightNot", + "1", + Lib.MkListV( + Lib.MkString(fmt.Sprintf("%s%d", prefix_step, cut_form_hyp_id)), + ), + ) + + // Conclude this branch. + cut_form_hyp := fofInference( + fmt.Sprintf("%s%d", prefix_step, cut_form_hyp_id), + "plain", + axioms.Push(conjecture), + Lib.MkListV(conjecture), + "hyp", + fmt.Sprintf("%d", axioms.Len()), + Lib.NewList[Lib.String](), + ) -func getCreatedFromOriginal(term AST.Term) AST.Term { - for i, t := range original_term { - if t.Equals(term) { - return constant_created[i] - } - } - return term + // Use a sequent style and start by the last inference down to the first one + return cut_form_hyp + "\n\n" + cut_form_not + "\n\n" + start, next_form_id } diff --git a/src/Search/print_proof.go b/src/Search/print_proof.go index 69cf734e..783868f3 100644 --- a/src/Search/print_proof.go +++ b/src/Search/print_proof.go @@ -41,10 +41,14 @@ import ( "github.com/GoelandProver/Goeland/Lib" ) -var BasicOutputProofStruct = &OutputProofStruct{ProofOutput: ProofStructListToText, Name: "Basic", Extension: ".proof"} +var BasicOutputProofStruct = &OutputProofStruct{ + ProofOutput: func(finalProof IProof, _ Lib.List[AST.Meta]) string { return finalProof.ToString() }, + Name: "Basic", + Extension: ".proof", +} type OutputProofStruct struct { - ProofOutput func(finalProof []ProofStruct, metaList Lib.List[AST.Meta]) string + ProofOutput func(finalProof IProof, metaList Lib.List[AST.Meta]) string Name string Extension string } @@ -55,7 +59,7 @@ func AddPrintProofAlgorithm(ps *OutputProofStruct) { outputProofStructs = append(outputProofStructs, ps) } -func PrintProof(final_proof []ProofStruct, metaList Lib.Set[AST.Meta]) { +func PrintProof(final_proof TableauxProof, metaList Lib.Set[AST.Meta]) { if !Glob.GetProof() { return } @@ -69,7 +73,10 @@ func PrintProof(final_proof []ProofStruct, metaList Lib.Set[AST.Meta]) { fmt.Printf("%v SZS output end Proof for %v\n", "%", Glob.GetProblemName()) } -func (ps *OutputProofStruct) printProofWithProofStruct(finalProof []ProofStruct, metaList Lib.Set[AST.Meta]) { +func (ps *OutputProofStruct) printProofWithProofStruct( + finalProof TableauxProof, + metaList Lib.Set[AST.Meta], +) { output := ps.ProofOutput(finalProof, metaList.Elements()) if Glob.GetWriteLogs() { diff --git a/src/Search/proof-adapter.go b/src/Search/proof-adapter.go index 99620061..7f31e5f2 100644 --- a/src/Search/proof-adapter.go +++ b/src/Search/proof-adapter.go @@ -87,7 +87,7 @@ func (proof TableauxProof) RuleApplied() TableauxRule { "Rewrite": RuleRew, } - r, ok := rule_map[proof[0].Rule] + r, ok := rule_map[proof[0].Rule_name] if !ok { Glob.Anomaly(label, fmt.Sprintf("Unknown tableau rule %s", proof[0].Rule)) } @@ -95,26 +95,6 @@ func (proof TableauxProof) RuleApplied() TableauxRule { return r } -func (proof TableauxProof) KindOfRule() TableauxRuleKind { - rule := proof.RuleApplied() - - switch rule { - case RuleNotNot, RuleNotOr, RuleNotImp, RuleAnd: - return KindAlpha - case RuleNotAnd, RuleNotEqu, RuleOr, RuleImp, RuleEqu: - return KindBeta - case RuleNotAll, RuleEx: - return KindDelta - case RuleNotEx, RuleAll, RuleReintro: - return KindGamma - case RuleRew: - return KindRew - } - - Glob.Anomaly(label, "Unknown kind of rule") - return 0 -} - func (proof TableauxProof) ResultFormulas() Lib.List[Lib.List[AST.Form]] { proof.makeSanityCheck() @@ -172,23 +152,47 @@ func (proof TableauxProof) TermGenerated() Lib.Option[Lib.Either[AST.Ty, AST.Ter if !(len(proof[0].Result_formulas) == 1 && proof[0].Result_formulas[0].GetForms().Len() == 1) { - return Lib.MkNone[AST.Term]() + return Lib.MkNone[Lib.Either[AST.Ty, AST.Term]]() } source_form := proof[0].Formula.GetForm() target_form := proof[0].Result_formulas[0].GetForms().At(0) - replaced_variable := getReplacedVariable(source_form) + replaced_variable, is_quantified := getReplacedVariable(source_form) + + if !is_quantified { + return Lib.MkNone[Lib.Either[AST.Ty, AST.Term]]() + } + debug(Lib.MkLazy(func() string { + return fmt.Sprintf( + "Trying to get occurrence of %s in %s", + replaced_variable.ToString(), + source_form.ToString(), + ) + })) + occurrence_opt := getOneOccurrence(source_form, replaced_variable) return Lib.OptBind( occurrence_opt, - func(occurrence Lib.List[Lib.Int]) Lib.Option[AST.Term] { + func(occurrence Lib.List[Lib.Int]) Lib.Option[Lib.Either[AST.Ty, AST.Term]] { + debug(Lib.MkLazy(func() string { + return fmt.Sprintf( + "Target: %s, occurrence: [%s]", + getCleanForm(target_form).ToString(), + Lib.ListToString(occurrence, ", ", ""), + ) + })) return Lib.MkSome(getTermAtOcc(target_form, occurrence)) }, ) } +func (proof TableauxProof) ToString() string { + json_content := ProofStructListToJsonProofStructList(proof) + return JsonProofStructListToText(json_content) +} + // ---------------------------------------------------------------------------- // Private utility functions // ---------------------------------------------------------------------------- @@ -220,12 +224,12 @@ func getAtomic(f AST.Form) AST.Form { return nil } -func getReplacedVariable(form AST.Form) AST.TypedVar { - get_first := func(vars Lib.List[AST.TypedVar]) AST.TypedVar { +func getReplacedVariable(form AST.Form) (AST.TypedVar, bool) { + get_first := func(vars Lib.List[AST.TypedVar]) (AST.TypedVar, bool) { if vars.Empty() { - Glob.Anomaly(label, "Found a quantified formula with an empty list of vars") + return AST.TypedVar{}, false } - return vars.At(0) + return vars.At(0), true } switch f := form.(type) { @@ -242,39 +246,41 @@ func getReplacedVariable(form AST.Form) AST.TypedVar { } } - Glob.Anomaly(label, "Found quantifier rule on non-quantified formula") - return AST.TypedVar{} + return AST.TypedVar{}, false } // A variable might be quantified but never appear in a formula func getOneOccurrence(form AST.Form, v AST.TypedVar) Lib.Option[Lib.List[Lib.Int]] { - clean_form := getCleanForm(form) - return getOneOccInCleanForm(clean_form, v, Lib.NewList[Lib.Int]()) + return getOneOccInCleanForm(getCleanForm(form), v, Lib.NewList[Lib.Int]()) } func getTermAtOcc(form AST.Form, occurrence Lib.List[Lib.Int]) Lib.Either[AST.Ty, AST.Term] { - clean_form := getCleanForm(form) - return getTermAtOccInCleanForm(clean_form, occurrence) + return getTermAtOccInCleanForm(getCleanForm(form), occurrence) } func getCleanForm(form AST.Form) AST.Form { + switch f := form.(type) { + case AST.Not: + return AST.MakerNot(getCleanForm_rec(f.GetForm())) + } + return getCleanForm_rec(form) +} + +func getCleanForm_rec(form AST.Form) AST.Form { switch f := form.(type) { case AST.All: - return f.GetForm() + return getCleanForm(f.GetForm()) case AST.Ex: - return f.GetForm() - case AST.Not: - switch nf := f.GetForm().(type) { - case AST.All: - return AST.MakerNot(nf.GetForm()) - case AST.Ex: - return AST.MakerNot(nf.GetForm()) - } + return getCleanForm(f.GetForm()) } return form } -func getOneOccInCleanForm(form AST.Form, v AST.TypedVar, occurrence Lib.List[Lib.Int]) Lib.Option[Lib.List[Lib.Int]] { +func getOneOccInCleanForm( + form AST.Form, + v AST.TypedVar, + occurrence Lib.List[Lib.Int], +) Lib.Option[Lib.List[Lib.Int]] { switch f := form.(type) { case AST.Pred: return getFunctionalOcc(f.GetTyArgs(), f.GetArgs(), v, occurrence) @@ -293,7 +299,10 @@ func getOneOccInCleanForm(form AST.Form, v AST.TypedVar, occurrence Lib.List[Lib return Lib.MkNone[Lib.List[Lib.Int]]() } -func getTermAtOccInCleanForm(form AST.Form, occurrence Lib.List[Lib.Int]) Lib.Either[AST.Ty, AST.Term] { +func getTermAtOccInCleanForm( + form AST.Form, + occurrence Lib.List[Lib.Int], +) Lib.Either[AST.Ty, AST.Term] { switch f := form.(type) { case AST.Pred: return getFunctionalTermAtOcc(f.GetTyArgs(), f.GetArgs(), occurrence) @@ -339,13 +348,21 @@ func getFunctionalTermAtOcc( terms Lib.List[AST.Term], occurrence Lib.List[Lib.Int], ) Lib.Either[AST.Ty, AST.Term] { + if occurrence.Empty() { + Glob.Anomaly(label, "An occurrence stops at the formula-level") + } + index := int(occurrence.At(0)) next_occ := occurrence.Slice(1, occurrence.Len()) if index < tys.Len() { return Lib.MkLeft[AST.Ty, AST.Term](getTermInTy(tys.At(index), next_occ)) } else { - return getTermInTerm(terms.At(index), next_occ) + if index-tys.Len() >= terms.Len() { + Glob.Anomaly(label, "Searching for an occurrence of an unknown term") + } + + return getTermInTerm(terms.At(index-tys.Len()), next_occ) } } @@ -355,7 +372,11 @@ func appCopy[A Lib.Copyable[A]](x A, ls Lib.List[A]) Lib.List[A] { return result_list } -func getOneOccInTy(ty AST.Ty, v AST.TyBound, occurrence Lib.List[Lib.Int]) Lib.Option[Lib.List[Lib.Int]] { +func getOneOccInTy( + ty AST.Ty, + v AST.TyBound, + occurrence Lib.List[Lib.Int], +) Lib.Option[Lib.List[Lib.Int]] { switch t := ty.(type) { case AST.TyBound: if t.Equals(v) { @@ -400,7 +421,11 @@ func getTermInTy(ty AST.Ty, occurrence Lib.List[Lib.Int]) AST.Ty { } } -func getOneOccInTrm(trm AST.Term, v AST.TypedVar, occurrence Lib.List[Lib.Int]) Lib.Option[Lib.List[Lib.Int]] { +func getOneOccInTrm( + trm AST.Term, + v AST.TypedVar, + occurrence Lib.List[Lib.Int], +) Lib.Option[Lib.List[Lib.Int]] { switch t := trm.(type) { case AST.Var: if t.Equals(v.ToBoundVar()) { @@ -419,19 +444,20 @@ func getTermInTerm(trm AST.Term, occurrence Lib.List[Lib.Int]) Lib.Either[AST.Ty if occurrence.Empty() { return Lib.MkRight[AST.Ty, AST.Term](trm) } else { - switch t := trm.(type) { - case AST.Fun: - return getFunctionalTermAtOcc(t.GetTyArgs(), t.GetArgs(), occurrence) - } - debug(Lib.MkLazy(func() string { return fmt.Sprintf( - "Tried to get occurrence [%s] in %s", + "Trying to get occurrence [%s] in %s", Lib.ListToString(occurrence, ", ", ""), trm.ToString(), ) })) - Glob.Anomaly(label, "Occurrence not found in type") + + switch t := trm.(type) { + case AST.Fun: + return getFunctionalTermAtOcc(t.GetTyArgs(), t.GetArgs(), occurrence) + } + + Glob.Anomaly(label, "Occurrence not found in term") return nil } } diff --git a/src/Search/proof.go b/src/Search/proof.go index e7bcecad..bce95dd1 100644 --- a/src/Search/proof.go +++ b/src/Search/proof.go @@ -149,14 +149,28 @@ func IntFormAndTermsListListToString(fll []IntFormAndTermsList) string { } func (p ProofStruct) ToString() string { - res := "(" + strconv.Itoa(p.GetNodeId()) + ")" + p.GetFormula().ToString() + " - " + p.GetRule() + " - " + IntFormAndTermsListListToString(p.GetResultFormulas()) + res := "(" + strconv.Itoa( + p.GetNodeId(), + ) + ")" + p.GetFormula(). + ToString() + + " - " + p.GetRule() + " - " + IntFormAndTermsListListToString( + p.GetResultFormulas(), + ) if len(p.GetChildren()) > 0 { res += " - " + ProofChildrenToString(p.GetChildren()) } return res } func (p ProofStruct) Copy() ProofStruct { - return ProofStruct{p.GetFormula(), p.GetIdDMT(), p.GetNodeId(), p.GetRule(), p.GetRuleName(), p.GetResultFormulas(), copyProofStructChildren(p.Children)} + return ProofStruct{ + p.GetFormula(), + p.GetIdDMT(), + p.GetNodeId(), + p.GetRule(), + p.GetRuleName(), + p.GetResultFormulas(), + copyProofStructChildren(p.Children), + } } func ProofStructListToString(l []ProofStruct) string { @@ -249,7 +263,13 @@ func MakeEmptyProofStruct() ProofStruct { } } -func MakeProofStruct(formula Core.FormAndTerms, formula_use, id int, rule, rule_name string, Result_formulas []IntFormAndTermsList, children [][]ProofStruct) ProofStruct { +func MakeProofStruct( + formula Core.FormAndTerms, + formula_use, id int, + rule, rule_name string, + Result_formulas []IntFormAndTermsList, + children [][]ProofStruct, +) ProofStruct { return ProofStruct{formula, formula_use, id, rule, rule_name, Result_formulas, children} } @@ -286,7 +306,15 @@ func IntFormAndTermsListToIntIntStringPairList(fl []IntFormAndTermsList) []IntIn func ProofStructListToJsonProofStructList(ps []ProofStruct) []JsonProofStruct { res := []JsonProofStruct{} for _, p := range ps { - new_json_element := JsonProofStruct{p.GetFormula().GetForm().ToString(), p.GetIdDMT(), p.Node_id, p.Rule, p.Rule_name, IntFormAndTermsListToIntIntStringPairList(p.Result_formulas), proofStructChildrenToJsonProofStructChildren(p.Children)} + new_json_element := JsonProofStruct{ + p.GetFormula().GetForm().ToString(), + p.GetIdDMT(), + p.Node_id, + p.Rule, + p.Rule_name, + IntFormAndTermsListToIntIntStringPairList(p.Result_formulas), + proofStructChildrenToJsonProofStructChildren(p.Children), + } res = append(res, new_json_element) } return res @@ -377,11 +405,6 @@ func JsonProofStructListToText(jps []JsonProofStruct) string { return res } -func ProofStructListToText(ps []ProofStruct, metaList Lib.List[AST.Meta]) string { - json_content := ProofStructListToJsonProofStructList(ps) - return JsonProofStructListToText(json_content) -} - func RetrieveUninstantiatedMetaFromProof(proofStruct []ProofStruct) Lib.Set[AST.Meta] { res := Lib.EmptySet[AST.Meta]() @@ -404,7 +427,10 @@ func RetrieveUninstantiatedMetaFromProof(proofStruct []ProofStruct) Lib.Set[AST. } /* Apply subst on a proof tree */ -func ApplySubstitutionOnProofList(s Lib.List[Unif.MixedSubstitution], proof_list []ProofStruct) []ProofStruct { +func ApplySubstitutionOnProofList( + s Lib.List[Unif.MixedSubstitution], + proof_list []ProofStruct, +) []ProofStruct { new_proof_list := []ProofStruct{} for _, p := range proof_list { @@ -414,7 +440,10 @@ func ApplySubstitutionOnProofList(s Lib.List[Unif.MixedSubstitution], proof_list for _, f := range p.GetResultFormulas() { new_result_formulas = append( new_result_formulas, - MakeIntFormAndTermsList(f.GetI(), Core.ApplySubstitutionsOnFormAndTermsList(s, f.GetFL())), + MakeIntFormAndTermsList( + f.GetI(), + Core.ApplySubstitutionsOnFormAndTermsList(s, f.GetFL()), + ), ) } p.SetResultFormulasProof(new_result_formulas) diff --git a/src/Search/tableau-proof.go b/src/Search/tableau-proof.go index dcdd4bb5..3b404ec4 100644 --- a/src/Search/tableau-proof.go +++ b/src/Search/tableau-proof.go @@ -38,6 +38,7 @@ package Search import ( "github.com/GoelandProver/Goeland/AST" + "github.com/GoelandProver/Goeland/Glob" "github.com/GoelandProver/Goeland/Lib" ) @@ -61,22 +62,74 @@ const ( RuleNotAll RuleReintro RuleRew + RuleWeaken ) const ( - KindAlpha TableauxRuleKind = iota + KindClosure TableauxRuleKind = iota + KindAlpha KindBeta KindDelta KindGamma KindRew + KindStructural ) +func (r TableauxRule) ToString() string { + smap := map[TableauxRule]string{ + RuleClosure: "Closure", + RuleImp: "BetaImp", + RuleAnd: "AlphaAnd", + RuleOr: "BetaOr", + RuleEqu: "BetaEqu", + RuleEx: "DeltaEx", + RuleAll: "GammaAll", + RuleNotNot: "AlphaNotNot", + RuleNotImp: "AlphaNotImp", + RuleNotAnd: "BetaNotAnd", + RuleNotOr: "AlphaNotOr", + RuleNotEqu: "BetaNotEqu", + RuleNotEx: "GammaNotEx", + RuleNotAll: "DeltaNotAll", + RuleReintro: "Gamma", + RuleRew: "Rew", + RuleWeaken: "Weakening", + } + res, found := smap[r] + if !found { + Glob.Anomaly(label, "Unknown rule") + } + return res +} + +func KindOfRule(r TableauxRule) TableauxRuleKind { + switch r { + case RuleClosure: + return KindClosure + case RuleNotNot, RuleNotOr, RuleNotImp, RuleAnd: + return KindAlpha + case RuleNotAnd, RuleNotEqu, RuleOr, RuleImp, RuleEqu: + return KindBeta + case RuleNotAll, RuleEx: + return KindDelta + case RuleNotEx, RuleAll: + return KindGamma + case RuleRew: + return KindRew + case RuleWeaken, RuleReintro: + return KindStructural + } + + Glob.Anomaly(label, "Unknown kind of rule") + return 0 +} + type IProof interface { AppliedOn() AST.Form RuleApplied() TableauxRule - KindOfRule() TableauxRuleKind ResultFormulas() Lib.List[Lib.List[AST.Form]] Children() Lib.List[IProof] RewrittenWith() Lib.Option[AST.Form] TermGenerated() Lib.Option[Lib.Either[AST.Ty, AST.Term]] + ToString() string } diff --git a/src/Unif/parsing.go b/src/Unif/parsing.go index c8a80fc6..8697f578 100644 --- a/src/Unif/parsing.go +++ b/src/Unif/parsing.go @@ -88,10 +88,18 @@ func (t TermForm) GetMetas() Lib.Set[AST.Meta] { } } -func (t TermForm) GetSubTerms() Lib.List[AST.Term] { +func (t TermForm) GetSubTerms() Lib.Set[AST.Term] { return t.GetTerm().GetSubTerms() } +func (t TermForm) GetSymbols() Lib.Set[AST.Id] { + return t.GetTerm().GetSymbols() +} + +func (t TermForm) Less(oth any) bool { + return t.GetTerm().Less(oth) +} + func (t TermForm) ReplaceMetaByTerm(meta AST.Meta, term AST.Term) AST.Form { return t } @@ -144,7 +152,10 @@ func ParseFormula(formula AST.Form) Sequence { } /* Parses a predicate to machine instructions */ -func getFunctionalArguments(ty_args Lib.List[AST.Ty], trm_args Lib.List[AST.Term]) Lib.List[AST.Term] { +func getFunctionalArguments( + ty_args Lib.List[AST.Ty], + trm_args Lib.List[AST.Term], +) Lib.List[AST.Term] { args := Lib.ListMap(ty_args, AST.TyToTerm) for _, arg := range trm_args.GetSlice() { diff --git a/src/main.go b/src/main.go index 7240cbad..7c321112 100644 --- a/src/main.go +++ b/src/main.go @@ -53,10 +53,11 @@ import ( "github.com/GoelandProver/Goeland/Glob" "github.com/GoelandProver/Goeland/Lib" "github.com/GoelandProver/Goeland/Mods/assisted" + "github.com/GoelandProver/Goeland/Mods/desko" "github.com/GoelandProver/Goeland/Mods/dmt" equality "github.com/GoelandProver/Goeland/Mods/equality/bse" - "github.com/GoelandProver/Goeland/Mods/gs3" "github.com/GoelandProver/Goeland/Mods/lambdapi" + "github.com/GoelandProver/Goeland/Mods/rocq" "github.com/GoelandProver/Goeland/Parser" "github.com/GoelandProver/Goeland/Search" "github.com/GoelandProver/Goeland/Search/incremental" @@ -128,7 +129,11 @@ func presearchLoader() (AST.Form, int) { Glob.PrintInfo( "preloader", - fmt.Sprintf("You are running problem %s on Goeland v.%s", path.Base(problem), Glob.GetVersion()), + fmt.Sprintf( + "You are running problem %s on Goeland v.%s", + path.Base(problem), + Glob.GetVersion(), + ), ) debug( Lib.MkLazy(func() string { @@ -150,7 +155,11 @@ func presearchLoader() (AST.Form, int) { bound = Glob.GetLimit() } - form, bound, contEq, is_typed_include := StatementListToFormula(actual_statements, bound, path.Dir(problem)) + form, bound, contEq, is_typed_include := StatementListToFormula( + actual_statements, + bound, + path.Dir(problem), + ) containsEquality = containsEquality || contEq if !containsEquality { @@ -210,8 +219,9 @@ func initDebuggers() { Typing.InitDebugger() Unif.InitDebugger() Engine.InitDebugger() - gs3.InitDebugger() + desko.InitDebugger() lambdapi.InitDebugger() + rocq.Init() } // FIXME: eventually, we would want to add an "interpretation" layer between elab and internal representation that does this @@ -231,7 +241,9 @@ func StatementListToFormula( file_name := statement.GetName() realname, err := getFile(file_name, problemDir) - debug(Lib.MkLazy(func() string { return fmt.Sprintf("File to parse : %s\n", realname) })) + debug( + Lib.MkLazy(func() string { return fmt.Sprintf("File to parse : %s\n", realname) }), + ) if err != nil { Glob.PrintError(main_label, err.Error()) @@ -324,7 +336,10 @@ func doTypeStatement(atomTyping Core.TFFAtomTyping) { typeScheme := atomTyping.Ty if typeScheme == nil { - Glob.PrintWarn("main", fmt.Sprintf("The constant %s has no type!", atomTyping.Literal.ToString())) + Glob.PrintWarn( + "main", + fmt.Sprintf("The constant %s has no type!", atomTyping.Literal.ToString()), + ) } Typing.AddToGlobalEnv(atomTyping.Literal.GetName(), atomTyping.Ty) diff --git a/src/options.go b/src/options.go index 48cdf630..cf6bea40 100644 --- a/src/options.go +++ b/src/options.go @@ -11,10 +11,10 @@ import ( "github.com/GoelandProver/Goeland/Glob" "github.com/GoelandProver/Goeland/Lib" "github.com/GoelandProver/Goeland/Mods/assisted" + "github.com/GoelandProver/Goeland/Mods/desko" "github.com/GoelandProver/Goeland/Mods/dmt" equality "github.com/GoelandProver/Goeland/Mods/equality/bse" "github.com/GoelandProver/Goeland/Mods/equality/sateq" - "github.com/GoelandProver/Goeland/Mods/gs3" "github.com/GoelandProver/Goeland/Mods/lambdapi" "github.com/GoelandProver/Goeland/Mods/rocq" "github.com/GoelandProver/Goeland/Mods/tptp" @@ -69,7 +69,13 @@ Using this function, you can initialize an option of type T. - funcAlways : a function that will be called regardless if the option was used or not (if it wasn't, the parameter will be 'defaultValue') */ -func (op *option[T]) init(name string, defaultValue T, usage string, funcNotDefault func(T), funcAlways func(T)) { +func (op *option[T]) init( + name string, + defaultValue T, + usage string, + funcNotDefault func(T), + funcAlways func(T), +) { op.initOption(defaultValue, funcNotDefault, funcAlways) switch any(defaultValue).(type) { @@ -96,21 +102,24 @@ func initOpts() { } } -/** +/* +* * An option has a type T and is initialized with five parameters: * name string: the name of the option that will be used in the command line. * defaultValue T: the default value that will be used if the option is not used. * usage string: the description on how to use and what the option does. * funcNotDefault func(T): a function that will be run if the option has changed from its default value. The parameter will be the value of the option. * funcAlways func(T): a function that will always be run. The parameter will be the value of the option. -**/ +* + */ func buildOptions() { (&option[string]{}).init( "debug", "none", "Enables printing debug information in the terminal. Debugging a specific part of the code is possible via -debug a,b,c which will output the debugs of parts a, b and c. If you want all the debugs, use -debug all.", Glob.SetDebug, - func(string) {}) + func(string) {}, + ) (&option[bool]{}).init( "silent", false, @@ -207,7 +216,8 @@ func buildOptions() { false, "Should only be used with the -proof parameter. Enables UTF-8 characters in prints for a pretty proof", func(bool) { AST.SetPrinter(AST.PrettyPrinter) }, - func(bool) {}) + func(bool) {}, + ) (&option[bool]{}).init( "dmt", false, @@ -301,7 +311,8 @@ func buildOptions() { false, "Should only be used with the -orocq or the -olp parameters. Enables the context for a standalone execution", func(bool) { rocq.SetContextEnabled(true) }, - func(bool) {}) + func(bool) {}, + ) (&option[bool]{}).init( "inner", false, @@ -319,7 +330,8 @@ func buildOptions() { Core.SetSelectedSkolemization(Sko.MkPreInnerSkolemization()) Glob.SetPreInnerSko(true) }, - func(bool) {}) + func(bool) {}, + ) (&option[bool]{}).init( "assisted", false, @@ -361,7 +373,8 @@ func buildOptions() { func(bool) { chronoInit() }, - func(bool) {}) + func(bool) {}, + ) (&option[bool]{}).init( "incr", false, @@ -377,7 +390,8 @@ func buildOptions() { func(string) {}, func(val string) { Glob.ProofFile = val - }) + }, + ) (&option[bool]{}).init( "vec", false, @@ -388,7 +402,8 @@ func buildOptions() { maxInt := math.MaxInt Glob.SetLimit(maxInt) }, - func(bool) {}) + func(bool) {}, + ) (&option[bool]{}).init( "print-id", false, @@ -423,7 +438,7 @@ func buildOptions() { func chronoInit() { old_rocq := rocq.MakeRocqProof - rocq.MakeRocqProof = func(proof *gs3.GS3Sequent, meta Lib.List[AST.Meta]) string { + rocq.MakeRocqProof = func(proof Search.IProof, meta Lib.List[AST.Meta]) string { start := time.Now() result := old_rocq(proof, meta) printChrono("Rocq", start) @@ -431,15 +446,15 @@ func chronoInit() { } oldLP := lambdapi.MakeLambdaPiProof - lambdapi.MakeLambdaPiProof = func(proof *gs3.GS3Sequent, meta Lib.List[AST.Meta]) string { + lambdapi.MakeLambdaPiProof = func(proof Search.IProof, meta Lib.List[AST.Meta]) string { start := time.Now() result := oldLP(proof, meta) printChrono("LP", start) return result } - oldGS3 := gs3.MakeGS3Proof - gs3.MakeGS3Proof = func(proof []Search.ProofStruct) *gs3.GS3Sequent { + oldGS3 := desko.MakeDeskolemizedProof + desko.MakeDeskolemizedProof = func(proof Search.IProof) *desko.GS3Sequent { start := time.Now() result := oldGS3(proof) printChrono("GS3", start) From e2d8d75a2660feb6a453cb72fab8e088b839dbee Mon Sep 17 00:00:00 2001 From: Johann Rosain Date: Tue, 10 Mar 2026 21:40:56 +0100 Subject: [PATCH 23/30] add: update test-suite --- devtools/run-test-suite.py | 107 ++++++++++++--------- devtools/test-suite/bugs/bug_16-1.p | 9 ++ devtools/test-suite/bugs/bug_16-2.p | 13 +++ devtools/test-suite/bugs/bug_46-1.p | 11 +++ devtools/test-suite/bugs/bug_46-2.p | 9 ++ devtools/test-suite/bugs/bug_46-3.p | 10 ++ devtools/test-suite/bugs/bug_46-5.p | 12 +++ devtools/test-suite/bugs/bug_70-1.p | 7 ++ devtools/test-suite/bugs/bug_70-2.p | 7 ++ devtools/test-suite/bugs/bug_70-3.p | 6 ++ devtools/test-suite/bugs_no_chk/bug_46-4.p | 9 ++ src/Makefile | 3 + 12 files changed, 160 insertions(+), 43 deletions(-) create mode 100644 devtools/test-suite/bugs/bug_16-1.p create mode 100644 devtools/test-suite/bugs/bug_16-2.p create mode 100644 devtools/test-suite/bugs/bug_46-1.p create mode 100644 devtools/test-suite/bugs/bug_46-2.p create mode 100644 devtools/test-suite/bugs/bug_46-3.p create mode 100644 devtools/test-suite/bugs/bug_46-5.p create mode 100644 devtools/test-suite/bugs/bug_70-1.p create mode 100644 devtools/test-suite/bugs/bug_70-2.p create mode 100644 devtools/test-suite/bugs/bug_70-3.p create mode 100644 devtools/test-suite/bugs_no_chk/bug_46-4.p diff --git a/devtools/run-test-suite.py b/devtools/run-test-suite.py index a3383f16..39a7cc98 100644 --- a/devtools/run-test-suite.py +++ b/devtools/run-test-suite.py @@ -9,21 +9,19 @@ from subprocess import PIPE, run class Parser: - ARGS = "% args: " - RES = "% result: " - ENV = "% env: " - EXIT_CODE = "% exit: " + PARAMETERS = ["args", "result", "env", "exit", "timeout"] no_check = False def __init__(self, filename): self.filename = filename - self.parseArguments() - self.parseResult() - self.parseEnv() - self.parseExitCode() + self.parameters = {} + for param in self.PARAMETERS: + self.parameters[param] = self.parseGen(f"% {param}:").strip() + + self.parameters["env"] = self.parameters["env"].replace("$(PWD)", os.path.dirname(os.path.abspath(__file__))) args_avoid_chk = ["-proof", "-otptp", "-osctptp"] - if "no_chk" in filename or self.expectedExitCode != "" or any(arg in self.arguments for arg in args_avoid_chk) or self.expectedResult == "NOT VALID": + if "no_chk" in filename or self.parameters["exit"] != "" or any(arg in self.parameters["args"] for arg in args_avoid_chk) or self.parameters["result"] == "NOT VALID": self.no_check = True def parseGen(self, pat): @@ -34,29 +32,24 @@ def parseGen(self, pat): return "" - def parseArguments(self): - self.arguments = self.parseGen(self.ARGS).strip() - - def parseResult(self): - self.expectedResult = self.parseGen(self.RES).strip() - - def parseEnv(self): - self.env = self.parseGen(self.ENV).strip() - # Special string: $(PWD) which replaces it by the directory of the script - self.env = self.env.replace("$(PWD)", os.path.dirname(os.path.abspath(__file__))) - - def parseExitCode(self): - self.expectedExitCode = self.parseGen(self.EXIT_CODE).strip() - def getCommandLine(self, checker_args): - arguments = self.arguments + checker_args - return self.env + " ../src/_build/goeland " + arguments + " " + self.filename + arguments = self.parameters["args"] + checker_args + timeout = "" + try: + timeout = f"timeout {int(self.parameters["timeout"])} " + except ValueError: + pass + + return self.parameters["env"] + " " + timeout + "../src/_build/goeland " + arguments + " " + self.filename def getArgsForPrinting(self): chk_str = "" + timeout_str = "" if self.no_check: chk_str = " (no check)" - return self.arguments + chk_str + if self.parameters["timeout"] != "": + timeout_str = f" (timeout {self.parameters['timeout']}s)" + return self.parameters["args"] + timeout_str + chk_str def sanitize(s): return s.encode('utf-8', errors='ignore').decode(errors='ignore') @@ -115,6 +108,10 @@ def getRocqCompiler() : raise Exception("No Rocq executable found on the system") def makeRocqCheck(f, output): + if "error" in output or not("% SZS output end" in output): + print("Fatal error: an unexpected error has occurred when outputting the ROCQ proof") + exit(1) + check_status, err = makeGenericCheck(getRocqCompiler(), "v", ["glob"], ["v", "vo", "vok", "vos"], f, output) if not check_status: @@ -123,19 +120,35 @@ def makeRocqCheck(f, output): exit(1) def makeLambdapiCheck(f, output): + # As the lambdapi output does not manage equality nor weakening, we tolerate fails for the problems + # of the test suite that have equality / weakening rules / that discard a quantified variable. + lp_tolerated_fails = [ + "TEST_EQ.p", + "TEST_EQ2.p", + "sankalp.p", + "bug_16-1.p", + "bug_16-2.p", + "bug_46-1.p", + "bug_46-2.p", + "bug_46-3.p", + "bug_46-4.p", + "bug_46-5.p", + "bug_70-2.p", + ] + + if (os.path.basename(f) in lp_tolerated_fails): + return + + if "error" in output or not("% SZS output end" in output): + print("Fatal error: an unexpected error has occurred when outputting the LP proof") + exit(1) + lp_command = "lambdapi check --lib-root .. --map-dir Logic.Goeland:../proof-certification/LambdaPi" check_status, err = makeGenericCheck(lp_command, "lp", [], ["lp"], f, output) - # As the lambdapi output does not manage equality, we tolerate fails for the problems - # of the test suite that have equality. - lp_tolerated_fails = ["TEST_EQ.p", "TEST_EQ2.p", "sankalp.p"] - if not check_status: - if os.path.basename(f) in lp_tolerated_fails: - print(f"LAMBDAPI check has failed, but it was expected.") - else: - print(f"LAMBDAPI check has failed") - exit(1) + print(f"LAMBDAPI check has failed") + exit(1) def runWithExpected(f, parser, checker_args, check_fun): """ @@ -154,23 +167,31 @@ def runWithExpected(f, parser, checker_args, check_fun): print(f"Runtime error: {err}") exit(1) - if parser.expectedExitCode != '': - if int(parser.expectedExitCode) != exit_code: - print(f"Error: expected exit code '{parser.expectedExitCode}', got: '{exit_code}'") + if parser.parameters["exit"] != '': + if int(parser.parameters["exit"]) != exit_code: + print(f"Error: expected exit code '{parser.parameters["exit"]}', got: '{exit_code}'") exit(1) else: return + if "error" in output: + print(f"Fatal error: an unexpected error has occurred during proof-search") + exit(1) + search = re.compile(".*% RES : (.*)$") for line in output.split("\n"): res = search.match(line) if res != None: actual = res.group(1) - if actual != parser.expectedResult: - print(f"Error: expected '{parser.expectedResult}', got: '{actual}'") + if actual != parser.parameters["result"]: + print(f"Error: expected '{parser.parameters['result']}', got: '{actual}'") exit(1) else: if parser.no_check: return - output, _, _ = runProver(f, parser.getCommandLine(checker_args)) + output, err, _ = runProver(f, parser.getCommandLine(checker_args)) + if err != "": + print(f"Runtime error when outputing the proof: {err}") + exit(1) + check_fun(f, output) return @@ -212,10 +233,10 @@ def compareOutputs(f, parser): outputTest = ["-proof", "-otptp", "-osctptp"] for f in sorted(glob.glob("test-suite/**/*.p")): parser = Parser(f) + print(f"{f}\t{parser.getArgsForPrinting()}") - if any(out in parser.arguments for out in outputTest) : + if any(out in parser.parameters["args"] for out in outputTest) : compareOutputs(f, parser) else : - print(f"{f}\t{parser.getArgsForPrinting()}") runWithRocqChk(f, parser) runWithLpChk(f, parser) diff --git a/devtools/test-suite/bugs/bug_16-1.p b/devtools/test-suite/bugs/bug_16-1.p new file mode 100644 index 00000000..a594d817 --- /dev/null +++ b/devtools/test-suite/bugs/bug_16-1.p @@ -0,0 +1,9 @@ +% args: -inner +% timeout: 10 +% result: VALID + +fof(problem,conjecture, + ~( ! [X,Y] : ( + (~p(Y) & ? [Z] : p(Z)) | + (~q(X) & ? [Z2] : q(Z2)) + ))). diff --git a/devtools/test-suite/bugs/bug_16-2.p b/devtools/test-suite/bugs/bug_16-2.p new file mode 100644 index 00000000..6cf31f14 --- /dev/null +++ b/devtools/test-suite/bugs/bug_16-2.p @@ -0,0 +1,13 @@ +% args: -preinner +% timeout: 10 +% result: VALID + +fof(problem,conjecture, + ~( ! [X] : + ( ( p(X) & + ( (? [Y] : ~(p(Y))) | + (? [Y] : ~(p(Y))) ) ) ) | + ( ! [Y] : + ( ( q(Y) & + ( (? [Z] : ~(q(Z))) | + (? [Z] : ~(q(Z))) ) ) ) ) )). diff --git a/devtools/test-suite/bugs/bug_46-1.p b/devtools/test-suite/bugs/bug_46-1.p new file mode 100644 index 00000000..51849dee --- /dev/null +++ b/devtools/test-suite/bugs/bug_46-1.p @@ -0,0 +1,11 @@ +% args: -inner +% result: VALID + +fof(church_46_9_2,conjecture, + ? [X] : + ! [Y] : + ( ( ( big_f(X,X) + => big_f(Y,Y) ) + => ( big_f(X,Y) + & big_g(X) ) ) + => big_g(Y) ) ). diff --git a/devtools/test-suite/bugs/bug_46-2.p b/devtools/test-suite/bugs/bug_46-2.p new file mode 100644 index 00000000..07304a5f --- /dev/null +++ b/devtools/test-suite/bugs/bug_46-2.p @@ -0,0 +1,9 @@ +% args: -inner +% result: VALID + +fof(church_46_15_5,conjecture, + ? [X] : + ! [Y] : + ? [Z1,Z2] : + ( big_f(X,Y,Z1,Z2,Z1) + => big_f(Z1,X,Y,Z1,Z2) ) ). diff --git a/devtools/test-suite/bugs/bug_46-3.p b/devtools/test-suite/bugs/bug_46-3.p new file mode 100644 index 00000000..cd7843fd --- /dev/null +++ b/devtools/test-suite/bugs/bug_46-3.p @@ -0,0 +1,10 @@ +% args: -inner +% result: VALID + +fof(church_46_15_6,conjecture, + ? [X1] : + ! [X2] : + ? [X3] : + ! [X4] : + ( big_f(X1,X2,X3) + => big_f(X2,X3,X4) ) ). diff --git a/devtools/test-suite/bugs/bug_46-5.p b/devtools/test-suite/bugs/bug_46-5.p new file mode 100644 index 00000000..66966f25 --- /dev/null +++ b/devtools/test-suite/bugs/bug_46-5.p @@ -0,0 +1,12 @@ +% args: -inner +% result: VALID + +fof(prove_this,conjecture, + ( ! [X] : + ? [Y] : + ( p(X) + & q(Y) ) + => ? [Z] : + ! [Y] : + ( p(Y) + | r(Z) ) ) ). diff --git a/devtools/test-suite/bugs/bug_70-1.p b/devtools/test-suite/bugs/bug_70-1.p new file mode 100644 index 00000000..053cb791 --- /dev/null +++ b/devtools/test-suite/bugs/bug_70-1.p @@ -0,0 +1,7 @@ +% result: VALID + +% This file tests whether the outputs for an existentially quantified variable that does not appear +% in the formula. + +fof(prove_this,conjecture, + ~( ! [X,Y]: (p(Y) & ~p(Y)) ) ). diff --git a/devtools/test-suite/bugs/bug_70-2.p b/devtools/test-suite/bugs/bug_70-2.p new file mode 100644 index 00000000..d6bbf06f --- /dev/null +++ b/devtools/test-suite/bugs/bug_70-2.p @@ -0,0 +1,7 @@ +% result: VALID + +% This file tests whether the outputs for a universally quantified variable that does not appear +% in the formula. + +fof(prove_this,conjecture, + ~( ? [X,Y]: (p(Y) & ~p(Y)) ) ). diff --git a/devtools/test-suite/bugs/bug_70-3.p b/devtools/test-suite/bugs/bug_70-3.p new file mode 100644 index 00000000..e00451e9 --- /dev/null +++ b/devtools/test-suite/bugs/bug_70-3.p @@ -0,0 +1,6 @@ +% result: VALID + +% This file tests the reintroduction rule. + +fof(prove_this,conjecture, + ( ? [X] : (d(X) => (! [X] : d(X) ) ) ) ). diff --git a/devtools/test-suite/bugs_no_chk/bug_46-4.p b/devtools/test-suite/bugs_no_chk/bug_46-4.p new file mode 100644 index 00000000..7a431cdb --- /dev/null +++ b/devtools/test-suite/bugs_no_chk/bug_46-4.p @@ -0,0 +1,9 @@ +% args: -inner +% result: VALID + +fof(x2120,conjecture, + ( ! [U,V,W] : + ( big_p(U,V) + | big_p(V,W) ) + => ? [X] : + ! [Y] : big_p(X,Y) ) ). diff --git a/src/Makefile b/src/Makefile index 6fc4326e..d44b3b71 100644 --- a/src/Makefile +++ b/src/Makefile @@ -29,6 +29,9 @@ ENABLED_TESTS=./Tests/Lib all: build +test-suite: + cd ../devtools && make test-suite + parser: $(GOYACC) $(GOYACCFLAGS) -p $(PREFIX) -o $(GOPARSER) $(YACCFILE) From 2b65427947141d84063eeee42e809bf87b35aa74 Mon Sep 17 00:00:00 2001 From: Johann Rosain Date: Tue, 17 Mar 2026 17:17:50 +0100 Subject: [PATCH 24/30] clean: remove useless indexes in formulas/terms --- src/AST/{formsDef.go => forms-def.go} | 333 +++++++++++++++--------- src/AST/formula.go | 52 ++-- src/AST/maker.go | 70 +---- src/AST/modular-printing.go | 37 +-- src/AST/printers.go | 13 +- src/AST/quantifiers.go | 24 +- src/AST/term.go | 15 +- src/AST/{termsDef.go => terms-def.go} | 96 +++---- src/AST/tptp-native-types.go | 2 - src/AST/ty-syntax.go | 52 ++-- src/AST/typed-vars.go | 39 +-- src/Core/Sko/inner-skolemization.go | 2 +- src/Core/Sko/interface.go | 6 +- src/Core/Sko/outer-skolemization.go | 2 +- src/Core/Sko/preinner-skolemization.go | 35 ++- src/Core/skolemisation.go | 10 +- src/Lib/list.go | 20 ++ src/Mods/desko/proof.go | 25 +- src/Mods/desko/sequent.go | 9 +- src/Mods/dmt/dmt.go | 4 +- src/Mods/dmt/rewrite.go | 85 +++++- src/Mods/equality/bse/equality_types.go | 8 +- src/Mods/equality/sateq/problem.go | 55 +++- src/Mods/equality/sateq/termrep.go | 8 +- src/Mods/lambdapi/output.go | 4 +- src/Mods/rocq/output.go | 4 +- src/Mods/tptp/proof.go | 22 +- src/Search/proof-adapter.go | 2 +- src/Search/proof.go | 2 +- src/Unif/instruction.go | 6 +- src/Unif/machine.go | 22 +- src/Unif/parsing.go | 12 +- src/Unif/substitutions_type.go | 18 +- 33 files changed, 623 insertions(+), 471 deletions(-) rename src/AST/{formsDef.go => forms-def.go} (78%) rename src/AST/{termsDef.go => terms-def.go} (86%) diff --git a/src/AST/formsDef.go b/src/AST/forms-def.go similarity index 78% rename from src/AST/formsDef.go rename to src/AST/forms-def.go index b705c815..2c12971c 100644 --- a/src/AST/formsDef.go +++ b/src/AST/forms-def.go @@ -87,16 +87,16 @@ type All struct { quantifier } -func MakeAllSimple(i int, vars Lib.List[TypedVar], forms Form, metas Lib.Set[Meta]) All { - return All{makeQuantifier(i, vars, forms, metas, ConnAll)} +func MakeAllSimple(vars Lib.List[TypedVar], forms Form, metas Lib.Set[Meta]) All { + return All{makeQuantifier(vars, forms, metas, ConnAll)} } -func MakeAll(i int, vars Lib.List[TypedVar], forms Form) All { - return MakeAllSimple(i, vars, forms, Lib.EmptySet[Meta]()) +func MakeAll(vars Lib.List[TypedVar], forms Form) All { + return MakeAllSimple(vars, forms, Lib.EmptySet[Meta]()) } func MakerAll(vars Lib.List[TypedVar], forms Form) All { - return MakeAll(MakerIndexFormula(), vars, forms) + return MakeAll(vars, forms) } func (a All) Equals(other any) bool { @@ -135,7 +135,17 @@ func (a All) ReplaceMetaByTerm(meta Meta, term Term) Form { return All{a.quantifier.replaceMetaByTerm(meta, term)} } -func (a All) Less(oth any) bool { return less(a, oth) } +func (a All) Less(oth any) bool { + if form, is_form := oth.(Form); is_form { + switch f := form.(type) { + case All: + return qLess(a.varList, f.varList, a.subForm, f.subForm) + default: + return false + } + } + return false +} // ----------------------------------------------------------------------------- // Exists @@ -144,16 +154,16 @@ type Ex struct { quantifier } -func MakeExSimple(i int, vars Lib.List[TypedVar], forms Form, metas Lib.Set[Meta]) Ex { - return Ex{makeQuantifier(i, vars, forms, metas, ConnEx)} +func MakeExSimple(vars Lib.List[TypedVar], forms Form, metas Lib.Set[Meta]) Ex { + return Ex{makeQuantifier(vars, forms, metas, ConnEx)} } -func MakeEx(i int, vars Lib.List[TypedVar], forms Form) Ex { - return MakeExSimple(i, vars, forms, Lib.EmptySet[Meta]()) +func MakeEx(vars Lib.List[TypedVar], forms Form) Ex { + return MakeExSimple(vars, forms, Lib.EmptySet[Meta]()) } func MakerEx(vars Lib.List[TypedVar], forms Form) Ex { - return MakeEx(MakerIndexFormula(), vars, forms) + return MakeEx(vars, forms) } func (e Ex) Equals(other any) bool { @@ -192,39 +202,46 @@ func (e Ex) ReplaceMetaByTerm(meta Meta, term Term) Form { return Ex{e.quantifier.replaceMetaByTerm(meta, term)} } -func (e Ex) Less(oth any) bool { return less(e, oth) } +func (e Ex) Less(oth any) bool { + if form, is_form := oth.(Form); is_form { + switch f := form.(type) { + case All: + return true + case Ex: + return qLess(e.varList, f.varList, e.subForm, f.subForm) + default: + return false + } + } + return false +} // ----------------------------------------------------------------------------- // Or type Or struct { - index int forms Lib.List[Form] metas Lib.Cache[Lib.Set[Meta], Or] } /** Constructors **/ -func MakeOrSimple(i int, forms Lib.List[Form], metas Lib.Set[Meta]) Or { - return Or{i, forms, Lib.MkCache(metas, Or.forceGetMetas)} +func MakeOrSimple(forms Lib.List[Form], metas Lib.Set[Meta]) Or { + return Or{forms, Lib.MkCache(metas, Or.forceGetMetas)} } -func MakeOr(i int, forms Lib.List[Form]) Or { - return MakeOrSimple(i, forms, Lib.EmptySet[Meta]()) +func MakeOr(forms Lib.List[Form]) Or { + return MakeOrSimple(forms, Lib.EmptySet[Meta]()) } func MakerOr(forms Lib.List[Form]) Or { - return MakeOr(MakerIndexFormula(), forms) + return MakeOr(forms) } /** Methods **/ /** - Form interface Methods **/ -func (o Or) GetIndex() int { - return o.index -} - func (o Or) forceGetMetas() Lib.Set[Meta] { return metasUnion(o.forms) } @@ -260,7 +277,6 @@ func (o Or) Equals(f any) bool { func (o Or) Copy() Form { return Or{ - o.index, Lib.ListCpy(o.forms), o.metas.Copy(Lib.Set[Meta].Copy), } @@ -275,7 +291,7 @@ func (o Or) ToString() string { func (o Or) ReplaceTermByTerm(old Term, new Term) (Form, bool) { formList, res := replaceTermInFormList(o.forms, old, new) - no := MakeOrSimple(o.GetIndex(), formList, o.metas.Raw()) + no := MakeOrSimple(formList, o.metas.Raw()) if !res && !o.metas.NeedsUpd() { no.metas.AvoidUpd() } @@ -284,16 +300,16 @@ func (o Or) ReplaceTermByTerm(old Term, new Term) (Form, bool) { func (o Or) SubstTy(old TyGenVar, new Ty) Form { formList := replaceTyVarInFormList(o.forms, old, new) - return MakeOrSimple(o.GetIndex(), formList, o.metas.Raw()) + return MakeOrSimple(formList, o.metas.Raw()) } func (o Or) RenameVariables() Form { - return MakeOr(o.GetIndex(), renameFormList(o.forms)) + return MakeOr(renameFormList(o.forms)) } func (o Or) SubstituteVarByMeta(old Var, new Meta) Form { newFormList, newMetas := substVarByMetaInFormList(old, new, o.forms, o.metas.Raw()) - return MakeOrSimple(o.index, newFormList, newMetas) + return MakeOrSimple(newFormList, newMetas) } func (o Or) GetSubFormulasRecur() Lib.List[Form] { @@ -305,59 +321,65 @@ func (o Or) GetChildFormulas() Lib.List[Form] { } func (o Or) ReplaceMetaByTerm(meta Meta, term Term) Form { - return MakeOr(o.GetIndex(), LsSubstByTerm(o.forms, meta, term)) + return MakeOr(LsSubstByTerm(o.forms, meta, term)) } -func (o Or) Less(oth any) bool { return less(o, oth) } +func (o Or) Less(oth any) bool { + if form, is_form := oth.(Form); is_form { + switch f := form.(type) { + case All, Ex: + return true + case Or: + return bLess(o.forms, f.forms) + default: + return false + } + } + return false +} // ----------------------------------------------------------------------------- // And type And struct { - index int forms Lib.List[Form] metas Lib.Cache[Lib.Set[Meta], And] } /** Constructors **/ -func MakeAndSimple(i int, forms Lib.List[Form], metas Lib.Set[Meta]) And { - return And{i, forms, Lib.MkCache(metas, And.forceGetMetas)} +func MakeAndSimple(forms Lib.List[Form], metas Lib.Set[Meta]) And { + return And{forms, Lib.MkCache(metas, And.forceGetMetas)} } -func MakeAndSimpleBinary(i int, forms Lib.List[Form], metas Lib.Set[Meta]) And { +func MakeAndSimpleBinary(forms Lib.List[Form], metas Lib.Set[Meta]) And { switch forms.Len() { // FIXME: case 0 and 1 should error, no? case 0, 1, 2: - return MakeAndSimple(i, forms, metas) + return MakeAndSimple(forms, metas) default: return MakeAndSimple( - i, Lib.MkListV[Form](forms.At(0), MakerAnd(forms.Slice(1, forms.Len()), true)), metas) } } -func MakeAnd(i int, forms Lib.List[Form], binary ...bool) And { +func MakeAnd(forms Lib.List[Form], binary ...bool) And { if binary != nil { - return MakeAndSimpleBinary(i, forms, Lib.EmptySet[Meta]()) + return MakeAndSimpleBinary(forms, Lib.EmptySet[Meta]()) } else { - return MakeAndSimple(i, forms, Lib.EmptySet[Meta]()) + return MakeAndSimple(forms, Lib.EmptySet[Meta]()) } } func MakerAnd(forms Lib.List[Form], binary ...bool) And { - return MakeAnd(MakerIndexFormula(), forms, binary...) + return MakeAnd(forms, binary...) } /** Methods **/ /** - Form interface Methods **/ -func (a And) GetIndex() int { - return a.index -} - func (a And) forceGetMetas() Lib.Set[Meta] { return metasUnion(a.forms) } @@ -396,7 +418,6 @@ func (a And) Equals(other any) bool { func (a And) Copy() Form { return And{ - a.index, Lib.ListCpy(a.forms), a.metas.Copy(Lib.Set[Meta].Copy), } @@ -411,7 +432,7 @@ func (a And) ToString() string { func (a And) ReplaceTermByTerm(old Term, new Term) (Form, bool) { varList, res := replaceTermInFormList(a.forms, old, new) - na := MakeAndSimple(a.index, varList, a.metas.Raw()) + na := MakeAndSimple(varList, a.metas.Raw()) if !res && !a.metas.NeedsUpd() { na.metas.AvoidUpd() } @@ -420,16 +441,16 @@ func (a And) ReplaceTermByTerm(old Term, new Term) (Form, bool) { func (a And) SubstTy(old TyGenVar, new Ty) Form { formList := replaceTyVarInFormList(a.forms, old, new) - return MakeAndSimple(a.GetIndex(), formList, a.metas.Raw()) + return MakeAndSimple(formList, a.metas.Raw()) } func (a And) RenameVariables() Form { - return MakeAnd(a.GetIndex(), renameFormList(a.forms)) + return MakeAnd(renameFormList(a.forms)) } func (a And) SubstituteVarByMeta(old Var, new Meta) Form { newFormList, newMetas := substVarByMetaInFormList(old, new, a.forms, a.metas.Raw()) - return MakeAndSimple(a.index, newFormList, newMetas) + return MakeAndSimple(newFormList, newMetas) } func (a And) GetSubFormulasRecur() Lib.List[Form] { @@ -441,43 +462,51 @@ func (a And) GetChildFormulas() Lib.List[Form] { } func (a And) ReplaceMetaByTerm(meta Meta, term Term) Form { - return MakeAnd(a.GetIndex(), LsSubstByTerm(a.forms, meta, term)) + return MakeAnd(LsSubstByTerm(a.forms, meta, term)) } -func (a And) Less(oth any) bool { return less(a, oth) } +func (a And) Less(oth any) bool { + if form, is_form := oth.(Form); is_form { + switch f := form.(type) { + case All, Ex, Or: + return true + case And: + return bLess(a.forms, f.forms) + default: + return false + } + } + return false +} // ----------------------------------------------------------------------------- // Equivalence type Equ struct { - index int f1, f2 Form metas Lib.Cache[Lib.Set[Meta], Equ] } -func MakeEquSimple(i int, firstForm, secondForm Form, metas Lib.Set[Meta]) Equ { +func MakeEquSimple(firstForm, secondForm Form, metas Lib.Set[Meta]) Equ { return Equ{ - i, firstForm, secondForm, Lib.MkCache(metas, Equ.forceGetMetas), } } -func MakeEqu(i int, firstForm, secondForm Form) Equ { - return MakeEquSimple(i, firstForm, secondForm, Lib.EmptySet[Meta]()) +func MakeEqu(firstForm, secondForm Form) Equ { + return MakeEquSimple(firstForm, secondForm, Lib.EmptySet[Meta]()) } func MakerEqu(firstForm, secondForm Form) Equ { - return MakeEqu(MakerIndexFormula(), firstForm, secondForm) + return MakeEqu(firstForm, secondForm) } -func (e Equ) GetIndex() int { return e.index } -func (e Equ) GetF1() Form { return e.f1.Copy() } -func (e Equ) GetF2() Form { return e.f2.Copy() } +func (e Equ) GetF1() Form { return e.f1.Copy() } +func (e Equ) GetF2() Form { return e.f2.Copy() } func (e Equ) Copy() Form { return Equ{ - e.index, e.GetF1(), e.GetF2(), e.metas.Copy(Lib.Set[Meta].Copy), @@ -512,7 +541,7 @@ func (e Equ) Equals(f any) bool { func (e Equ) ReplaceTermByTerm(old Term, new Term) (Form, bool) { f1, res1 := e.GetF1().ReplaceTermByTerm(old, new) f2, res2 := e.GetF2().ReplaceTermByTerm(old, new) - ne := MakeEquSimple(e.GetIndex(), f1, f2, e.metas.Raw()) + ne := MakeEquSimple(f1, f2, e.metas.Raw()) if !res1 && !res2 && !e.metas.NeedsUpd() { e.metas.AvoidUpd() @@ -523,7 +552,6 @@ func (e Equ) ReplaceTermByTerm(old Term, new Term) (Form, bool) { func (e Equ) SubstTy(old TyGenVar, new Ty) Form { return MakeEquSimple( - e.GetIndex(), e.f1.SubstTy(old, new), e.f2.SubstTy(old, new), e.metas.Raw(), @@ -531,7 +559,7 @@ func (e Equ) SubstTy(old TyGenVar, new Ty) Form { } func (e Equ) RenameVariables() Form { - return MakeEqu(e.GetIndex(), e.GetF1().RenameVariables(), e.GetF2().RenameVariables()) + return MakeEqu(e.GetF1().RenameVariables(), e.GetF2().RenameVariables()) } func (e Equ) GetSubTerms() Lib.Set[Term] { @@ -544,7 +572,7 @@ func (e Equ) GetSymbols() Lib.Set[Id] { func (e Equ) SubstituteVarByMeta(old Var, new Meta) Form { fl, metas := substVarByMetaInFormList(old, new, Lib.MkListV(e.f1, e.f2), e.metas.Raw()) - return MakeEquSimple(e.index, fl.At(0), fl.At(1), metas) + return MakeEquSimple(fl.At(0), fl.At(1), metas) } func (e Equ) GetSubFormulasRecur() Lib.List[Form] { @@ -557,46 +585,53 @@ func (e Equ) GetChildFormulas() Lib.List[Form] { func (e Equ) ReplaceMetaByTerm(meta Meta, term Term) Form { return MakeEqu( - e.GetIndex(), e.f1.ReplaceMetaByTerm(meta, term), e.f2.ReplaceMetaByTerm(meta, term), ) } -func (e Equ) Less(oth any) bool { return less(e, oth) } +func (e Equ) Less(oth any) bool { + if form, is_form := oth.(Form); is_form { + switch f := form.(type) { + case All, Ex, Or, And: + return true + case Equ: + return bLess(Lib.MkListV(e.f1, e.f2), Lib.MkListV(f.f1, f.f2)) + default: + return false + } + } + return false +} // ----------------------------------------------------------------------------- // Implication type Imp struct { - index int f1, f2 Form metas Lib.Cache[Lib.Set[Meta], Imp] } -func MakeImpSimple(i int, firstForm, secondForm Form, metas Lib.Set[Meta]) Imp { +func MakeImpSimple(firstForm, secondForm Form, metas Lib.Set[Meta]) Imp { return Imp{ - i, firstForm, secondForm, Lib.MkCache(metas, Imp.forceGetMetas), } } -func MakeImp(i int, firstForm, secondForm Form) Imp { - return MakeImpSimple(i, firstForm, secondForm, Lib.EmptySet[Meta]()) +func MakeImp(firstForm, secondForm Form) Imp { + return MakeImpSimple(firstForm, secondForm, Lib.EmptySet[Meta]()) } func MakerImp(firstForm, secondForm Form) Imp { - return MakeImp(MakerIndexFormula(), firstForm, secondForm) + return MakeImp(firstForm, secondForm) } -func (i Imp) GetIndex() int { return i.index } -func (i Imp) GetF1() Form { return i.f1.Copy() } -func (i Imp) GetF2() Form { return i.f2.Copy() } +func (i Imp) GetF1() Form { return i.f1.Copy() } +func (i Imp) GetF2() Form { return i.f2.Copy() } func (i Imp) Copy() Form { return Imp{ - i.index, i.GetF1(), i.GetF2(), i.metas.Copy(Lib.Set[Meta].Copy), @@ -634,7 +669,7 @@ func (i Imp) ReplaceTermByTerm(old Term, new Term) (Form, bool) { f1, res1 := i.GetF1().ReplaceTermByTerm(old, new) f2, res2 := i.GetF2().ReplaceTermByTerm(old, new) - ni := MakeImpSimple(i.index, f1, f2, i.metas.Raw()) + ni := MakeImpSimple(f1, f2, i.metas.Raw()) if !res1 && !res2 && !i.metas.NeedsUpd() { ni.metas.AvoidUpd() @@ -645,7 +680,6 @@ func (i Imp) ReplaceTermByTerm(old Term, new Term) (Form, bool) { func (i Imp) SubstTy(old TyGenVar, new Ty) Form { return MakeImpSimple( - i.GetIndex(), i.f1.SubstTy(old, new), i.f2.SubstTy(old, new), i.metas.Raw(), @@ -653,7 +687,7 @@ func (i Imp) SubstTy(old TyGenVar, new Ty) Form { } func (i Imp) RenameVariables() Form { - return MakeImp(i.GetIndex(), i.GetF1().RenameVariables(), i.GetF2().RenameVariables()) + return MakeImp(i.GetF1().RenameVariables(), i.GetF2().RenameVariables()) } func (i Imp) GetSubTerms() Lib.Set[Term] { @@ -666,7 +700,7 @@ func (i Imp) GetSymbols() Lib.Set[Id] { func (i Imp) SubstituteVarByMeta(old Var, new Meta) Form { fl, metas := substVarByMetaInFormList(old, new, Lib.MkListV(i.f1, i.f2), i.metas.Raw()) - return MakeImpSimple(i.index, fl.At(0), fl.At(1), metas) + return MakeImpSimple(fl.At(0), fl.At(1), metas) } func (i Imp) GetSubFormulasRecur() Lib.List[Form] { @@ -679,45 +713,51 @@ func (i Imp) GetChildFormulas() Lib.List[Form] { func (i Imp) ReplaceMetaByTerm(meta Meta, term Term) Form { return MakeImp( - i.GetIndex(), i.f1.ReplaceMetaByTerm(meta, term), i.f2.ReplaceMetaByTerm(meta, term), ) } -func (i Imp) Less(oth any) bool { return less(i, oth) } +func (i Imp) Less(oth any) bool { + if form, is_form := oth.(Form); is_form { + switch f := form.(type) { + case All, Ex, Or, And, Equ: + return true + case Imp: + return bLess(Lib.MkListV(i.f1, i.f2), Lib.MkListV(f.f1, f.f2)) + default: + return false + } + } + return false +} // ----------------------------------------------------------------------------- // Not type Not struct { - index int f Form metas Lib.Cache[Lib.Set[Meta], Not] } /** Constructors **/ -func MakeNotSimple(i int, form Form, metas Lib.Set[Meta]) Not { - return Not{i, form, Lib.MkCache(metas, Not.forceGetMetas)} +func MakeNotSimple(form Form, metas Lib.Set[Meta]) Not { + return Not{form, Lib.MkCache(metas, Not.forceGetMetas)} } -func MakeNot(i int, form Form) Not { - return MakeNotSimple(i, form, Lib.EmptySet[Meta]()) +func MakeNot(form Form) Not { + return MakeNotSimple(form, Lib.EmptySet[Meta]()) } func MakerNot(form Form) Not { - return MakeNot(MakerIndexFormula(), form) + return MakeNot(form) } /** Methods **/ /** - Form interface Methods **/ -func (n Not) GetIndex() int { - return n.index -} - func (n Not) forceGetMetas() Lib.Set[Meta] { return n.GetForm().GetMetas() } @@ -743,7 +783,7 @@ func (n Not) Equals(other any) bool { } func (n Not) Copy() Form { - nn := MakeNotSimple(n.index, n.GetForm(), n.metas.Raw().Copy()) + nn := MakeNotSimple(n.GetForm(), n.metas.Raw().Copy()) if !n.metas.NeedsUpd() { nn.metas.AvoidUpd() } @@ -760,7 +800,7 @@ func (n Not) ToString() string { func (n Not) ReplaceTermByTerm(old Term, new Term) (Form, bool) { f, res := n.f.ReplaceTermByTerm(old, new) - nn := MakeNotSimple(n.GetIndex(), f, n.metas.Raw()) + nn := MakeNotSimple(f, n.metas.Raw()) if !res && !n.metas.NeedsUpd() { nn.metas.AvoidUpd() } @@ -770,18 +810,17 @@ func (n Not) ReplaceTermByTerm(old Term, new Term) (Form, bool) { func (n Not) SubstTy(old TyGenVar, new Ty) Form { return MakeNotSimple( - n.GetIndex(), n.f.SubstTy(old, new), n.metas.Raw(), ) } func (n Not) RenameVariables() Form { - return MakeNot(n.GetIndex(), n.f.RenameVariables()) + return MakeNot(n.f.RenameVariables()) } func (n Not) ReplaceMetaByTerm(meta Meta, term Term) Form { - return MakeNot(n.GetIndex(), n.f.ReplaceMetaByTerm(meta, term)) + return MakeNot(n.f.ReplaceMetaByTerm(meta, term)) } /** - Other Methods **/ @@ -792,7 +831,7 @@ func (n Not) GetForm() Form { func (n Not) SubstituteVarByMeta(old Var, new Meta) Form { f := n.GetForm().SubstituteVarByMeta(old, new) - return MakeNotSimple(n.index, f, f.GetMetas().Copy()) + return MakeNotSimple(f, f.GetMetas().Copy()) } func (n Not) GetSubFormulasRecur() Lib.List[Form] { @@ -830,13 +869,24 @@ func getDeepFormWithoutNot(form Form, isEven bool) (Form, bool) { } } -func (n Not) Less(oth any) bool { return less(n, oth) } +func (n Not) Less(oth any) bool { + if form, is_form := oth.(Form); is_form { + switch f := form.(type) { + case All, Ex, Or, And, Equ, Imp: + return true + case Not: + return n.f.Less(f.f) + default: + return false + } + } + return false +} // ----------------------------------------------------------------------------- // Predicates type Pred struct { - index int id Id tys Lib.List[Ty] args Lib.List[Term] @@ -844,14 +894,12 @@ type Pred struct { } func MakePredSimple( - index int, id Id, tys Lib.List[Ty], terms Lib.List[Term], metas Lib.Set[Meta], ) Pred { return Pred{ - index, id, tys, terms, @@ -860,13 +908,11 @@ func MakePredSimple( } func MakePred( - index int, id Id, tys Lib.List[Ty], terms Lib.List[Term], ) Pred { return MakePredSimple( - index, id, tys, terms, @@ -879,12 +925,11 @@ func MakerPred( tys Lib.List[Ty], terms Lib.List[Term], ) Pred { - return MakePred(MakerIndexFormula(), id, tys, terms) + return MakePred(id, tys, terms) } /* Pred attributes getters */ -func (p Pred) GetIndex() int { return p.index } func (p Pred) GetID() Id { return p.id.Copy().(Id) } func (p Pred) GetTyArgs() Lib.List[Ty] { return p.tys } func (p Pred) GetArgs() Lib.List[Term] { return p.args } @@ -903,7 +948,6 @@ func (p Pred) ToString() string { func (p Pred) Copy() Form { np := MakePredSimple( - p.index, p.id, p.GetTyArgs(), p.GetArgs(), @@ -960,7 +1004,6 @@ func (p Pred) ReplaceTermByTerm(old Term, new Term) (Form, bool) { termList, res := replaceTermInTermList(p.GetArgs(), old, new) np := MakePredSimple( - p.GetIndex(), p.GetID(), p.GetTyArgs(), termList, @@ -984,7 +1027,6 @@ func (p Pred) SubstTy(old TyGenVar, new Ty) Form { func(t Term) Term { return t.SubstTy(old, new) }, ) return MakePredSimple( - p.GetIndex(), p.GetID(), typed_args, args, @@ -1019,7 +1061,6 @@ func (p Pred) SubstituteVarByMeta(old Var, new Meta) Form { case Pred: if res { return MakePredSimple( - nf.index, nf.id, nf.tys, nf.args, @@ -1044,38 +1085,53 @@ func (p Pred) GetChildFormulas() Lib.List[Form] { func (p Pred) ReplaceMetaByTerm(meta Meta, term Term) Form { return MakePred( - p.GetIndex(), p.id, p.tys, Lib.ListMap(p.args, func(t Term) Term { return t.ReplaceSubTermBy(meta, term) }), ) } -func (p Pred) Less(oth any) bool { return less(p, oth) } +func (p Pred) Less(oth any) bool { + if form, is_form := oth.(Form); is_form { + switch f := form.(type) { + case All, Ex, Or, And, Equ, Imp, Not: + return true + case Pred: + if p.args.Len() < f.args.Len() { + return true + } else if p.args.Len() > f.args.Len() { + return false + } else { + return Lib.ListLess(p.args, f.args) + } + default: + return false + } + } + return false +} // ----------------------------------------------------------------------------- // True and False type Top struct { - index int } -func MakeTop(i int) Top { - return Top{i} +func MakeTop() Top { + return Top{} } func MakerTop() Top { - return MakeTop(MakerIndexFormula()) + return MakeTop() } func (Top) ToString() string { return printer.StrConn(ConnTop) } -func (t Top) Copy() Form { return MakeTop(t.GetIndex()) } +func (t Top) Copy() Form { return MakeTop() } func (Top) Equals(f any) bool { _, isTop := f.(Top); return isTop } func (Top) GetMetas() Lib.Set[Meta] { return Lib.EmptySet[Meta]() } -func (t Top) ReplaceTermByTerm(Term, Term) (Form, bool) { return MakeTop(t.GetIndex()), false } +func (t Top) ReplaceTermByTerm(Term, Term) (Form, bool) { return MakeTop(), false } func (t Top) SubstTy(TyGenVar, Ty) Form { return t } -func (t Top) RenameVariables() Form { return MakeTop(t.GetIndex()) } -func (t Top) GetIndex() int { return t.index } +func (t Top) RenameVariables() Form { return MakeTop() } func (t Top) GetSubTerms() Lib.Set[Term] { return Lib.EmptySet[Term]() } func (t Top) GetSymbols() Lib.Set[Id] { return Lib.EmptySet[Id]() } func (t Top) SubstituteVarByMeta(Var, Meta) Form { return t } @@ -1083,29 +1139,37 @@ func (t Top) GetInternalMetas() Lib.Set[Meta] { return Lib.EmptySet[ func (t Top) GetSubFormulasRecur() Lib.List[Form] { return Lib.MkListV[Form](t) } func (t Top) GetChildFormulas() Lib.List[Form] { return Lib.NewList[Form]() } func (t Top) ReplaceMetaByTerm(meta Meta, term Term) Form { return t } -func (t Top) Less(oth any) bool { return less(t, oth) } +func (t Top) Less(oth any) bool { + if form, is_form := oth.(Form); is_form { + switch form.(type) { + case All, Ex, Or, And, Equ, Imp, Not, Pred: + return true + default: + return false + } + } + return false +} /* Bot (always false) definition */ type Bot struct { - index int } -func MakeBot(i int) Bot { - return Bot{i} +func MakeBot() Bot { + return Bot{} } func MakerBot() Bot { - return MakeBot(MakerIndexFormula()) + return MakeBot() } func (Bot) ToString() string { return printer.StrConn(ConnBot) } -func (b Bot) Copy() Form { return MakeBot(b.GetIndex()) } +func (b Bot) Copy() Form { return MakeBot() } func (Bot) Equals(f any) bool { _, isBot := f.(Bot); return isBot } func (Bot) GetMetas() Lib.Set[Meta] { return Lib.EmptySet[Meta]() } -func (b Bot) ReplaceTermByTerm(Term, Term) (Form, bool) { return MakeBot(b.GetIndex()), false } +func (b Bot) ReplaceTermByTerm(Term, Term) (Form, bool) { return MakeBot(), false } func (b Bot) SubstTy(TyGenVar, Ty) Form { return b } -func (b Bot) RenameVariables() Form { return MakeBot(b.GetIndex()) } -func (b Bot) GetIndex() int { return b.index } +func (b Bot) RenameVariables() Form { return MakeBot() } func (b Bot) GetSubTerms() Lib.Set[Term] { return Lib.EmptySet[Term]() } func (b Bot) GetSymbols() Lib.Set[Id] { return Lib.EmptySet[Id]() } func (b Bot) SubstituteVarByMeta(Var, Meta) Form { return b } @@ -1113,4 +1177,13 @@ func (b Bot) GetInternalMetas() Lib.Set[Meta] { return Lib.EmptySet[ func (b Bot) GetSubFormulasRecur() Lib.List[Form] { return Lib.MkListV[Form](b) } func (b Bot) GetChildFormulas() Lib.List[Form] { return Lib.NewList[Form]() } func (b Bot) ReplaceMetaByTerm(meta Meta, term Term) Form { return b } -func (b Bot) Less(oth any) bool { return less(b, oth) } +func (b Bot) Less(oth any) bool { + if form, is_form := oth.(Form); is_form { + switch form.(type) { + case All, Ex, Or, And, Equ, Imp, Not, Pred, Top: + return true + } + return false + } + return false +} diff --git a/src/AST/formula.go b/src/AST/formula.go index 3decaf3f..9ab5b3cf 100644 --- a/src/AST/formula.go +++ b/src/AST/formula.go @@ -44,7 +44,6 @@ import ( /*** Structure ***/ type Form interface { - GetIndex() int GetMetas() Lib.Set[Meta] GetSubTerms() Lib.Set[Term] GetSymbols() Lib.Set[Id] @@ -63,13 +62,6 @@ type Form interface { ReplaceMetaByTerm(meta Meta, term Term) Form } -func less(form Form, oth any) bool { - if f, is_form := oth.(Form); is_form { - return form.GetIndex() < f.GetIndex() - } - return false -} - /* Replace a term by a term inside a function. */ func replaceTermInTermList( terms Lib.List[Term], @@ -80,40 +72,28 @@ func replaceTermInTermList( newTermList := Lib.MkList[Term](terms.Len()) for i, val := range terms.GetSlice() { - switch nf := val.(type) { - case Var: - if oldTerm.GetIndex() == nf.GetIndex() { - newTermList.Upd(i, newTerm) - res = true - } else { + if oldTerm.Equals(val) { + newTermList.Upd(i, newTerm) + res = true + } else { + switch nf := val.(type) { + case Var, Meta: newTermList.Upd(i, val) - } - case Fun: - if oldTerm.GetIndex() == nf.GetIndex() { - newTermList.Upd(i, newTerm) - res = true - } else { + case Fun: termList, r := replaceTermInTermList( nf.GetArgs(), oldTerm, newTerm, ) newTermList.Upd(i, MakerFun( - nf.GetP(), + nf.GetID(), nf.GetTyArgs(), termList, )) res = res || r + default: + Glob.Anomaly("ReplaceTermInTermList", "Term is not a Var, a Fun, or a Meta") } - case Meta: - if oldTerm.Equals(newTerm) { - newTermList.Upd(i, newTerm) - res = true - } else { - newTermList.Upd(i, val) - } - default: - Glob.Anomaly("ReplaceTermInTermList", "Term is not a Var, a Fun, or a Meta") } } @@ -166,3 +146,15 @@ func renameFormList(forms Lib.List[Form]) Lib.List[Form] { return newForms } + +// Comparisons + +func qLess(vars1, vars2 Lib.List[TypedVar], f1, f2 Form) bool { + return vars1.Len() < vars2.Len() || + (vars1.Len() == vars2.Len() && + f1.Less(f2)) +} + +func bLess(fs1, fs2 Lib.List[Form]) bool { + return Lib.ListLess(fs1, fs2) +} diff --git a/src/AST/maker.go b/src/AST/maker.go index 427701e2..5893654a 100644 --- a/src/AST/maker.go +++ b/src/AST/maker.go @@ -37,6 +37,7 @@ package AST import ( + "fmt" "sync" "github.com/GoelandProver/Goeland/Glob" @@ -44,14 +45,9 @@ import ( ) /* Datas */ -var cpt_term int -var cpt_formula int - -var idTable map[string]int = make(map[string]int) -var idVar map[string]int = make(map[string]int) var occurenceMeta map[string]int = make(map[string]int) var lock_term sync.Mutex -var lock_formula sync.Mutex +var meta_id int var debug Glob.Debugger @@ -74,79 +70,44 @@ func Init() { /* Reset all the maps and counters */ func Reset() { - cpt_term = 0 - cpt_formula = 0 - idTable = map[string]int{} - idVar = map[string]int{} ResetMeta() } /* Reset the metavariable table (useful when the IDDFS stop and restart) */ func ResetMeta() { + meta_id = 0 occurenceMeta = map[string]int{} } /* ID maker */ +// Deprecated: use MakeId instead func MakerId(s string) Id { - lock_term.Lock() - i, ok := idTable[s] - lock_term.Unlock() - if ok { - return MakeId(i, s) - } else { - return MakerNewId(s) - } -} - -func MakerNewId(s string) Id { - lock_term.Lock() - idTable[s] = cpt_term - id := MakeId(cpt_term, s) - cpt_term += 1 - lock_term.Unlock() - return id + return MakeId(s) } /* Var maker */ +// Deprecated: use MakeVar instead func MakerVar(s string) Var { - lock_term.Lock() - i, ok := idVar[s] - lock_term.Unlock() - if ok { - return MakeVar(i, s) - } else { - return MakerNewVar(s) - } -} - -func MakerNewVar(s string) Var { - lock_term.Lock() - idVar[s] = cpt_term - vr := MakeVar(cpt_term, s) - cpt_term += 1 - lock_term.Unlock() - return vr + return MakeVar(s) } /* Meta maker */ func MakerMeta(s string, formula int, ty Ty) Meta { lock_term.Lock() + new_id := meta_id + meta_id++ i, ok := occurenceMeta[s] lock_term.Unlock() if ok { lock_term.Lock() occurenceMeta[s] = i + 1 - new_index := cpt_term - cpt_term += 1 lock_term.Unlock() - return MakeMeta(new_index, i, s, formula, ty) + return MakeMeta(new_id, i, fmt.Sprintf("%s%d", s, new_id), formula, ty) } else { lock_term.Lock() occurenceMeta[s] = 1 - new_index := cpt_term - cpt_term += 1 lock_term.Unlock() - return MakeMeta(new_index, 0, s, formula, ty) + return MakeMeta(new_id, 0, fmt.Sprintf("%s%d", s, new_id), formula, ty) } } @@ -159,12 +120,3 @@ func MakerConst(id Id) Fun { func MakerFun(id Id, ty_args Lib.List[Ty], terms Lib.List[Term]) Fun { return MakeFun(id, ty_args, terms, Lib.EmptySet[Meta]()) } - -/* Index make for formula */ -func MakerIndexFormula() int { - lock_formula.Lock() - res := cpt_formula - cpt_formula++ - lock_formula.Unlock() - return res -} diff --git a/src/AST/modular-printing.go b/src/AST/modular-printing.go index 0545bf10..a4d90243 100644 --- a/src/AST/modular-printing.go +++ b/src/AST/modular-printing.go @@ -66,7 +66,7 @@ var printer_debug Glob.Debugger type PrinterAction struct { genericAction func(string) string // Always executed actionOnId func(Id) string - actionOnBoundVar func(string, int) string + actionOnBoundVar func(string) string actionOnMeta func(string, int) string actionOnType func(string) string actionOnTypedVar func(Lib.Pair[string, Ty]) string @@ -76,9 +76,9 @@ type PrinterAction struct { func (p PrinterAction) Compose(oth PrinterAction) PrinterAction { return PrinterAction{ genericAction: func(s string) string { return oth.genericAction(p.genericAction(s)) }, - actionOnId: func(i Id) string { return oth.actionOnId(MakeId(i.index, p.actionOnId(i))) }, - actionOnBoundVar: func(name string, index int) string { - return oth.actionOnBoundVar(p.actionOnBoundVar(name, index), index) + actionOnId: func(i Id) string { return oth.actionOnId(MakeId(p.actionOnId(i))) }, + actionOnBoundVar: func(name string) string { + return oth.actionOnBoundVar(p.actionOnBoundVar(name)) }, actionOnMeta: func(name string, index int) string { return oth.actionOnMeta(p.actionOnMeta(name, index), index) @@ -103,8 +103,8 @@ func (p PrinterAction) StrId(i Id) string { return p.Str(p.actionOnId(i)) } -func (p PrinterAction) StrBound(name string, index int) string { - return p.Str(p.actionOnBoundVar(name, index)) +func (p PrinterAction) StrBound(name string) string { + return p.Str(p.actionOnBoundVar(name)) } func (p PrinterAction) StrMeta(name string, index int) string { @@ -130,7 +130,7 @@ func PrinterIdentity2[T any](s string, _ T) string { return s } func MkPrinterAction( genericAction func(string) string, actionOnId func(Id) string, - actionOnBoundVar func(string, int) string, + actionOnBoundVar func(string) string, actionOnMeta func(string, int) string, actionOnType func(string) string, actionOnTypedVar func(Lib.Pair[string, Ty]) string, @@ -224,12 +224,12 @@ func (c PrinterConnective) DefaultOnFunctionalArgs( if is_infix { if args.Len() != 2 { - Glob.Anomaly("Printer", fmt.Sprintf( - "invalid number of infix arguments: expected 2, got %d (in <<%s>> for %s)", - args.Len(), - arguments, - id.ToString(), - )) + // Glob.Anomaly("Printer", fmt.Sprintf( + // "invalid number of infix arguments: expected 2, got %d (in <<%s>> for %s)", + // args.Len(), + // arguments, + // id.ToString(), + // )) } return fmt.Sprintf("%s %s %s", args.At(0), id.ToString(), args.At(1)) } else { @@ -353,15 +353,6 @@ func initPrinters() { &prettyPrinterConnectives, } - PrintIDAction = PrinterAction{ - genericAction: PrinterIdentity, - actionOnId: func(i Id) string { return fmt.Sprintf("%s_%d", i.name, i.index) }, - actionOnBoundVar: PrinterIdentity2[int], - actionOnMeta: PrinterIdentity2[int], - actionOnType: PrinterIdentity, - actionOnTypedVar: PrinterIdentityPair[Ty], - } - QuoteID = PrinterAction{ genericAction: PrinterIdentity, actionOnId: func(i Id) string { @@ -371,7 +362,7 @@ func initPrinters() { } return i.name }, - actionOnBoundVar: PrinterIdentity2[int], + actionOnBoundVar: PrinterIdentity, actionOnMeta: PrinterIdentity2[int], actionOnType: PrinterIdentity, actionOnTypedVar: PrinterIdentityPair[Ty], diff --git a/src/AST/printers.go b/src/AST/printers.go index c48c4b3f..dbf22101 100644 --- a/src/AST/printers.go +++ b/src/AST/printers.go @@ -37,8 +37,9 @@ package AST import ( - "github.com/GoelandProver/Goeland/Lib" "strings" + + "github.com/GoelandProver/Goeland/Lib" ) func RemoveSuperfluousParenthesesAction(connectives PrinterConnective) PrinterAction { @@ -55,10 +56,12 @@ func RemoveSuperfluousParenthesesAction(connectives PrinterConnective) PrinterAc tentative_str := s[len(complexChildStart) : len(s)-len(complexChildEnd)] is_open := 0 for i, char := range tentative_str { - if len(complexChildStart) <= i && tentative_str[i-len(complexChildStart):i] == complexChildStart { + if len(complexChildStart) <= i && + tentative_str[i-len(complexChildStart):i] == complexChildStart { is_open += 1 } - if len(complexChildEnd) <= i && tentative_str[i-len(complexChildEnd):i] == complexChildEnd { + if len(complexChildEnd) <= i && + tentative_str[i-len(complexChildEnd):i] == complexChildEnd { is_open -= 1 } if char == ' ' && is_open == 0 { @@ -71,7 +74,7 @@ func RemoveSuperfluousParenthesesAction(connectives PrinterConnective) PrinterAc return s }, actionOnId: func(i Id) string { return i.name }, - actionOnBoundVar: func(s string, index int) string { return s }, + actionOnBoundVar: func(s string) string { return s }, actionOnMeta: func(s string, index int) string { return s }, actionOnType: func(s string) string { return s }, actionOnTypedVar: func(p Lib.Pair[string, Ty]) string { return p.Fst }, @@ -90,7 +93,7 @@ func SanitizerAction(connectives PrinterConnective, forbidden_chars []string) Pr return s }, actionOnId: func(i Id) string { return i.name }, - actionOnBoundVar: func(s string, index int) string { return s }, + actionOnBoundVar: func(s string) string { return s }, actionOnMeta: func(s string, index int) string { return s }, actionOnType: func(s string) string { return s }, actionOnTypedVar: func(p Lib.Pair[string, Ty]) string { return p.Fst }, diff --git a/src/AST/quantifiers.go b/src/AST/quantifiers.go index ca16519f..da324069 100644 --- a/src/AST/quantifiers.go +++ b/src/AST/quantifiers.go @@ -44,14 +44,12 @@ import ( type quantifier struct { metas Lib.Cache[Lib.Set[Meta], quantifier] - index int varList Lib.List[TypedVar] subForm Form symbol Connective } func makeQuantifier( - i int, vars Lib.List[TypedVar], subForm Form, metas Lib.Set[Meta], @@ -59,17 +57,12 @@ func makeQuantifier( ) quantifier { return quantifier{ Lib.MkCache(metas, quantifier.forceGetMetas), - i, vars, subForm, symbol, } } -func (q quantifier) GetIndex() int { - return q.index -} - func (q quantifier) GetVarList() Lib.List[TypedVar] { return Lib.ListCpy(q.varList) } @@ -122,7 +115,6 @@ func (q quantifier) GetSymbols() Lib.Set[Id] { func (q quantifier) copy() quantifier { nq := makeQuantifier( - q.GetIndex(), Lib.ListCpy(q.varList), q.GetForm(), q.metas.Raw().Copy(), @@ -139,7 +131,6 @@ func (q quantifier) copy() quantifier { func (q quantifier) replaceTermByTerm(old Term, new Term) (quantifier, bool) { f, res := q.GetForm().ReplaceTermByTerm(old, new) return makeQuantifier( - q.GetIndex(), q.GetVarList(), f, q.metas.Raw().Copy(), @@ -150,7 +141,6 @@ func (q quantifier) replaceTermByTerm(old Term, new Term) (quantifier, bool) { func (q quantifier) replaceTyVar(old TyGenVar, new Ty) quantifier { f := q.GetForm().SubstTy(old, new) return makeQuantifier( - q.GetIndex(), Lib.ListMap( q.GetVarList(), func(p TypedVar) TypedVar { return p.SubstTy(old, new) }, @@ -167,12 +157,11 @@ func (q quantifier) renameVariables() quantifier { newTyBv := Lib.NewList[Lib.Pair[TyBound, Ty]]() for _, v := range q.GetVarList().GetSlice() { - newVar := MakerNewVar(v.GetName()) - newVar = MakerVar(fmt.Sprintf("%s%d", newVar.GetName(), newVar.GetIndex())) - newVarList.Append(MkTypedVar(newVar.name, newVar.index, v.ty)) + newVar := MakerVar(v.GetName()) + newVarList.Append(MkTypedVar(newVar.name, v.ty)) f, replaced := newForm.ReplaceTermByTerm(v.ToBoundVar(), newVar) if !replaced { - newBv := MkTyBV(newVar.name, newVar.index) + newBv := MkTyBV(newVar.name) f = f.SubstTy(v.ToTyBoundVar(), newBv) newTyBv.Append(Lib.MkPair(v.ToTyBoundVar(), newBv)) } @@ -180,7 +169,6 @@ func (q quantifier) renameVariables() quantifier { } return makeQuantifier( - q.GetIndex(), Lib.ListMap( newVarList, func(p TypedVar) TypedVar { @@ -197,9 +185,12 @@ func (q quantifier) renameVariables() quantifier { } func (q quantifier) substituteVarByMeta(old Var, new Meta) quantifier { + if Lib.ListMem(old, Lib.ListMap(q.varList, func(x TypedVar) Var { return x.ToBoundVar() })) { + return q + } + newForm := q.GetForm().SubstituteVarByMeta(old, new) return makeQuantifier( - q.GetIndex(), q.GetVarList(), newForm, newForm.GetMetas().Copy(), @@ -210,7 +201,6 @@ func (q quantifier) substituteVarByMeta(old Var, new Meta) quantifier { func (q quantifier) replaceMetaByTerm(meta Meta, term Term) quantifier { newForm := q.GetForm().ReplaceMetaByTerm(meta, term) return makeQuantifier( - q.GetIndex(), q.GetVarList(), newForm, newForm.GetMetas().Copy(), diff --git a/src/AST/term.go b/src/AST/term.go index d059226d..6087336a 100644 --- a/src/AST/term.go +++ b/src/AST/term.go @@ -46,7 +46,6 @@ type Term interface { Lib.Comparable Lib.Stringable Lib.Copyable[Term] - GetIndex() int GetName() string IsMeta() bool IsFun() bool @@ -61,16 +60,16 @@ type Term interface { } /*** Makers ***/ -func MakeId(i int, s string) Id { - return Id{i, s} +func MakeId(s string) Id { + return Id{s} } -func MakeQuotedId(i int, s string) Id { - return Id{i, "" + s + "'"} +func MakeQuotedId(s string) Id { + return Id{"" + s + "'"} } -func MakeVar(i int, s string) Var { - return Var{i, s} +func MakeVar(s string) Var { + return Var{s} } func MakeMeta(index, occurence int, s string, f int, ty Ty) Meta { @@ -94,7 +93,7 @@ func GetSymbol(tm Term) Lib.Option[Id] { case Fun: return Lib.MkSome(t.GetID()) case Id: - return Lib.MkSome(tm) + return Lib.MkSome(t) } debug(Lib.MkLazy(func() string { diff --git a/src/AST/termsDef.go b/src/AST/terms-def.go similarity index 86% rename from src/AST/termsDef.go rename to src/AST/terms-def.go index 3c2ec7c9..71c2af4e 100644 --- a/src/AST/termsDef.go +++ b/src/AST/terms-def.go @@ -39,7 +39,6 @@ package AST import ( "strings" - "github.com/GoelandProver/Goeland/Glob" "github.com/GoelandProver/Goeland/Lib" ) @@ -47,15 +46,13 @@ import ( // Predicates / functions symbols type Id struct { - index int - name string + name string } -func (i Id) GetIndex() int { return i.index } func (i Id) GetName() string { return i.name } func (i Id) IsMeta() bool { return false } func (i Id) IsFun() bool { return false } -func (i Id) Copy() Term { return MakeId(i.GetIndex(), i.GetName()) } +func (i Id) Copy() Term { return MakeId(i.GetName()) } func (Id) ToMeta() Meta { return MakeEmptyMeta() } func (Id) GetMetas() Lib.Set[Meta] { return Lib.EmptySet[Meta]() } func (Id) GetMetaList() Lib.List[Meta] { return Lib.NewList[Meta]() } @@ -85,28 +82,18 @@ func (i Id) GetSymbols() Lib.Set[Id] { return Lib.Singleton(i) } -// id < other : -1; id = other : 0; id > other : 1 func (i Id) CompareWith(other Id) int { - if i.name == other.name { - switch { - case i.index < other.index: - return -1 - case i.index == other.index: - return 0 - default: - return 1 - } - } - return strings.Compare(i.name, other.name) } func (i Id) Less(u any) bool { - switch t := u.(type) { - case Term: - return i.GetIndex() < t.GetIndex() - default: - Glob.Anomaly("Strict term comparison", "Not comparing two terms") + if t, is_term := u.(Term); is_term { + switch trm := t.(type) { + case Id: + return i.name < trm.name + default: + return false + } } return false } @@ -136,7 +123,6 @@ func (f Fun) GetArgs() Lib.List[Term] { return f.args } func (f *Fun) SetArgs(tl Lib.List[Term]) { f.args = tl } -func (f Fun) GetIndex() int { return f.GetID().GetIndex() } func (f Fun) GetName() string { return f.GetID().GetName() } func (f Fun) IsMeta() bool { return false } func (f Fun) IsFun() bool { return true } @@ -259,11 +245,16 @@ func (f Fun) GetSymbols() Lib.Set[Id] { } func (f Fun) Less(u any) bool { - switch t := u.(type) { - case Term: - return f.GetIndex() < t.GetIndex() - default: - Glob.Anomaly("Strict term comparison", "Not comparing two terms") + if t, is_term := u.(Term); is_term { + switch trm := t.(type) { + case Id: + return true + case Fun: + return f.p.Less(trm.p) || + (f.p.Equals(trm.p) && Lib.ListLess(f.args, trm.args)) + default: + return false + } } return false } @@ -272,23 +263,21 @@ func (f Fun) Less(u any) bool { // Bound variables type Var struct { - index int - name string + name string } -func (v Var) ToString() string { return printer.StrBound(v.name, v.index) } -func (v Var) GetIndex() int { return v.index } +func (v Var) ToString() string { return printer.StrBound(v.name) } func (v Var) GetName() string { return v.name } func (v Var) IsMeta() bool { return false } func (v Var) IsFun() bool { return false } -func (v Var) Copy() Term { return MakeVar(v.GetIndex(), v.GetName()) } +func (v Var) Copy() Term { return MakeVar(v.GetName()) } func (Var) ToMeta() Meta { return MakeEmptyMeta() } func (Var) GetMetas() Lib.Set[Meta] { return Lib.EmptySet[Meta]() } func (Var) GetMetaList() Lib.List[Meta] { return Lib.NewList[Meta]() } func (v Var) Equals(t any) bool { if typed, ok := t.(Var); ok { - return v.GetIndex() == typed.GetIndex() + return v.name == typed.name } return false } @@ -311,11 +300,15 @@ func (v Var) ReplaceSubTermBy(original_term, new_term Term) Term { func (v Var) SubstTy(TyGenVar, Ty) Term { return v } func (v Var) Less(u any) bool { - switch t := u.(type) { - case Term: - return v.GetIndex() < t.GetIndex() - default: - Glob.Anomaly("Strict term comparison", "Not comparing two terms") + if t, is_term := u.(Term); is_term { + switch trm := t.(type) { + case Id, Fun: + return true + case Var: + return v.name < trm.name + default: + return false + } } return false } @@ -335,8 +328,8 @@ func (m Meta) ToString() string { return printer.StrMeta(m.name, m.index) } func (m Meta) GetFormula() int { return m.formula } func (m Meta) GetName() string { return m.name } -func (m Meta) GetIndex() int { return m.index } func (m Meta) GetOccurence() int { return m.occurence } +func (m Meta) GetIndex() int { return m.index } func (m Meta) IsMeta() bool { return true } func (m Meta) IsFun() bool { return false } func (m Meta) ToMeta() Meta { return m } @@ -346,13 +339,16 @@ func (m Meta) GetTy() Ty { return m.ty } func (m Meta) Equals(t any) bool { if typed, ok := t.(Meta); ok { - return typed.GetIndex() == m.GetIndex() + return m.index == typed.index && + m.occurence == typed.occurence && + m.name == typed.name && + m.formula == typed.formula } return false } func (m Meta) Copy() Term { - return MakeMeta(m.GetIndex(), m.GetOccurence(), m.GetName(), m.GetFormula(), m.GetTy()) + return MakeMeta(m.index, m.GetOccurence(), m.GetName(), m.GetFormula(), m.GetTy()) } func (m Meta) ReplaceSubTermBy(original_term, new_term Term) Term { @@ -373,11 +369,17 @@ func (m Meta) GetSymbols() Lib.Set[Id] { } func (m Meta) Less(u any) bool { - switch t := u.(type) { - case Term: - return m.GetIndex() < t.GetIndex() - default: - Glob.Anomaly("Strict term comparison", "Not comparing two terms") + if t, is_term := u.(Term); is_term { + switch trm := t.(type) { + case Id, Fun, Var: + return true + case Meta: + return m.occurence < trm.occurence || + (m.occurence == trm.occurence && m.name < trm.name) || + (m.occurence == trm.occurence && m.name == trm.name && m.formula < trm.formula) + default: + return false + } } return false } diff --git a/src/AST/tptp-native-types.go b/src/AST/tptp-native-types.go index 320cf3b7..3b4b821d 100644 --- a/src/AST/tptp-native-types.go +++ b/src/AST/tptp-native-types.go @@ -60,8 +60,6 @@ func initTPTPNativeTypes() { tIndividual = MkTyConst("$i") tProp = MkTyConst("$o") - - count_meta = 0 } func TType() Ty { diff --git a/src/AST/ty-syntax.go b/src/AST/ty-syntax.go index f05d3fd8..e21dd3e3 100644 --- a/src/AST/ty-syntax.go +++ b/src/AST/ty-syntax.go @@ -39,15 +39,11 @@ package AST import ( "fmt" - "sync" "github.com/GoelandProver/Goeland/Glob" "github.com/GoelandProver/Goeland/Lib" ) -var meta_mut sync.Mutex -var count_meta int - type TyGenVar interface { isGenVar() } @@ -67,7 +63,7 @@ type tyVar struct { func (tyVar) isTy() {} func (v tyVar) ToString() string { - return printer.StrBound(v.repr, 0) + return printer.StrBound(v.repr) } func (v tyVar) Equals(oth any) bool { if ov, ok := oth.(tyVar); ok { @@ -80,14 +76,13 @@ func (v tyVar) Copy() Ty { return tyVar{v.repr} } func (v tyVar) SubstTy(TyGenVar, Ty) Ty { return v } type TyBound struct { - name string - index int + name string } func (TyBound) isTy() {} func (TyBound) isGenVar() {} func (b TyBound) ToString() string { - return printer.StrBound(b.name, b.index) + return printer.StrBound(b.name) } func (b TyBound) Equals(oth any) bool { if bv, ok := oth.(TyBound); ok { @@ -95,7 +90,7 @@ func (b TyBound) Equals(oth any) bool { } return false } -func (b TyBound) Copy() Ty { return TyBound{b.name, b.index} } +func (b TyBound) Copy() Ty { return TyBound{b.name} } func (b TyBound) GetName() string { return b.name } func (b TyBound) SubstTy(old TyGenVar, new Ty) Ty { @@ -106,8 +101,8 @@ func (b TyBound) SubstTy(old TyGenVar, new Ty) Ty { } type TyMeta struct { - name string index int + name string formula int // for compatibility with term metas } @@ -118,11 +113,11 @@ func (m TyMeta) ToString() string { } func (m TyMeta) Equals(oth any) bool { if om, ok := oth.(TyMeta); ok { - return m.name == om.name && m.index == om.index + return m.name == om.name && m.formula == om.formula } return false } -func (m TyMeta) Copy() Ty { return TyMeta{m.name, m.index, m.formula} } +func (m TyMeta) Copy() Ty { return TyMeta{m.index, m.name, m.formula} } func (m TyMeta) SubstTy(v TyGenVar, new Ty) Ty { if m.Equals(v) { @@ -131,12 +126,12 @@ func (m TyMeta) SubstTy(v TyGenVar, new Ty) Ty { return m } -func (m TyMeta) ToTermMeta() Meta { return MakeMeta(m.index, -1, m.name, m.formula, tType) } +func (m TyMeta) ToTermMeta() Meta { return MakeMeta(m.index, 0, m.name, m.formula, tType) } func TyMetaFromMeta(m Meta) TyMeta { return TyMeta{ - m.name, m.index, + m.name, m.formula, } } @@ -292,15 +287,16 @@ func MkTyVar(repr string) Ty { return tyVar{repr} } -func MkTyBV(name string, index int) Ty { - return TyBound{name, index} +func MkTyBV(name string) Ty { + return TyBound{name} } func MkTyMeta(name string, formula int) Ty { - meta_mut.Lock() - meta := TyMeta{name, count_meta, formula} - count_meta += 1 - meta_mut.Unlock() + lock_term.Lock() + index := meta_id + meta_id++ + lock_term.Unlock() + meta := TyMeta{index, name, formula} return meta } @@ -324,21 +320,9 @@ func MkTyPi(vars Lib.List[string], ty Ty) Ty { return TyPi{vars, ty} } -// FIXME: the Maker logic should be factorized somewhere +// Deprecated: use MkTyBV instead func MakerTyBV(name string) Ty { - lock_term.Lock() - i, ok := idVar[name] - lock_term.Unlock() - if ok { - return MkTyBV(name, i) - } else { - lock_term.Lock() - idVar[name] = cpt_term - vr := MkTyBV(name, cpt_term) - cpt_term += 1 - lock_term.Unlock() - return vr - } + return MkTyBV(name) } func InstantiateTy(ty Ty, instance Lib.List[Ty]) Ty { diff --git a/src/AST/typed-vars.go b/src/AST/typed-vars.go index 05254f77..cf0435c4 100644 --- a/src/AST/typed-vars.go +++ b/src/AST/typed-vars.go @@ -41,19 +41,17 @@ import ( ) type TypedVar struct { - name string - index int - ty Ty + name string + ty Ty } func (v TypedVar) Copy() TypedVar { - return TypedVar{v.name, v.index, v.ty.Copy()} + return TypedVar{v.name, v.ty.Copy()} } func (v TypedVar) Equals(oth any) bool { if ov, ok := oth.(TypedVar); ok { - return v.name == ov.name && v.index == ov.index && - v.ty.Equals(ov.ty) + return v.name == ov.name && v.ty.Equals(ov.ty) } return false } @@ -66,42 +64,27 @@ func (v TypedVar) GetName() string { return v.name } -func (v TypedVar) GetIndex() int { - return v.index -} - func (v TypedVar) GetTy() Ty { return v.ty } func (v TypedVar) ToBoundVar() Var { - return MakeVar(v.index, v.name) + return MakeVar(v.name) } func (v TypedVar) ToTyBoundVar() TyBound { - return MkTyBV(v.name, v.index).(TyBound) + return MkTyBV(v.name).(TyBound) } func (v TypedVar) SubstTy(old TyGenVar, new Ty) TypedVar { - return TypedVar{v.name, v.index, v.ty.SubstTy(old, new)} + return TypedVar{v.name, v.ty.SubstTy(old, new)} } -func MkTypedVar(name string, index int, ty Ty) TypedVar { - return TypedVar{name, index, ty} +func MkTypedVar(name string, ty Ty) TypedVar { + return TypedVar{name, ty} } +// Deprecated: use MkTypedVar instead func MakerTypedVar(name string, ty Ty) TypedVar { - lock_term.Lock() - i, ok := idVar[name] - lock_term.Unlock() - if ok { - return MkTypedVar(name, i, ty) - } else { - lock_term.Lock() - idVar[name] = cpt_term - vr := MkTypedVar(name, cpt_term, ty) - cpt_term += 1 - lock_term.Unlock() - return vr - } + return MkTypedVar(name, ty) } diff --git a/src/Core/Sko/inner-skolemization.go b/src/Core/Sko/inner-skolemization.go index 3db9f882..3f8d43d0 100644 --- a/src/Core/Sko/inner-skolemization.go +++ b/src/Core/Sko/inner-skolemization.go @@ -63,7 +63,7 @@ func (sko InnerSkolemization) Skolemize( _ Lib.Set[AST.Meta], ) (Skolemization, AST.Form) { sko.mu.Lock() - symbol := genFreshSymbol(&sko.existingSymbols, x) + symbol := genFreshSymbol(&sko.existingSymbols) sko.mu.Unlock() internalMetas := form.GetMetas().Elements() diff --git a/src/Core/Sko/interface.go b/src/Core/Sko/interface.go index 8ef14586..f2e92c7c 100644 --- a/src/Core/Sko/interface.go +++ b/src/Core/Sko/interface.go @@ -60,9 +60,9 @@ type Skolemization interface { /* If every Skolem symbol is created using this function, then it will generate * a fresh symbol for sure. Otherwise, nothing is guaranteed. */ -func genFreshSymbol(existingSymbols *Lib.Set[AST.Id], x AST.TypedVar) AST.Id { - symbol := AST.MakerNewId( - fmt.Sprintf("skolem@%v@%d", x.GetName(), existingSymbols.Cardinal()), +func genFreshSymbol(existingSymbols *Lib.Set[AST.Id]) AST.Id { + symbol := AST.MakerId( + fmt.Sprintf("skolem@%d", existingSymbols.Cardinal()), ) *existingSymbols = existingSymbols.Add(symbol) diff --git a/src/Core/Sko/outer-skolemization.go b/src/Core/Sko/outer-skolemization.go index 1cfa7fa8..c4bc2abf 100644 --- a/src/Core/Sko/outer-skolemization.go +++ b/src/Core/Sko/outer-skolemization.go @@ -63,7 +63,7 @@ func (sko OuterSkolemization) Skolemize( fvs Lib.Set[AST.Meta], ) (Skolemization, AST.Form) { sko.mu.Lock() - symbol := genFreshSymbol(&sko.existingSymbols, x) + symbol := genFreshSymbol(&sko.existingSymbols) sko.mu.Unlock() metas := fvs.Elements() diff --git a/src/Core/Sko/preinner-skolemization.go b/src/Core/Sko/preinner-skolemization.go index b81cd965..9944a7d6 100644 --- a/src/Core/Sko/preinner-skolemization.go +++ b/src/Core/Sko/preinner-skolemization.go @@ -65,17 +65,17 @@ func (sko PreInnerSkolemization) Skolemize( x AST.TypedVar, _ Lib.Set[AST.Meta], ) (Skolemization, AST.Form) { - realDelta := alphaConvert(delta, 0, make(map[int]AST.Var)) + realDelta := alphaConvert(delta, 0, make(map[string]AST.Var)) var symbol AST.Id sko.mu.Lock() if val, ok := sko.linkedSymbols.Find( func(p Glob.Pair[AST.Form, AST.Id]) bool { return p.Fst.Equals(realDelta) }, - Glob.MakePair(Glob.To[AST.Form](AST.MakerBot()), AST.MakeId(-1, "")), + Glob.MakePair(Glob.To[AST.Form](AST.MakerBot()), AST.MakeId("")), ); ok { symbol = val.Snd } else { - symbol = genFreshSymbol(&sko.existingSymbols, x) + symbol = genFreshSymbol(&sko.existingSymbols) sko.linkedSymbols.Append(Glob.MakePair(realDelta, symbol)) } sko.mu.Unlock() @@ -103,7 +103,7 @@ func fresh(k int) string { func alphaConvert( form AST.Form, k int, - substitution map[int]AST.Var, + substitution map[string]AST.Var, ) AST.Form { switch f := form.(type) { case AST.Top, AST.Bot: @@ -114,31 +114,26 @@ func alphaConvert( return alphaConvertTerm(t, substitution) }) return AST.MakePred( - f.GetIndex(), f.GetID(), f.GetTyArgs(), mappedTerms, ) case AST.Not: return AST.MakeNot( - f.GetIndex(), alphaConvert(f.GetForm(), k, substitution), ) case AST.Imp: return AST.MakeImp( - f.GetIndex(), alphaConvert(f.GetF1(), k, substitution), alphaConvert(f.GetF2(), k, substitution), ) case AST.Equ: return AST.MakeEqu( - f.GetIndex(), alphaConvert(f.GetF1(), k, substitution), alphaConvert(f.GetF2(), k, substitution), ) case AST.And: return AST.MakeAnd( - f.GetIndex(), Lib.MkListV( Glob.MapTo( f.GetChildFormulas().GetSlice(), @@ -148,7 +143,6 @@ func alphaConvert( ) case AST.Or: return AST.MakeOr( - f.GetIndex(), Lib.MkListV(Glob.MapTo( f.GetChildFormulas().GetSlice(), func(_ int, f AST.Form) AST.Form { @@ -157,36 +151,39 @@ func alphaConvert( ) case AST.All: k, substitution, vl := makeConvertedVarList(k, substitution, f.GetVarList()) - return AST.MakeAll(f.GetIndex(), vl, alphaConvert(f.GetForm(), k, substitution)) + return AST.MakeAll(vl, alphaConvert(f.GetForm(), k, substitution)) case AST.Ex: k, substitution, vl := makeConvertedVarList(k, substitution, f.GetVarList()) - return AST.MakeEx(f.GetIndex(), vl, alphaConvert(f.GetForm(), k, substitution)) + return AST.MakeEx(vl, alphaConvert(f.GetForm(), k, substitution)) } Glob.Anomaly( "preinner", - fmt.Sprintf("On alpha-conversion of %s: form does not correspond to any known ones", form.ToString()), + fmt.Sprintf( + "On alpha-conversion of %s: form does not correspond to any known ones", + form.ToString(), + ), ) return form } func makeConvertedVarList( k int, - substitution map[int]AST.Var, + substitution map[string]AST.Var, vl Lib.List[AST.TypedVar], -) (int, map[int]AST.Var, Lib.List[AST.TypedVar]) { +) (int, map[string]AST.Var, Lib.List[AST.TypedVar]) { newVarList := Lib.MkList[AST.TypedVar](vl.Len()) for i, v := range vl.GetSlice() { - nv := AST.MkTypedVar(fresh(k+i), k+i, v.GetTy()) + nv := AST.MkTypedVar(fresh(k+i), v.GetTy()) newVarList.Upd(i, nv) - substitution[v.GetIndex()] = nv.ToBoundVar() + substitution[v.GetName()] = nv.ToBoundVar() } return k + vl.Len(), substitution, newVarList } -func alphaConvertTerm(t AST.Term, substitution map[int]AST.Var) AST.Term { +func alphaConvertTerm(t AST.Term, substitution map[string]AST.Var) AST.Term { switch nt := t.(type) { case AST.Var: - if val, ok := substitution[nt.GetIndex()]; ok { + if val, ok := substitution[nt.GetName()]; ok { return val } else { return nt diff --git a/src/Core/skolemisation.go b/src/Core/skolemisation.go index e8947805..66a7341c 100644 --- a/src/Core/skolemisation.go +++ b/src/Core/skolemisation.go @@ -33,6 +33,8 @@ package Core import ( "fmt" + "sync" + "github.com/GoelandProver/Goeland/AST" "github.com/GoelandProver/Goeland/Core/Sko" "github.com/GoelandProver/Goeland/Glob" @@ -72,6 +74,8 @@ import ( **/ var selectedSkolemization Sko.Skolemization = Sko.MkOuterSkolemization() +var ty_index = 0 +var ty_mutex sync.Mutex const ( isNegAll = iota @@ -128,8 +132,10 @@ func realSkolemize( var res AST.Form if AST.IsTType(x.GetTy()) { - id := AST.MakerId("skoTy") - id = AST.MakerId(fmt.Sprintf("skoTy@%d", id.GetIndex())) + ty_mutex.Lock() + id := AST.MakerId(fmt.Sprintf("skoTy@%d", ty_index)) + ty_index++ + ty_mutex.Unlock() res = deltaForm.SubstTy(x.ToTyBoundVar(), AST.MkTyConst(id.ToString())) } else { selectedSkolemization, res = selectedSkolemization.Skolemize( diff --git a/src/Lib/list.go b/src/Lib/list.go index 877a35be..ec3f9076 100644 --- a/src/Lib/list.go +++ b/src/Lib/list.go @@ -279,6 +279,26 @@ func (l StrictlyOrderedList[T]) Less(i, j int) bool { return l.values.At(i).Less(l.values.At(j)) } +func ListLess[T StrictlyOrdered](l1, l2 List[T]) bool { + if l1.Len() < l2.Len() { + return true + } + + if l1.Len() > l2.Len() { + return false + } + + // invariant: l.Len() = another.Len() + for i := 0; i < l1.Len(); i++ { + if l1.At(i).Less(l2.At(i)) { + return true + } else if l2.At(i).Less(l1.At(i)) { + return false + } + } + return false +} + func (l StrictlyOrderedList[T]) Swap(i, j int) { l.values.values[i], l.values.values[j] = l.values.values[j], l.values.values[i] diff --git a/src/Mods/desko/proof.go b/src/Mods/desko/proof.go index 594273f4..14100f80 100644 --- a/src/Mods/desko/proof.go +++ b/src/Mods/desko/proof.go @@ -50,6 +50,7 @@ var debug Glob.Debugger var debug_interrupt Glob.InterruptingDebugger var raise_anomaly = func(msg string) { Glob.Anomaly(label, msg) } var desko_delta StrategyRule +var indexes Lib.List[AST.Form] type proof_node struct { proof Search.IProof @@ -77,6 +78,7 @@ var MakeDeskolemizedProof = func(proof Search.IProof) *GS3Sequent { Glob.Fatal(label, "Unsupported Skolemization") } + indexes = Lib.NewList[AST.Form]() root := new(GS3Sequent) deskolemize_proof(root, proof, precompute_branch_checker(proof), empty_proof_info()) return root @@ -120,6 +122,19 @@ func deskolemize_proof( } } +func index(f AST.Form) int { + switch id := Lib.ListIndexOf(f, indexes).(type) { + case Lib.Some[int]: + return id.Val + case Lib.None[int]: + indexes = indexes.Push(f) + return indexes.Len() - 1 + } + + Glob.Fatal(label, fmt.Sprintf("Formula %s not found in the index list", f.ToString())) + return -1 +} + func gen_apply_rule(node *GS3Sequent, proof Search.IProof, info proof_info) []proof_info { node.children = Lib.NewList[*GS3Sequent]() node.appliedOn = proof.AppliedOn() @@ -132,7 +147,7 @@ func gen_apply_rule(node *GS3Sequent, proof Search.IProof, info proof_info) []pr child_info := copy_proof_info(info) child_info.ctx.Append(node.formsGenerated.At(i).GetSlice()...) for _, f := range node.formsGenerated.At(i).GetSlice() { - child_info.form_introduction[f.GetIndex()] = proof_node{proof: proof, child: i} + child_info.form_introduction[index(f)] = proof_node{proof: proof, child: i} } child := new(GS3Sequent) node.children.Append(child) @@ -237,16 +252,16 @@ func desko_inner( // containing a term before weakening it. term_delayed_weakening := []Lib.Option[Lib.Either[AST.Ty, AST.Term]]{} for _, form := range forms_to_weaken.GetSlice() { - comes_from := info.form_introduction[form.GetIndex()].proof.AppliedOn() + comes_from := info.form_introduction[index(form)].proof.AppliedOn() if is_on_branch(sko_symbol, comes_from) { - to_replay.Append(info.form_introduction[form.GetIndex()]) + to_replay.Append(info.form_introduction[index(form)]) } node = gen_weaken(node, Lib.MkNone[Lib.Either[AST.Ty, AST.Term]](), form) - if Search.KindOfRule(info.form_introduction[form.GetIndex()].proof.RuleApplied()) == + if Search.KindOfRule(info.form_introduction[index(form)].proof.RuleApplied()) == Search.KindDelta { term_delayed_weakening = append( term_delayed_weakening, - info.form_introduction[form.GetIndex()].proof.TermGenerated(), + info.form_introduction[index(form)].proof.TermGenerated(), ) } } diff --git a/src/Mods/desko/sequent.go b/src/Mods/desko/sequent.go index c9ef1b00..5d704a8a 100644 --- a/src/Mods/desko/sequent.go +++ b/src/Mods/desko/sequent.go @@ -67,13 +67,20 @@ func (s *GS3Sequent) TermGenerated() Lib.Option[Lib.Either[AST.Ty, AST.Term]] { func (s *GS3Sequent) ToString() string { res := Lib.ListToString(s.children, "\n", "") + trm_str := "" + + switch tm := s.termGenerated.(type) { + case Lib.Some[Lib.Either[AST.Ty, AST.Term]]: + trm_str = "(" + Lib.EitherToString[AST.Ty, AST.Term](tm.Val, "ty", "tm") + ")" + } return fmt.Sprintf( - "%s\ngs3(%p, %s, %s ---> %s)", + "%s\ngs3(%p, %s, %s%s ---> %s)", res, s, s.appliedOn.ToString(), s.rule.ToString(), + trm_str, s.children.ToString(func(c *GS3Sequent) string { return fmt.Sprintf("%p", c) }, ",", "[]"), ) } diff --git a/src/Mods/dmt/dmt.go b/src/Mods/dmt/dmt.go index b97fbebc..5b042aa9 100644 --- a/src/Mods/dmt/dmt.go +++ b/src/Mods/dmt/dmt.go @@ -60,6 +60,8 @@ var flagPresko = flag.Bool("presko", false, "Activate preskolemization on DMT") var registeredAxioms Lib.List[AST.Form] +var rewriteIndexes Lib.List[AST.Form] + /** * Base function needed to initialize any plugin of Goéland. * It registers the hooks to the plugin manager, and parses the given options. @@ -84,8 +86,8 @@ func initPluginGlobalVariables() { negativeRewrite = make(map[string]Lib.List[AST.Form]) positiveTree = Unif.NewNode() negativeTree = Unif.NewNode() - registeredAxioms = Lib.NewList[AST.Form]() + rewriteIndexes = Lib.NewList[AST.Form]() } /** diff --git a/src/Mods/dmt/rewrite.go b/src/Mods/dmt/rewrite.go index c72375f3..4663eefe 100644 --- a/src/Mods/dmt/rewrite.go +++ b/src/Mods/dmt/rewrite.go @@ -55,7 +55,12 @@ func Rewrite(atomic AST.Form) ([]Core.IntSubstAndForm, error) { return rewriteGeneric(tree, atomic, form, polarity) } -func rewriteGeneric(tree Unif.DataStructure, atomic AST.Form, form AST.Form, polarity bool) ([]Core.IntSubstAndForm, error) { +func rewriteGeneric( + tree Unif.DataStructure, + atomic AST.Form, + form AST.Form, + polarity bool, +) ([]Core.IntSubstAndForm, error) { rewritten := []Core.IntSubstAndForm{} var err error = nil @@ -71,7 +76,12 @@ func rewriteGeneric(tree Unif.DataStructure, atomic AST.Form, form AST.Form, pol return rewritten, err } -func getRewrittenFormulas(rewritten []Core.IntSubstAndForm, unif []Unif.MatchingSubstitutions, atomic AST.Form, polarity bool) ([]Core.IntSubstAndForm, error) { +func getRewrittenFormulas( + rewritten []Core.IntSubstAndForm, + unif []Unif.MatchingSubstitutions, + atomic AST.Form, + polarity bool, +) ([]Core.IntSubstAndForm, error) { unifs := sortUnifications(unif, polarity, atomic) if len(unifs) == 0 { rewritten = rewriteFailure(atomic) @@ -88,14 +98,27 @@ func getRewrittenFormulas(rewritten []Core.IntSubstAndForm, unif []Unif.Matching return rewritten, nil } -func addRewrittenFormulas(rewritten []Core.IntSubstAndForm, unif Unif.MatchingSubstitutions, atomic AST.Form, equivalence Lib.List[AST.Form]) []Core.IntSubstAndForm { +func addRewrittenFormulas( + rewritten []Core.IntSubstAndForm, + unif Unif.MatchingSubstitutions, + atomic AST.Form, + equivalence Lib.List[AST.Form], +) []Core.IntSubstAndForm { // Keep only useful substitutions useful_subst := Unif.ToSubstitutions( Core.RemoveElementWithoutMM(Unif.FromSubstitutions(unif.GetSubst()), atomic.GetMetas()), ) meta_search := atomic.GetMetas() if !checkMetaAreFromSearch(meta_search, useful_subst) { - Glob.PrintError("DMT", fmt.Sprintf("There is at least one meta in final subst which is not from search : %v - %v - %v", useful_subst.ToString(), atomic.ToString(), unif.GetForm().ToString())) + Glob.PrintError( + "DMT", + fmt.Sprintf( + "There is at least one meta in final subst which is not from search : %v - %v - %v", + useful_subst.ToString(), + atomic.ToString(), + unif.GetForm().ToString(), + ), + ) } filteredUnif := Unif.MakeMatchingSubstitutions( unif.GetForm(), @@ -129,21 +152,44 @@ func rewriteFailure(atomic AST.Form) []Core.IntSubstAndForm { return []Core.IntSubstAndForm{ Core.MakeIntSubstAndForm( -1, - Core.MakeSubstAndForm(Lib.MkListV(Unif.MkMixedFromSubst(Unif.Failure()[0])), Lib.MkListV(atomic)), + Core.MakeSubstAndForm( + Lib.MkListV(Unif.MkMixedFromSubst(Unif.Failure()[0])), + Lib.MkListV(atomic), + ), ), } } -func addUnifToAtomics(atomics []Core.IntSubstAndForm, candidate AST.Form, unif Unif.MatchingSubstitutions) []Core.IntSubstAndForm { +func RewID(f AST.Form) int { + switch id := Lib.ListIndexOf(f, rewriteIndexes).(type) { + case Lib.Some[int]: + return id.Val + case Lib.None[int]: + rewriteIndexes = rewriteIndexes.Push(f) + return rewriteIndexes.Len() - 1 + } + + Glob.Fatal("dmt", fmt.Sprintf("Formula %s not found in the index list", f.ToString())) + return -1 +} + +func addUnifToAtomics( + atomics []Core.IntSubstAndForm, + candidate AST.Form, + unif Unif.MatchingSubstitutions, +) []Core.IntSubstAndForm { mixed := Lib.NewList[Unif.MixedSubstitution]() for _, subst := range unif.GetSubst() { mixed.Append(Unif.MkMixedFromSubst(subst)) } substAndForm := Core.MakeSubstAndForm(mixed, Lib.MkListV(candidate)) if isBotOrTop(candidate) { - atomics = Core.InsertFirstIntSubstAndFormList(atomics, Core.MakeIntSubstAndForm(unif.GetForm().GetIndex(), substAndForm)) + atomics = Core.InsertFirstIntSubstAndFormList( + atomics, + Core.MakeIntSubstAndForm(RewID(unif.GetForm()), substAndForm), + ) } else { - atomics = append(atomics, Core.MakeIntSubstAndForm(unif.GetForm().GetIndex(), substAndForm)) + atomics = append(atomics, Core.MakeIntSubstAndForm(RewID(unif.GetForm()), substAndForm)) } return atomics } @@ -152,7 +198,11 @@ func isBotOrTop(form AST.Form) bool { return Glob.Is[AST.Bot](form) || Glob.Is[AST.Top](form) } -func sortUnifications(unifs []Unif.MatchingSubstitutions, polarity bool, atomic AST.Form) []Unif.MatchingSubstitutions { +func sortUnifications( + unifs []Unif.MatchingSubstitutions, + polarity bool, + atomic AST.Form, +) []Unif.MatchingSubstitutions { rewriteMap := selectFromPolarity(polarity, positiveRewrite, negativeRewrite) sortedUnifs := []Unif.MatchingSubstitutions{} @@ -168,7 +218,11 @@ func sortUnifications(unifs []Unif.MatchingSubstitutions, polarity bool, atomic } // Priority of substitutions: Top/Bottom > others -func insert(sortedUnifs []Unif.MatchingSubstitutions, list Lib.List[AST.Form], unif Unif.MatchingSubstitutions) []Unif.MatchingSubstitutions { +func insert( + sortedUnifs []Unif.MatchingSubstitutions, + list Lib.List[AST.Form], + unif Unif.MatchingSubstitutions, +) []Unif.MatchingSubstitutions { if Lib.ListMem(AST.MakerTop().Copy(), list) || Lib.ListMem(AST.MakerBot().Copy(), list) { sortedUnifs = insertFirst(sortedUnifs, unif) } else { @@ -177,7 +231,10 @@ func insert(sortedUnifs []Unif.MatchingSubstitutions, list Lib.List[AST.Form], u return sortedUnifs } -func insertFirst(sortedUnifs []Unif.MatchingSubstitutions, unif Unif.MatchingSubstitutions) []Unif.MatchingSubstitutions { +func insertFirst( + sortedUnifs []Unif.MatchingSubstitutions, + unif Unif.MatchingSubstitutions, +) []Unif.MatchingSubstitutions { if len(sortedUnifs) > 0 { // Moves everything to the right once. sortedUnifs = append(sortedUnifs[:1], sortedUnifs[0:]...) @@ -226,7 +283,11 @@ func checkMetaAreFromSearch(metas Lib.Set[AST.Meta], subst Unif.Substitutions) b return true } -func getUnifiedEquivalence(atom AST.Form, subst Unif.Substitutions, polarity bool) (Lib.List[AST.Form], error) { +func getUnifiedEquivalence( + atom AST.Form, + subst Unif.Substitutions, + polarity bool, +) (Lib.List[AST.Form], error) { equivalence := findEquivalence(atom, polarity) if equivalence.Empty() { return Lib.NewList[AST.Form](), diff --git a/src/Mods/equality/bse/equality_types.go b/src/Mods/equality/bse/equality_types.go index d0ce8462..71e47682 100644 --- a/src/Mods/equality/bse/equality_types.go +++ b/src/Mods/equality/bse/equality_types.go @@ -126,7 +126,6 @@ func retrieveEqualities(dt Unif.DataStructure) Equalities { eq_pred := AST.MakerPred(AST.Id_eq, Lib.NewList[AST.Ty](), Lib.NewList[AST.Term]()) eq_pred = AST.MakePred( - eq_pred.GetIndex(), AST.Id_eq, Lib.MkListV[AST.Ty](meta_ty), Lib.MkListV[AST.Term](MetaEQ1, MetaEQ2), @@ -157,7 +156,6 @@ func retrieveInequalities(dt Unif.DataStructure) Inequalities { neq_pred := AST.MakerPred(AST.Id_eq, Lib.NewList[AST.Ty](), Lib.NewList[AST.Term]()) neq_pred = AST.MakePred( - neq_pred.GetIndex(), AST.Id_eq, Lib.MkListV(meta_ty), Lib.MkListV[AST.Term](MetaNEQ1, MetaNEQ2), @@ -165,7 +163,11 @@ func retrieveInequalities(dt Unif.DataStructure) Inequalities { _, neq_list := dt.Unify(neq_pred) for _, ms := range neq_list { - ms_ordered := orderSubstForRetrieve(ms.MatchingSubstitutions().GetSubst(), MetaNEQ1, MetaNEQ2) + ms_ordered := orderSubstForRetrieve( + ms.MatchingSubstitutions().GetSubst(), + MetaNEQ1, + MetaNEQ2, + ) neq1_term, ok_t1 := ms_ordered.Get(MetaNEQ1) if ok_t1 == -1 { Glob.PrintError("RI", "Meta_eq_1 not found in map") diff --git a/src/Mods/equality/sateq/problem.go b/src/Mods/equality/sateq/problem.go index 7c409c6b..74665512 100644 --- a/src/Mods/equality/sateq/problem.go +++ b/src/Mods/equality/sateq/problem.go @@ -34,6 +34,7 @@ package sateq import ( "github.com/GoelandProver/Goeland/AST" "github.com/GoelandProver/Goeland/Glob" + "github.com/GoelandProver/Goeland/Lib" equality "github.com/GoelandProver/Goeland/Mods/equality/bse" "github.com/GoelandProver/Goeland/Mods/equality/eqStruct" "github.com/GoelandProver/Goeland/Unif" @@ -43,6 +44,8 @@ import ( type Problem struct { goals *Glob.List[*Glob.List[*Glob.BasicPair[*eqClass, *eqClass]]] + metas Lib.List[AST.Meta] + funs Lib.List[AST.Fun] functionsIndex map[int]*Glob.List[*termRecord] // terms indexed by their function symbol metasIndex map[int]*termRecord // metas indexed by identifier @@ -54,6 +57,8 @@ type Problem struct { func NewProblem() *Problem { pb := &Problem{ Glob.NewList[*Glob.List[*Glob.BasicPair[*eqClass, *eqClass]]](), + Lib.NewList[AST.Meta](), + Lib.NewList[AST.Fun](), make(map[int]*Glob.List[*termRecord]), make(map[int]*termRecord), @@ -104,13 +109,39 @@ func (problem *Problem) Metas() *Glob.List[*termRecord] { return l } +func (problem *Problem) mindex(m AST.Meta) int { + switch id := Lib.ListIndexOf(m, problem.metas).(type) { + case Lib.Some[int]: + return id.Val + case Lib.None[int]: + problem.metas = problem.metas.Push(m) + return problem.metas.Len() - 1 + } + + Glob.Anomaly("sateq", "Reached an unreachable state") + return -1 +} + +func (problem *Problem) findex(f AST.Fun) int { + switch id := Lib.ListIndexOf(f, problem.funs).(type) { + case Lib.Some[int]: + return id.Val + case Lib.None[int]: + problem.funs = problem.funs.Push(f) + return problem.funs.Len() - 1 + } + + Glob.Anomaly("sateq", "Reached an unreachable state") + return -1 +} + func (problem *Problem) getEquivalenceClass(t AST.Term) *eqClass { if t.IsMeta() { - if tr, found := problem.metasIndex[t.GetIndex()]; found { + if tr, found := problem.metasIndex[problem.mindex(t.ToMeta())]; found { return tr.eqClass } if typed, ok := t.(AST.Meta); ok { - return problem.addNewTermRecord(metaTermRecord(typed)) + return problem.addNewTermRecord(metaTermRecord(problem, typed)) } } else { if typed, ok := t.(AST.Fun); ok { @@ -118,7 +149,7 @@ func (problem *Problem) getEquivalenceClass(t AST.Term) *eqClass { for i, st := range typed.GetArgs().GetSlice() { args[i] = problem.getEquivalenceClass(st) } - tr1 := funTermRecord(typed, args) + tr1 := funTermRecord(problem, typed, args) if idxList, found := problem.functionsIndex[tr1.index]; found { for _, tr2 := range idxList.Slice() { if tr1.congruent(tr2) { @@ -167,8 +198,10 @@ func (problem *Problem) mergeEquivalenceClasses(ec1, ec2 *eqClass) { } // update indexes (see invariant above) - problem.partitionIndex[ecMerged].Append(problem.partitionIndex[ecDeleted].Slice()...) // the entries of partitionIndex are disjoint - problem.supertermIndex[ecMerged].AppendIfNotContains(problem.supertermIndex[ecDeleted].Slice()...) + problem.partitionIndex[ecMerged].Append( + problem.partitionIndex[ecDeleted].Slice()...) // the entries of partitionIndex are disjoint + problem.supertermIndex[ecMerged].AppendIfNotContains( + problem.supertermIndex[ecDeleted].Slice()...) delete(problem.partitionIndex, ecDeleted) delete(problem.supertermIndex, ecDeleted) @@ -186,14 +219,22 @@ func (problem *Problem) mergeEquivalenceClasses(ec1, ec2 *eqClass) { } func (problem *Problem) AddAssumption(eq eqStruct.TermPair) { - problem.mergeEquivalenceClasses(problem.getEquivalenceClass(eq.GetT1()), problem.getEquivalenceClass(eq.GetT2())) + problem.mergeEquivalenceClasses( + problem.getEquivalenceClass(eq.GetT1()), + problem.getEquivalenceClass(eq.GetT2()), + ) } func (problem *Problem) AddGoal(goal []eqStruct.TermPair) { g := Glob.NewList[*Glob.BasicPair[*eqClass, *eqClass]]() for _, eq := range goal { - g.AppendIfNotContains(Glob.NewBasicPair(problem.getEquivalenceClass(eq.GetT1()), problem.getEquivalenceClass(eq.GetT2()))) + g.AppendIfNotContains( + Glob.NewBasicPair( + problem.getEquivalenceClass(eq.GetT1()), + problem.getEquivalenceClass(eq.GetT2()), + ), + ) } problem.goals.AppendIfNotContains(g) diff --git a/src/Mods/equality/sateq/termrep.go b/src/Mods/equality/sateq/termrep.go index 244a5777..54145a6a 100644 --- a/src/Mods/equality/sateq/termrep.go +++ b/src/Mods/equality/sateq/termrep.go @@ -116,17 +116,17 @@ func makeEqClass() *eqClass { return &r } -func metaTermRecord(m AST.Meta) *termRecord { +func metaTermRecord(problem *Problem, m AST.Meta) *termRecord { return &termRecord{ - index: m.GetIndex(), + index: problem.mindex(m), eqClass: makeEqClass(), meta: &m, } } -func funTermRecord(t AST.Fun, args []*eqClass) *termRecord { +func funTermRecord(problem *Problem, t AST.Fun, args []*eqClass) *termRecord { return &termRecord{ - index: t.GetIndex(), + index: problem.findex(t), eqClass: makeEqClass(), meta: nil, symbolId: t.GetID(), diff --git a/src/Mods/lambdapi/output.go b/src/Mods/lambdapi/output.go index 403bd9de..5d2fbd20 100644 --- a/src/Mods/lambdapi/output.go +++ b/src/Mods/lambdapi/output.go @@ -156,8 +156,8 @@ func LambdapiPrinterAction() AST.PrinterAction { return result_string }, func(i AST.Id) string { return i.GetName() }, - AST.PrinterIdentity2[int], - func(metaName string, index int) string { return fmt.Sprintf("%s_%d", metaName, index) }, + AST.PrinterIdentity, + func(metaName string, metaIndex int) string { return fmt.Sprintf("%s_%d", metaName, metaIndex) }, sanitize_type, func(typed_var Lib.Pair[string, AST.Ty]) string { return fmt.Sprintf("(%s : %s)", typed_var.Fst, sanitize_type(typed_var.Snd.ToString())) diff --git a/src/Mods/rocq/output.go b/src/Mods/rocq/output.go index 15cc569c..bcb3aaff 100644 --- a/src/Mods/rocq/output.go +++ b/src/Mods/rocq/output.go @@ -121,8 +121,8 @@ func RocqPrinterAction() AST.PrinterAction { rocq_action := AST.MkPrinterAction( AST.PrinterIdentity, func(i AST.Id) string { return i.GetName() }, - AST.PrinterIdentity2[int], - func(metaName string, index int) string { return fmt.Sprintf("%s_%d", metaName, index) }, + AST.PrinterIdentity, + func(metaName string, metaIndex int) string { return fmt.Sprintf("%s_%d", metaName, metaIndex) }, sanitize_type, func(typed_var Lib.Pair[string, AST.Ty]) string { return fmt.Sprintf("(%s : %s)", typed_var.Fst, sanitize_type(typed_var.Snd.ToString())) diff --git a/src/Mods/tptp/proof.go b/src/Mods/tptp/proof.go index 57cafe0d..33eaeb85 100644 --- a/src/Mods/tptp/proof.go +++ b/src/Mods/tptp/proof.go @@ -72,7 +72,7 @@ func makeTPTPProofFromIProof(proof Search.IProof) string { proof.AppliedOn().GetSubTerms(), func(term AST.Term) AST.Term { new_term_name := fmt.Sprintf("%s%d", prefix_const, original_terms.Len()) - new_term := AST.MakerConst(AST.MakerNewId(new_term_name)) + new_term := AST.MakerConst(AST.MakerId(new_term_name)) original_terms.Append(Lib.MkRight[AST.Ty, AST.Term](term)) return new_term }, @@ -128,6 +128,22 @@ func fofInference( ) } +func axiomIndex(ax AST.Form, axioms Lib.List[AST.Form]) int { + switch i := Lib.ListIndexOf(ax, axioms).(type) { + case Lib.Some[int]: + return i.Val + } + + raise_anomaly( + fmt.Sprintf( + "Axiom %s not found in [%s]", + ax.ToString(), + Lib.ListToString(axioms, ", ", ""), + ), + ) + return -1 +} + func performCutAxiomStep(axioms Lib.List[AST.Form], conjecture AST.Form) string { axiom_steps := []string{} @@ -147,7 +163,7 @@ func performCutAxiomStep(axioms Lib.List[AST.Form], conjecture AST.Form) string "cut", "0", Lib.MkListV( - Lib.MkString(fmt.Sprintf("ax%d", ax.GetIndex())), + Lib.MkString(fmt.Sprintf("ax%d", axiomIndex(ax, axioms))), Lib.MkString(nextStep), ), ) @@ -670,7 +686,7 @@ func makeTheorem(axioms Lib.List[AST.Form], conjecture AST.Form) string { for _, ax := range axioms.GetSlice() { declared_axioms = append( declared_axioms, - fmt.Sprintf("fof(ax%d, axiom, %s).", ax.GetIndex(), ax.ToString()), + fmt.Sprintf("fof(ax%d, axiom, %s).", axiomIndex(ax, axioms), ax.ToString()), ) } diff --git a/src/Search/proof-adapter.go b/src/Search/proof-adapter.go index 7f31e5f2..f6c5aa1e 100644 --- a/src/Search/proof-adapter.go +++ b/src/Search/proof-adapter.go @@ -139,7 +139,7 @@ func (proof TableauxProof) RewrittenWith() Lib.Option[AST.Form] { end_form = end_form.(AST.All).GetForm() } end_form = getAtomic(end_form) - if end_form.GetIndex() == rewrite_id { + if dmt.RewID(end_form) == rewrite_id { form_opt = Lib.MkSome(axiom) } } diff --git a/src/Search/proof.go b/src/Search/proof.go index bce95dd1..15e4460d 100644 --- a/src/Search/proof.go +++ b/src/Search/proof.go @@ -296,7 +296,7 @@ func IntFormAndTermsListToIntIntStringPairList(fl []IntFormAndTermsList) []IntIn tmp_fl.Node_id = f.i for _, f2 := range f.fl { - tmp_fl.Isp = append(tmp_fl.Isp, IntStringPair{f2.GetForm().GetIndex(), f2.ToString()}) + tmp_fl.Isp = append(tmp_fl.Isp, IntStringPair{0, f2.ToString()}) } res = append(res, tmp_fl) } diff --git a/src/Unif/instruction.go b/src/Unif/instruction.go index f8b7e7c0..da434d8a 100644 --- a/src/Unif/instruction.go +++ b/src/Unif/instruction.go @@ -111,7 +111,8 @@ func (d Down) IsEquivalent(instr Instruction) bool { return reflect.TypeOf(instr) == reflect.TypeOf(d) } func (c Check) IsEquivalent(instr Instruction) bool { - return reflect.TypeOf(instr) == reflect.TypeOf(c) && c.term.GetName() == instr.(Check).term.GetName() && c.term.GetIndex() == instr.(Check).term.GetIndex() + return reflect.TypeOf(instr) == reflect.TypeOf(c) && + c.term.GetName() == instr.(Check).term.GetName() } func (p Push) IsEquivalent(instr Instruction) bool { return reflect.DeepEqual(p, instr) @@ -123,7 +124,8 @@ func (p Put) IsEquivalent(instr Instruction) bool { return reflect.TypeOf(instr) == reflect.TypeOf(p) && p.i == instr.(Put).i } func (c Compare) IsEquivalent(instr Instruction) bool { - return reflect.TypeOf(instr) == reflect.TypeOf(c) && c.i == instr.(Compare).i && c.j == instr.(Compare).j + return reflect.TypeOf(instr) == reflect.TypeOf(c) && c.i == instr.(Compare).i && + c.j == instr.(Compare).j } /* ToString */ diff --git a/src/Unif/machine.go b/src/Unif/machine.go index 6fa2c0ec..99f6e689 100644 --- a/src/Unif/machine.go +++ b/src/Unif/machine.go @@ -37,7 +37,10 @@ package Unif import ( + "fmt" + "github.com/GoelandProver/Goeland/AST" + "github.com/GoelandProver/Goeland/Glob" "github.com/GoelandProver/Goeland/Lib" ) @@ -103,13 +106,13 @@ func (m *Machine) getCurrentMeta() AST.Meta { /* While term is a metavariable, replace it by its substitution in the map of substitutions (meta). */ func (m *Machine) unwrapMeta(term AST.Term) AST.Term { - deja_vu := map[int]bool{} + deja_vu := Lib.EmptySet[AST.Term]() for term.IsMeta() { val, ok := m.meta.Get(term.ToMeta()) - if (ok == -1) || deja_vu[term.GetIndex()] { + if (ok == -1) || deja_vu.Contains(term) { break } - deja_vu[term.GetIndex()] = true + deja_vu = deja_vu.Add(term) term = val.Copy() } return term @@ -198,7 +201,18 @@ func removePost(slice []IntPair, s int) []IntPair { /*** Indexes Match ***/ /* Checks if the indexes of term1 and term2 match. */ func (m *Machine) doIndexMatch(term1, term2 AST.Term) bool { - return (term1.GetIndex() == term2.GetIndex()) + switch id1 := AST.GetSymbol(term1).(type) { + case Lib.Some[AST.Id]: + switch id2 := AST.GetSymbol(term2).(type) { + case Lib.Some[AST.Id]: + return id1.Val.Equals(id2.Val) + } + } + Glob.Anomaly( + "unif", + fmt.Sprintf("Expected %s and %s to be functionals", term1.ToString(), term2.ToString()), + ) + return false } /* Checks if the indexes of t and instrTerm match. If t is a meta, it will try to unwrap t to the end, and check if the indexes of the unwrapped t and instrTerm match. */ diff --git a/src/Unif/parsing.go b/src/Unif/parsing.go index 8697f578..c50f6246 100644 --- a/src/Unif/parsing.go +++ b/src/Unif/parsing.go @@ -38,13 +38,12 @@ import ( ) type TermForm struct { - index int - t AST.Term + t AST.Term } func (t TermForm) ToString() string { return t.ToString() } func (t TermForm) GetTerm() AST.Term { return t.t.Copy() } -func (t TermForm) Copy() AST.Form { return makeTermForm(t.GetIndex(), t.GetTerm()) } +func (t TermForm) Copy() AST.Form { return makeTermForm(t.GetTerm()) } func (t TermForm) RenameVariables() AST.Form { return t } func (t TermForm) ReplaceTermByTerm(AST.Term, AST.Term) (AST.Form, bool) { return t, false @@ -52,7 +51,6 @@ func (t TermForm) ReplaceTermByTerm(AST.Term, AST.Term) (AST.Form, bool) { func (t TermForm) SubstTy(AST.TyGenVar, AST.Ty) AST.Form { return t } -func (t TermForm) GetIndex() int { return t.index } func (t TermForm) SubstituteVarByMeta(AST.Var, AST.Meta) AST.Form { return t } func (t TermForm) GetInternalMetas() Lib.List[AST.Meta] { return Lib.NewList[AST.Meta]() } func (t TermForm) SetInternalMetas(Lib.List[AST.Meta]) AST.Form { return t } @@ -110,11 +108,11 @@ func MakerTermForm(t AST.Term) TermForm { args := getFunctionalArguments(trm.GetTyArgs(), trm.GetArgs()) t = AST.MakerFun(trm.GetID(), Lib.NewList[AST.Ty](), args) } - return makeTermForm(AST.MakerIndexFormula(), t.Copy()) + return makeTermForm(t.Copy()) } -func makeTermForm(i int, t AST.Term) TermForm { - return TermForm{i, t.Copy()} +func makeTermForm(t AST.Term) TermForm { + return TermForm{t.Copy()} } /* Parses a formulae to a sequence of instructions. */ diff --git a/src/Unif/substitutions_type.go b/src/Unif/substitutions_type.go index 7c43b118..4d69ee69 100644 --- a/src/Unif/substitutions_type.go +++ b/src/Unif/substitutions_type.go @@ -93,7 +93,8 @@ func (s Substitutions) Equals(other any) bool { i := 0 for !found && i < len(typed) { - if subst_s1.Key().Equals(typed[i].Key()) && subst_s1.Value().Equals(typed[i].Value()) { + if subst_s1.Key().Equals(typed[i].Key()) && + subst_s1.Value().Equals(typed[i].Value()) { found = true } @@ -134,11 +135,9 @@ func (s *Substitutions) Set(key AST.Meta, value AST.Term) { } func (s Substitutions) Get(key AST.Meta) (AST.Term, int) { - if key.GetIndex() != -1 { - for i, subst := range s { - if subst.Key().Equals(key) { - return subst.Value(), i - } + for i, subst := range s { + if subst.Key().Equals(key) { + return subst.Value(), i } } return nil, -1 @@ -290,7 +289,12 @@ func Eliminate(s *Substitutions) { } /* Eliminate inside : eliminate for a given couple (key, value) on a substitution */ -func eliminateInside(key AST.Meta, value AST.Term, s Substitutions, has_changed_top *bool) Substitutions { +func eliminateInside( + key AST.Meta, + value AST.Term, + s Substitutions, + has_changed_top *bool, +) Substitutions { has_changed := true for has_changed { has_changed = false From 6274fc03ac6be8ccc73536b639f5081286053fcc Mon Sep 17 00:00:00 2001 From: Johann Rosain Date: Fri, 20 Mar 2026 14:38:34 +0100 Subject: [PATCH 25/30] test-suite: remove indexes of bound variables in the .out --- devtools/test-suite/proofs/example_sctptp.out | 30 +++++++-------- devtools/test-suite/proofs/example_tptp.out | 30 +++++++-------- .../test-suite/proofs/tf1_basic_thm-2.out | 38 +++++++++---------- devtools/test-suite/proofs/tf1_basic_thm.out | 18 ++++----- 4 files changed, 58 insertions(+), 58 deletions(-) diff --git a/devtools/test-suite/proofs/example_sctptp.out b/devtools/test-suite/proofs/example_sctptp.out index b99a1dfc..36dbe26e 100644 --- a/devtools/test-suite/proofs/example_sctptp.out +++ b/devtools/test-suite/proofs/example_sctptp.out @@ -1,29 +1,29 @@ -fof(c_example_sctptp_p, conjecture, (! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))). +fof(c_example_sctptp_p, conjecture, (! [X]: p(X)) <=> ~(? [Y]: ~p(Y))). -fof(f8, plain, [~((! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))), ~(! [X4]: p(X4)), ~(? [Y6]: ~p(Y6)), ~(~(? [Y6]: ~p(Y6)) => (! [X4]: p(X4))), ~p(Sko_0), ~~p(Sko_0), p(Sko_0)] --> [], inference(leftHyp, [status(thm), 6], [])). +fof(f8, plain, [~((! [X]: p(X)) <=> ~(? [Y]: ~p(Y))), ~(! [X]: p(X)), ~(? [Y]: ~p(Y)), ~(~(? [Y]: ~p(Y)) => (! [X]: p(X))), ~p(Sko_0), ~~p(Sko_0), p(Sko_0)] --> [], inference(leftHyp, [status(thm), 6], [])). -fof(f7, plain, [~((! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))), ~(! [X4]: p(X4)), ~(? [Y6]: ~p(Y6)), ~(~(? [Y6]: ~p(Y6)) => (! [X4]: p(X4))), ~p(Sko_0), ~~p(Sko_0)] --> [], inference(leftNotNot, [status(thm), 5], [f8])). +fof(f7, plain, [~((! [X]: p(X)) <=> ~(? [Y]: ~p(Y))), ~(! [X]: p(X)), ~(? [Y]: ~p(Y)), ~(~(? [Y]: ~p(Y)) => (! [X]: p(X))), ~p(Sko_0), ~~p(Sko_0)] --> [], inference(leftNotNot, [status(thm), 5], [f8])). -fof(f6, plain, [~((! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))), ~(! [X4]: p(X4)), ~(? [Y6]: ~p(Y6)), ~(~(? [Y6]: ~p(Y6)) => (! [X4]: p(X4))), ~p(Sko_0)] --> [], inference(leftNotEx, [status(thm), 2, $fot(Sko_0)], [f7])). +fof(f6, plain, [~((! [X]: p(X)) <=> ~(? [Y]: ~p(Y))), ~(! [X]: p(X)), ~(? [Y]: ~p(Y)), ~(~(? [Y]: ~p(Y)) => (! [X]: p(X))), ~p(Sko_0)] --> [], inference(leftNotEx, [status(thm), 2, $fot(Sko_0)], [f7])). -fof(f4, plain, [~((! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))), ~(! [X4]: p(X4)), ~(? [Y6]: ~p(Y6)), ~(~(? [Y6]: ~p(Y6)) => (! [X4]: p(X4)))] --> [], inference(leftNotAll, [status(thm), 1, 'Sko_0'], [f6])). +fof(f4, plain, [~((! [X]: p(X)) <=> ~(? [Y]: ~p(Y))), ~(! [X]: p(X)), ~(? [Y]: ~p(Y)), ~(~(? [Y]: ~p(Y)) => (! [X]: p(X)))] --> [], inference(leftNotAll, [status(thm), 1, 'Sko_0'], [f6])). -fof(f11, plain, [~((! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))), ! [X4]: p(X4), ~~(? [Y6]: ~p(Y6)), ~((! [X4]: p(X4)) => ~(? [Y6]: ~p(Y6))), ? [Y6]: ~p(Y6), ~p(Sko_1), p(Sko_1)] --> [], inference(leftHyp, [status(thm), 6], [])). +fof(f11, plain, [~((! [X]: p(X)) <=> ~(? [Y]: ~p(Y))), ! [X]: p(X), ~~(? [Y]: ~p(Y)), ~((! [X]: p(X)) => ~(? [Y]: ~p(Y))), ? [Y]: ~p(Y), ~p(Sko_1), p(Sko_1)] --> [], inference(leftHyp, [status(thm), 6], [])). -fof(f10, plain, [~((! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))), ! [X4]: p(X4), ~~(? [Y6]: ~p(Y6)), ~((! [X4]: p(X4)) => ~(? [Y6]: ~p(Y6))), ? [Y6]: ~p(Y6), ~p(Sko_1)] --> [], inference(leftForall, [status(thm), 1, $fot(Sko_1)], [f11])). +fof(f10, plain, [~((! [X]: p(X)) <=> ~(? [Y]: ~p(Y))), ! [X]: p(X), ~~(? [Y]: ~p(Y)), ~((! [X]: p(X)) => ~(? [Y]: ~p(Y))), ? [Y]: ~p(Y), ~p(Sko_1)] --> [], inference(leftForall, [status(thm), 1, $fot(Sko_1)], [f11])). -fof(f9, plain, [~((! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))), ! [X4]: p(X4), ~~(? [Y6]: ~p(Y6)), ~((! [X4]: p(X4)) => ~(? [Y6]: ~p(Y6))), ? [Y6]: ~p(Y6)] --> [], inference(leftExists, [status(thm), 4, 'Sko_1'], [f10])). +fof(f9, plain, [~((! [X]: p(X)) <=> ~(? [Y]: ~p(Y))), ! [X]: p(X), ~~(? [Y]: ~p(Y)), ~((! [X]: p(X)) => ~(? [Y]: ~p(Y))), ? [Y]: ~p(Y)] --> [], inference(leftExists, [status(thm), 4, 'Sko_1'], [f10])). -fof(f5, plain, [~((! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))), ! [X4]: p(X4), ~~(? [Y6]: ~p(Y6)), ~((! [X4]: p(X4)) => ~(? [Y6]: ~p(Y6)))] --> [], inference(leftNotNot, [status(thm), 2], [f9])). +fof(f5, plain, [~((! [X]: p(X)) <=> ~(? [Y]: ~p(Y))), ! [X]: p(X), ~~(? [Y]: ~p(Y)), ~((! [X]: p(X)) => ~(? [Y]: ~p(Y)))] --> [], inference(leftNotNot, [status(thm), 2], [f9])). -fof(f3ext2, plain, [~((! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))), ~(~(? [Y6]: ~p(Y6)) => (! [X4]: p(X4)))] --> [], inference(leftNotImplies, [status(thm), 1], [f4])). +fof(f3ext2, plain, [~((! [X]: p(X)) <=> ~(? [Y]: ~p(Y))), ~(~(? [Y]: ~p(Y)) => (! [X]: p(X)))] --> [], inference(leftNotImplies, [status(thm), 1], [f4])). -fof(f3ext1, plain, [~((! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))), ~((! [X4]: p(X4)) => ~(? [Y6]: ~p(Y6)))] --> [], inference(leftNotImplies, [status(thm), 1], [f5])). +fof(f3ext1, plain, [~((! [X]: p(X)) <=> ~(? [Y]: ~p(Y))), ~((! [X]: p(X)) => ~(? [Y]: ~p(Y)))] --> [], inference(leftNotImplies, [status(thm), 1], [f5])). -fof(f3, plain, [~((! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6)))] --> [], inference(leftNotIff, [status(thm), 0], [f3ext1, f3ext2])). +fof(f3, plain, [~((! [X]: p(X)) <=> ~(? [Y]: ~p(Y)))] --> [], inference(leftNotIff, [status(thm), 0], [f3ext1, f3ext2])). -fof(f2, plain, [(! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))] --> [(! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))], inference(hyp, [status(thm), 0], [])). +fof(f2, plain, [(! [X]: p(X)) <=> ~(? [Y]: ~p(Y))] --> [(! [X]: p(X)) <=> ~(? [Y]: ~p(Y))], inference(hyp, [status(thm), 0], [])). -fof(f1, plain, [] --> [(! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6)), ~((! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6)))], inference(rightNot, [status(thm), 1], [f2])). +fof(f1, plain, [] --> [(! [X]: p(X)) <=> ~(? [Y]: ~p(Y)), ~((! [X]: p(X)) <=> ~(? [Y]: ~p(Y)))], inference(rightNot, [status(thm), 1], [f2])). -fof(f0, plain, [] --> [(! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))], inference(cut, [status(thm), 1], [f1, f3])). +fof(f0, plain, [] --> [(! [X]: p(X)) <=> ~(? [Y]: ~p(Y))], inference(cut, [status(thm), 1], [f1, f3])). diff --git a/devtools/test-suite/proofs/example_tptp.out b/devtools/test-suite/proofs/example_tptp.out index 3ae286e7..a5a9dfbf 100644 --- a/devtools/test-suite/proofs/example_tptp.out +++ b/devtools/test-suite/proofs/example_tptp.out @@ -1,29 +1,29 @@ -fof(c_example_tptp_p, conjecture, (! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))). +fof(c_example_tptp_p, conjecture, (! [X]: p(X)) <=> ~(? [Y]: ~p(Y))). -fof(f8, plain, [~((! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))), ~(! [X4]: p(X4)), ~(? [Y6]: ~p(Y6)), ~(~(? [Y6]: ~p(Y6)) => (! [X4]: p(X4))), ~p(sko_0), ~~p(sko_0), p(sko_0)] --> [], inference(leftHyp, [status(thm), 6], [])). +fof(f8, plain, [~((! [X]: p(X)) <=> ~(? [Y]: ~p(Y))), ~(! [X]: p(X)), ~(? [Y]: ~p(Y)), ~(~(? [Y]: ~p(Y)) => (! [X]: p(X))), ~p(sko_0), ~~p(sko_0), p(sko_0)] --> [], inference(leftHyp, [status(thm), 6], [])). -fof(f7, plain, [~((! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))), ~(! [X4]: p(X4)), ~(? [Y6]: ~p(Y6)), ~(~(? [Y6]: ~p(Y6)) => (! [X4]: p(X4))), ~p(sko_0), ~~p(sko_0)] --> [], inference(leftNotNot, [status(thm), 5], [f8])). +fof(f7, plain, [~((! [X]: p(X)) <=> ~(? [Y]: ~p(Y))), ~(! [X]: p(X)), ~(? [Y]: ~p(Y)), ~(~(? [Y]: ~p(Y)) => (! [X]: p(X))), ~p(sko_0), ~~p(sko_0)] --> [], inference(leftNotNot, [status(thm), 5], [f8])). -fof(f6, plain, [~((! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))), ~(! [X4]: p(X4)), ~(? [Y6]: ~p(Y6)), ~(~(? [Y6]: ~p(Y6)) => (! [X4]: p(X4))), ~p(sko_0)] --> [], inference(leftNotEx, [status(thm), 2, $fot(sko_0)], [f7])). +fof(f6, plain, [~((! [X]: p(X)) <=> ~(? [Y]: ~p(Y))), ~(! [X]: p(X)), ~(? [Y]: ~p(Y)), ~(~(? [Y]: ~p(Y)) => (! [X]: p(X))), ~p(sko_0)] --> [], inference(leftNotEx, [status(thm), 2, $fot(sko_0)], [f7])). -fof(f4, plain, [~((! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))), ~(! [X4]: p(X4)), ~(? [Y6]: ~p(Y6)), ~(~(? [Y6]: ~p(Y6)) => (! [X4]: p(X4)))] --> [], inference(leftNotAll, [status(thm), 1, 'sko_0'], [f6])). +fof(f4, plain, [~((! [X]: p(X)) <=> ~(? [Y]: ~p(Y))), ~(! [X]: p(X)), ~(? [Y]: ~p(Y)), ~(~(? [Y]: ~p(Y)) => (! [X]: p(X)))] --> [], inference(leftNotAll, [status(thm), 1, 'sko_0'], [f6])). -fof(f11, plain, [~((! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))), ! [X4]: p(X4), ~~(? [Y6]: ~p(Y6)), ~((! [X4]: p(X4)) => ~(? [Y6]: ~p(Y6))), ? [Y6]: ~p(Y6), ~p(sko_1), p(sko_1)] --> [], inference(leftHyp, [status(thm), 6], [])). +fof(f11, plain, [~((! [X]: p(X)) <=> ~(? [Y]: ~p(Y))), ! [X]: p(X), ~~(? [Y]: ~p(Y)), ~((! [X]: p(X)) => ~(? [Y]: ~p(Y))), ? [Y]: ~p(Y), ~p(sko_1), p(sko_1)] --> [], inference(leftHyp, [status(thm), 6], [])). -fof(f10, plain, [~((! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))), ! [X4]: p(X4), ~~(? [Y6]: ~p(Y6)), ~((! [X4]: p(X4)) => ~(? [Y6]: ~p(Y6))), ? [Y6]: ~p(Y6), ~p(sko_1)] --> [], inference(leftForall, [status(thm), 1, $fot(sko_1)], [f11])). +fof(f10, plain, [~((! [X]: p(X)) <=> ~(? [Y]: ~p(Y))), ! [X]: p(X), ~~(? [Y]: ~p(Y)), ~((! [X]: p(X)) => ~(? [Y]: ~p(Y))), ? [Y]: ~p(Y), ~p(sko_1)] --> [], inference(leftForall, [status(thm), 1, $fot(sko_1)], [f11])). -fof(f9, plain, [~((! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))), ! [X4]: p(X4), ~~(? [Y6]: ~p(Y6)), ~((! [X4]: p(X4)) => ~(? [Y6]: ~p(Y6))), ? [Y6]: ~p(Y6)] --> [], inference(leftExists, [status(thm), 4, 'sko_1'], [f10])). +fof(f9, plain, [~((! [X]: p(X)) <=> ~(? [Y]: ~p(Y))), ! [X]: p(X), ~~(? [Y]: ~p(Y)), ~((! [X]: p(X)) => ~(? [Y]: ~p(Y))), ? [Y]: ~p(Y)] --> [], inference(leftExists, [status(thm), 4, 'sko_1'], [f10])). -fof(f5, plain, [~((! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))), ! [X4]: p(X4), ~~(? [Y6]: ~p(Y6)), ~((! [X4]: p(X4)) => ~(? [Y6]: ~p(Y6)))] --> [], inference(leftNotNot, [status(thm), 2], [f9])). +fof(f5, plain, [~((! [X]: p(X)) <=> ~(? [Y]: ~p(Y))), ! [X]: p(X), ~~(? [Y]: ~p(Y)), ~((! [X]: p(X)) => ~(? [Y]: ~p(Y)))] --> [], inference(leftNotNot, [status(thm), 2], [f9])). -fof(f3ext2, plain, [~((! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))), ~(~(? [Y6]: ~p(Y6)) => (! [X4]: p(X4)))] --> [], inference(leftNotImplies, [status(thm), 1], [f4])). +fof(f3ext2, plain, [~((! [X]: p(X)) <=> ~(? [Y]: ~p(Y))), ~(~(? [Y]: ~p(Y)) => (! [X]: p(X)))] --> [], inference(leftNotImplies, [status(thm), 1], [f4])). -fof(f3ext1, plain, [~((! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))), ~((! [X4]: p(X4)) => ~(? [Y6]: ~p(Y6)))] --> [], inference(leftNotImplies, [status(thm), 1], [f5])). +fof(f3ext1, plain, [~((! [X]: p(X)) <=> ~(? [Y]: ~p(Y))), ~((! [X]: p(X)) => ~(? [Y]: ~p(Y)))] --> [], inference(leftNotImplies, [status(thm), 1], [f5])). -fof(f3, plain, [~((! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6)))] --> [], inference(leftNotIff, [status(thm), 0], [f3ext1, f3ext2])). +fof(f3, plain, [~((! [X]: p(X)) <=> ~(? [Y]: ~p(Y)))] --> [], inference(leftNotIff, [status(thm), 0], [f3ext1, f3ext2])). -fof(f2, plain, [(! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))] --> [(! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))], inference(hyp, [status(thm), 0], [])). +fof(f2, plain, [(! [X]: p(X)) <=> ~(? [Y]: ~p(Y))] --> [(! [X]: p(X)) <=> ~(? [Y]: ~p(Y))], inference(hyp, [status(thm), 0], [])). -fof(f1, plain, [] --> [(! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6)), ~((! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6)))], inference(rightNot, [status(thm), 1], [f2])). +fof(f1, plain, [] --> [(! [X]: p(X)) <=> ~(? [Y]: ~p(Y)), ~((! [X]: p(X)) <=> ~(? [Y]: ~p(Y)))], inference(rightNot, [status(thm), 1], [f2])). -fof(f0, plain, [] --> [(! [X4]: p(X4)) <=> ~(? [Y6]: ~p(Y6))], inference(cut, [status(thm), 1], [f1, f3])). +fof(f0, plain, [] --> [(! [X]: p(X)) <=> ~(? [Y]: ~p(Y))], inference(cut, [status(thm), 1], [f1, f3])). diff --git a/devtools/test-suite/proofs/tf1_basic_thm-2.out b/devtools/test-suite/proofs/tf1_basic_thm-2.out index 9f8a3e0e..16a0fdbb 100644 --- a/devtools/test-suite/proofs/tf1_basic_thm-2.out +++ b/devtools/test-suite/proofs/tf1_basic_thm-2.out @@ -1,28 +1,28 @@ -[0] ALPHA_AND : (! [A13]: head(A13 ; nil(A13 ; )) = none(A13 ; )) & (! [A15, X17, XS19]: head(A15 ; cons(A15 ; X17, XS19)) = some(A15 ; X17)) & ~(! [A21, X23, Y25, Z27]: head(A21 ; cons(A21 ; X23, cons(A21 ; Y25, cons(A21 ; Z27, nil(A21 ; ))))) = some(A21 ; X23)) - -> [1] ! [A13]: head(A13 ; nil(A13 ; )) = none(A13 ; ), ! [A15, X17, XS19]: head(A15 ; cons(A15 ; X17, XS19)) = some(A15 ; X17), ~(! [A21, X23, Y25, Z27]: head(A21 ; cons(A21 ; X23, cons(A21 ; Y25, cons(A21 ; Z27, nil(A21 ; ))))) = some(A21 ; X23)) +[0] ALPHA_AND : (! [A]: head(A ; nil(A ; )) = none(A ; )) & (! [A, X, XS]: head(A ; cons(A ; X, XS)) = some(A ; X)) & ~(! [A, X, Y, Z]: head(A ; cons(A ; X, cons(A ; Y, cons(A ; Z, nil(A ; ))))) = some(A ; X)) + -> [1] ! [A]: head(A ; nil(A ; )) = none(A ; ), ! [A, X, XS]: head(A ; cons(A ; X, XS)) = some(A ; X), ~(! [A, X, Y, Z]: head(A ; cons(A ; X, cons(A ; Y, cons(A ; Z, nil(A ; ))))) = some(A ; X)) -[1] DELTA_NOT_FORALL : ~(! [A21, X23, Y25, Z27]: head(A21 ; cons(A21 ; X23, cons(A21 ; Y25, cons(A21 ; Z27, nil(A21 ; ))))) = some(A21 ; X23)) - -> [2] ~(! [X23, Y25, Z27]: head(skoTy@29 ; cons(skoTy@29 ; X23, cons(skoTy@29 ; Y25, cons(skoTy@29 ; Z27, nil(skoTy@29 ; ))))) = some(skoTy@29 ; X23)) +[1] DELTA_NOT_FORALL : ~(! [A, X, Y, Z]: head(A ; cons(A ; X, cons(A ; Y, cons(A ; Z, nil(A ; ))))) = some(A ; X)) + -> [2] ~(! [X, Y, Z]: head(skoTy@0 ; cons(skoTy@0 ; X, cons(skoTy@0 ; Y, cons(skoTy@0 ; Z, nil(skoTy@0 ; ))))) = some(skoTy@0 ; X)) -[2] DELTA_NOT_FORALL : ~(! [X23, Y25, Z27]: head(skoTy@29 ; cons(skoTy@29 ; X23, cons(skoTy@29 ; Y25, cons(skoTy@29 ; Z27, nil(skoTy@29 ; ))))) = some(skoTy@29 ; X23)) - -> [3] ~(! [Y25, Z27]: head(skoTy@29 ; cons(skoTy@29 ; skolem@X23@0, cons(skoTy@29 ; Y25, cons(skoTy@29 ; Z27, nil(skoTy@29 ; ))))) = some(skoTy@29 ; skolem@X23@0)) +[2] DELTA_NOT_FORALL : ~(! [X, Y, Z]: head(skoTy@0 ; cons(skoTy@0 ; X, cons(skoTy@0 ; Y, cons(skoTy@0 ; Z, nil(skoTy@0 ; ))))) = some(skoTy@0 ; X)) + -> [3] ~(! [Y, Z]: head(skoTy@0 ; cons(skoTy@0 ; skolem@0, cons(skoTy@0 ; Y, cons(skoTy@0 ; Z, nil(skoTy@0 ; ))))) = some(skoTy@0 ; skolem@0)) -[3] DELTA_NOT_FORALL : ~(! [Y25, Z27]: head(skoTy@29 ; cons(skoTy@29 ; skolem@X23@0, cons(skoTy@29 ; Y25, cons(skoTy@29 ; Z27, nil(skoTy@29 ; ))))) = some(skoTy@29 ; skolem@X23@0)) - -> [4] ~(! [Z27]: head(skoTy@29 ; cons(skoTy@29 ; skolem@X23@0, cons(skoTy@29 ; skolem@Y25@1, cons(skoTy@29 ; Z27, nil(skoTy@29 ; ))))) = some(skoTy@29 ; skolem@X23@0)) +[3] DELTA_NOT_FORALL : ~(! [Y, Z]: head(skoTy@0 ; cons(skoTy@0 ; skolem@0, cons(skoTy@0 ; Y, cons(skoTy@0 ; Z, nil(skoTy@0 ; ))))) = some(skoTy@0 ; skolem@0)) + -> [4] ~(! [Z]: head(skoTy@0 ; cons(skoTy@0 ; skolem@0, cons(skoTy@0 ; skolem@1, cons(skoTy@0 ; Z, nil(skoTy@0 ; ))))) = some(skoTy@0 ; skolem@0)) -[4] DELTA_NOT_FORALL : ~(! [Z27]: head(skoTy@29 ; cons(skoTy@29 ; skolem@X23@0, cons(skoTy@29 ; skolem@Y25@1, cons(skoTy@29 ; Z27, nil(skoTy@29 ; ))))) = some(skoTy@29 ; skolem@X23@0)) - -> [5] ~(head(skoTy@29 ; cons(skoTy@29 ; skolem@X23@0, cons(skoTy@29 ; skolem@Y25@1, cons(skoTy@29 ; skolem@Z27@2, nil(skoTy@29 ; ))))) = some(skoTy@29 ; skolem@X23@0)) +[4] DELTA_NOT_FORALL : ~(! [Z]: head(skoTy@0 ; cons(skoTy@0 ; skolem@0, cons(skoTy@0 ; skolem@1, cons(skoTy@0 ; Z, nil(skoTy@0 ; ))))) = some(skoTy@0 ; skolem@0)) + -> [5] ~(head(skoTy@0 ; cons(skoTy@0 ; skolem@0, cons(skoTy@0 ; skolem@1, cons(skoTy@0 ; skolem@2, nil(skoTy@0 ; ))))) = some(skoTy@0 ; skolem@0)) -[5] GAMMA_FORALL : ! [A13]: head(A13 ; nil(A13 ; )) = none(A13 ; ) - -> [6] head(A13 ; nil(A13 ; )) = none(A13 ; ) +[5] GAMMA_FORALL : ! [A]: head(A ; nil(A ; )) = none(A ; ) + -> [6] head(A ; nil(A ; )) = none(A ; ) -[6] GAMMA_FORALL : ! [A15, X17, XS19]: head(A15 ; cons(A15 ; X17, XS19)) = some(A15 ; X17) - -> [7] ! [X17, XS19]: head(skoTy@29 ; cons(skoTy@29 ; X17, XS19)) = some(skoTy@29 ; X17) +[6] GAMMA_FORALL : ! [A, X, XS]: head(A ; cons(A ; X, XS)) = some(A ; X) + -> [7] ! [X, XS]: head(skoTy@0 ; cons(skoTy@0 ; X, XS)) = some(skoTy@0 ; X) -[7] GAMMA_FORALL : ! [X17, XS19]: head(skoTy@29 ; cons(skoTy@29 ; X17, XS19)) = some(skoTy@29 ; X17) - -> [8] ! [XS19]: head(skoTy@29 ; cons(skoTy@29 ; skolem@X23@0, XS19)) = some(skoTy@29 ; skolem@X23@0) +[7] GAMMA_FORALL : ! [X, XS]: head(skoTy@0 ; cons(skoTy@0 ; X, XS)) = some(skoTy@0 ; X) + -> [8] ! [XS]: head(skoTy@0 ; cons(skoTy@0 ; skolem@0, XS)) = some(skoTy@0 ; skolem@0) -[8] GAMMA_FORALL : ! [XS19]: head(skoTy@29 ; cons(skoTy@29 ; skolem@X23@0, XS19)) = some(skoTy@29 ; skolem@X23@0) - -> [9] head(skoTy@29 ; cons(skoTy@29 ; skolem@X23@0, cons(skoTy@29 ; skolem@Y25@1, cons(skoTy@29 ; skolem@Z27@2, nil(skoTy@29 ; ))))) = some(skoTy@29 ; skolem@X23@0) +[8] GAMMA_FORALL : ! [XS]: head(skoTy@0 ; cons(skoTy@0 ; skolem@0, XS)) = some(skoTy@0 ; skolem@0) + -> [9] head(skoTy@0 ; cons(skoTy@0 ; skolem@0, cons(skoTy@0 ; skolem@1, cons(skoTy@0 ; skolem@2, nil(skoTy@0 ; ))))) = some(skoTy@0 ; skolem@0) -[9] CLOSURE : head(skoTy@29 ; cons(skoTy@29 ; skolem@X23@0, cons(skoTy@29 ; skolem@Y25@1, cons(skoTy@29 ; skolem@Z27@2, nil(skoTy@29 ; ))))) = some(skoTy@29 ; skolem@X23@0) +[9] CLOSURE : head(skoTy@0 ; cons(skoTy@0 ; skolem@0, cons(skoTy@0 ; skolem@1, cons(skoTy@0 ; skolem@2, nil(skoTy@0 ; ))))) = some(skoTy@0 ; skolem@0) diff --git a/devtools/test-suite/proofs/tf1_basic_thm.out b/devtools/test-suite/proofs/tf1_basic_thm.out index 3a5ce077..9a0b34af 100644 --- a/devtools/test-suite/proofs/tf1_basic_thm.out +++ b/devtools/test-suite/proofs/tf1_basic_thm.out @@ -1,16 +1,16 @@ -[0] ALPHA_AND : (! [A14]: head(A14 ; nil(A14 ; )) = none(A14 ; )) & (! [A16, X18, XS20]: head(A16 ; cons(A16 ; X18, XS20)) = some(A16 ; X18)) & ~(head($int ; cons($int ; 1, cons($int ; 2, cons($int ; 3, nil($int ; ))))) = some($int ; 1)) - -> [1] ! [A14]: head(A14 ; nil(A14 ; )) = none(A14 ; ), ! [A16, X18, XS20]: head(A16 ; cons(A16 ; X18, XS20)) = some(A16 ; X18), ~(head($int ; cons($int ; 1, cons($int ; 2, cons($int ; 3, nil($int ; ))))) = some($int ; 1)) +[0] ALPHA_AND : (! [A]: head(A ; nil(A ; )) = none(A ; )) & (! [A, X, XS]: head(A ; cons(A ; X, XS)) = some(A ; X)) & ~(head($int ; cons($int ; 1, cons($int ; 2, cons($int ; 3, nil($int ; ))))) = some($int ; 1)) + -> [1] ! [A]: head(A ; nil(A ; )) = none(A ; ), ! [A, X, XS]: head(A ; cons(A ; X, XS)) = some(A ; X), ~(head($int ; cons($int ; 1, cons($int ; 2, cons($int ; 3, nil($int ; ))))) = some($int ; 1)) -[1] GAMMA_FORALL : ! [A14]: head(A14 ; nil(A14 ; )) = none(A14 ; ) - -> [2] head(A14 ; nil(A14 ; )) = none(A14 ; ) +[1] GAMMA_FORALL : ! [A]: head(A ; nil(A ; )) = none(A ; ) + -> [2] head(A ; nil(A ; )) = none(A ; ) -[2] GAMMA_FORALL : ! [A16, X18, XS20]: head(A16 ; cons(A16 ; X18, XS20)) = some(A16 ; X18) - -> [3] ! [X18, XS20]: head($int ; cons($int ; X18, XS20)) = some($int ; X18) +[2] GAMMA_FORALL : ! [A, X, XS]: head(A ; cons(A ; X, XS)) = some(A ; X) + -> [3] ! [X, XS]: head($int ; cons($int ; X, XS)) = some($int ; X) -[3] GAMMA_FORALL : ! [X18, XS20]: head($int ; cons($int ; X18, XS20)) = some($int ; X18) - -> [4] ! [XS20]: head($int ; cons($int ; 1, XS20)) = some($int ; 1) +[3] GAMMA_FORALL : ! [X, XS]: head($int ; cons($int ; X, XS)) = some($int ; X) + -> [4] ! [XS]: head($int ; cons($int ; 1, XS)) = some($int ; 1) -[4] GAMMA_FORALL : ! [XS20]: head($int ; cons($int ; 1, XS20)) = some($int ; 1) +[4] GAMMA_FORALL : ! [XS]: head($int ; cons($int ; 1, XS)) = some($int ; 1) -> [5] head($int ; cons($int ; 1, cons($int ; 2, cons($int ; 3, nil($int ; ))))) = some($int ; 1) [5] CLOSURE : head($int ; cons($int ; 1, cons($int ; 2, cons($int ; 3, nil($int ; ))))) = some($int ; 1) From 5b59b357ab7621a24399fd36ad963a2f40e32feb Mon Sep 17 00:00:00 2001 From: Johann Rosain Date: Fri, 20 Mar 2026 15:20:01 +0100 Subject: [PATCH 26/30] upd: remove maker functions to keep only make functions --- src/AST/forms-def.go | 101 +----------------- src/AST/formula.go | 2 +- src/AST/maker.go | 99 +++++++++++++---- src/AST/quantifiers.go | 2 +- src/AST/term.go | 21 ---- src/AST/terms-def.go | 14 +-- src/AST/ty-syntax.go | 6 +- src/Core/Sko/inner-skolemization.go | 2 +- src/Core/Sko/interface.go | 2 +- src/Core/Sko/outer-skolemization.go | 2 +- src/Core/Sko/preinner-skolemization.go | 6 +- src/Core/instanciation.go | 10 +- src/Core/skolemisation.go | 8 +- src/Core/substitutions_search.go | 2 +- src/Engine/syntax-translation.go | 30 +++--- src/Mods/CertifUtils/utils.go | 2 +- src/Mods/desko/proof.go | 2 +- src/Mods/dmt/axiom_registration.go | 18 ++-- src/Mods/dmt/rewrite.go | 2 +- .../equality/bse/equality_problem_list.go | 4 +- src/Mods/equality/bse/equality_types.go | 12 +-- src/Mods/equality/sateq/subsgatherer.go | 2 +- src/Mods/lambdapi/context.go | 2 +- src/Mods/lambdapi/proof.go | 12 +-- src/Mods/rocq/context.go | 2 +- src/Mods/rocq/proof.go | 10 +- src/Mods/tptp/proof.go | 20 ++-- src/Search/incremental/rules.go | 16 +-- src/Search/proof-adapter.go | 2 +- src/Search/proof.go | 2 +- src/Search/rules.go | 16 +-- src/Unif/matching.go | 2 +- src/Unif/matching_substitutions.go | 2 +- src/Unif/parsing.go | 4 +- src/Unif/substitutions_type.go | 4 +- src/main.go | 8 +- 36 files changed, 196 insertions(+), 255 deletions(-) diff --git a/src/AST/forms-def.go b/src/AST/forms-def.go index 2c12971c..4032ae28 100644 --- a/src/AST/forms-def.go +++ b/src/AST/forms-def.go @@ -91,14 +91,6 @@ func MakeAllSimple(vars Lib.List[TypedVar], forms Form, metas Lib.Set[Meta]) All return All{makeQuantifier(vars, forms, metas, ConnAll)} } -func MakeAll(vars Lib.List[TypedVar], forms Form) All { - return MakeAllSimple(vars, forms, Lib.EmptySet[Meta]()) -} - -func MakerAll(vars Lib.List[TypedVar], forms Form) All { - return MakeAll(vars, forms) -} - func (a All) Equals(other any) bool { if typed, ok := other.(All); ok { return a.quantifier.Equals(typed.quantifier) @@ -158,14 +150,6 @@ func MakeExSimple(vars Lib.List[TypedVar], forms Form, metas Lib.Set[Meta]) Ex { return Ex{makeQuantifier(vars, forms, metas, ConnEx)} } -func MakeEx(vars Lib.List[TypedVar], forms Form) Ex { - return MakeExSimple(vars, forms, Lib.EmptySet[Meta]()) -} - -func MakerEx(vars Lib.List[TypedVar], forms Form) Ex { - return MakeEx(vars, forms) -} - func (e Ex) Equals(other any) bool { if typed, ok := other.(Ex); ok { return e.quantifier.Equals(typed.quantifier) @@ -230,14 +214,6 @@ func MakeOrSimple(forms Lib.List[Form], metas Lib.Set[Meta]) Or { return Or{forms, Lib.MkCache(metas, Or.forceGetMetas)} } -func MakeOr(forms Lib.List[Form]) Or { - return MakeOrSimple(forms, Lib.EmptySet[Meta]()) -} - -func MakerOr(forms Lib.List[Form]) Or { - return MakeOr(forms) -} - /** Methods **/ /** - Form interface Methods **/ @@ -359,23 +335,11 @@ func MakeAndSimpleBinary(forms Lib.List[Form], metas Lib.Set[Meta]) And { return MakeAndSimple(forms, metas) default: return MakeAndSimple( - Lib.MkListV[Form](forms.At(0), MakerAnd(forms.Slice(1, forms.Len()), true)), + Lib.MkListV[Form](forms.At(0), MakeAnd(forms.Slice(1, forms.Len()), true)), metas) } } -func MakeAnd(forms Lib.List[Form], binary ...bool) And { - if binary != nil { - return MakeAndSimpleBinary(forms, Lib.EmptySet[Meta]()) - } else { - return MakeAndSimple(forms, Lib.EmptySet[Meta]()) - } -} - -func MakerAnd(forms Lib.List[Form], binary ...bool) And { - return MakeAnd(forms, binary...) -} - /** Methods **/ /** - Form interface Methods **/ @@ -495,14 +459,6 @@ func MakeEquSimple(firstForm, secondForm Form, metas Lib.Set[Meta]) Equ { } } -func MakeEqu(firstForm, secondForm Form) Equ { - return MakeEquSimple(firstForm, secondForm, Lib.EmptySet[Meta]()) -} - -func MakerEqu(firstForm, secondForm Form) Equ { - return MakeEqu(firstForm, secondForm) -} - func (e Equ) GetF1() Form { return e.f1.Copy() } func (e Equ) GetF2() Form { return e.f2.Copy() } func (e Equ) Copy() Form { @@ -620,14 +576,6 @@ func MakeImpSimple(firstForm, secondForm Form, metas Lib.Set[Meta]) Imp { } } -func MakeImp(firstForm, secondForm Form) Imp { - return MakeImpSimple(firstForm, secondForm, Lib.EmptySet[Meta]()) -} - -func MakerImp(firstForm, secondForm Form) Imp { - return MakeImp(firstForm, secondForm) -} - func (i Imp) GetF1() Form { return i.f1.Copy() } func (i Imp) GetF2() Form { return i.f2.Copy() } func (i Imp) Copy() Form { @@ -746,14 +694,6 @@ func MakeNotSimple(form Form, metas Lib.Set[Meta]) Not { return Not{form, Lib.MkCache(metas, Not.forceGetMetas)} } -func MakeNot(form Form) Not { - return MakeNotSimple(form, Lib.EmptySet[Meta]()) -} - -func MakerNot(form Form) Not { - return MakeNot(form) -} - /** Methods **/ /** - Form interface Methods **/ @@ -855,7 +795,7 @@ func SimplifyNegations(form Form) Form { form, isEven := getDeepFormWithoutNot(form, true) if !isEven { - form = MakerNot(form) + form = MakeNot(form) } return form @@ -907,27 +847,6 @@ func MakePredSimple( } } -func MakePred( - id Id, - tys Lib.List[Ty], - terms Lib.List[Term], -) Pred { - return MakePredSimple( - id, - tys, - terms, - Lib.EmptySet[Meta](), - ) -} - -func MakerPred( - id Id, - tys Lib.List[Ty], - terms Lib.List[Term], -) Pred { - return MakePred(id, tys, terms) -} - /* Pred attributes getters */ func (p Pred) GetID() Id { return p.id.Copy().(Id) } @@ -1117,14 +1036,6 @@ func (p Pred) Less(oth any) bool { type Top struct { } -func MakeTop() Top { - return Top{} -} - -func MakerTop() Top { - return MakeTop() -} - func (Top) ToString() string { return printer.StrConn(ConnTop) } func (t Top) Copy() Form { return MakeTop() } func (Top) Equals(f any) bool { _, isTop := f.(Top); return isTop } @@ -1155,14 +1066,6 @@ func (t Top) Less(oth any) bool { type Bot struct { } -func MakeBot() Bot { - return Bot{} -} - -func MakerBot() Bot { - return MakeBot() -} - func (Bot) ToString() string { return printer.StrConn(ConnBot) } func (b Bot) Copy() Form { return MakeBot() } func (Bot) Equals(f any) bool { _, isBot := f.(Bot); return isBot } diff --git a/src/AST/formula.go b/src/AST/formula.go index 9ab5b3cf..ea2a3e1f 100644 --- a/src/AST/formula.go +++ b/src/AST/formula.go @@ -85,7 +85,7 @@ func replaceTermInTermList( oldTerm, newTerm, ) - newTermList.Upd(i, MakerFun( + newTermList.Upd(i, MakeFun( nf.GetID(), nf.GetTyArgs(), termList, diff --git a/src/AST/maker.go b/src/AST/maker.go index 5893654a..f8fcf0c0 100644 --- a/src/AST/maker.go +++ b/src/AST/maker.go @@ -62,8 +62,8 @@ var EmptyPredEq Pred /* Initialization */ func Init() { Reset() - Id_eq = MakerId("=") - EmptyPredEq = MakerPred(Id_eq, Lib.NewList[Ty](), Lib.NewList[Term]()) + Id_eq = MakeId("=") + EmptyPredEq = MakePred(Id_eq, Lib.NewList[Ty](), Lib.NewList[Term]()) initPrinters() initTPTPNativeTypes() } @@ -79,20 +79,76 @@ func ResetMeta() { occurenceMeta = map[string]int{} } -/* ID maker */ -// Deprecated: use MakeId instead -func MakerId(s string) Id { - return MakeId(s) +// Formulas makers + +func MakeAll(vars Lib.List[TypedVar], forms Form) All { + return MakeAllSimple(vars, forms, Lib.EmptySet[Meta]()) +} + +func MakeEx(vars Lib.List[TypedVar], forms Form) Ex { + return MakeExSimple(vars, forms, Lib.EmptySet[Meta]()) +} + +func MakeOr(forms Lib.List[Form]) Or { + return MakeOrSimple(forms, Lib.EmptySet[Meta]()) +} + +func MakeAnd(forms Lib.List[Form], binary ...bool) And { + if binary != nil { + return MakeAndSimpleBinary(forms, Lib.EmptySet[Meta]()) + } else { + return MakeAndSimple(forms, Lib.EmptySet[Meta]()) + } +} + +func MakeEqu(firstForm, secondForm Form) Equ { + return MakeEquSimple(firstForm, secondForm, Lib.EmptySet[Meta]()) +} + +func MakeImp(firstForm, secondForm Form) Imp { + return MakeImpSimple(firstForm, secondForm, Lib.EmptySet[Meta]()) +} + +func MakeNot(form Form) Not { + return MakeNotSimple(form, Lib.EmptySet[Meta]()) } -/* Var maker */ -// Deprecated: use MakeVar instead -func MakerVar(s string) Var { - return MakeVar(s) +func MakePred( + id Id, + tys Lib.List[Ty], + terms Lib.List[Term], +) Pred { + return MakePredSimple( + id, + tys, + terms, + Lib.EmptySet[Meta](), + ) } -/* Meta maker */ -func MakerMeta(s string, formula int, ty Ty) Meta { +func MakeTop() Top { + return Top{} +} + +func MakeBot() Bot { + return Bot{} +} + +// Terms makers + +func MakeId(s string) Id { + return Id{s} +} + +func MakeQuotedId(s string) Id { + return Id{"" + s + "'"} +} + +func MakeVar(s string) Var { + return Var{s} +} + +func MakeMeta(s string, f int, ty Ty) Meta { lock_term.Lock() new_id := meta_id meta_id++ @@ -102,21 +158,24 @@ func MakerMeta(s string, formula int, ty Ty) Meta { lock_term.Lock() occurenceMeta[s] = i + 1 lock_term.Unlock() - return MakeMeta(new_id, i, fmt.Sprintf("%s%d", s, new_id), formula, ty) + return Meta{new_id, i, fmt.Sprintf("%s%d", s, new_id), f, ty} } else { lock_term.Lock() occurenceMeta[s] = 1 lock_term.Unlock() - return MakeMeta(new_id, 0, fmt.Sprintf("%s%d", s, new_id), formula, ty) + return Meta{new_id, 0, fmt.Sprintf("%s%d", s, new_id), f, ty} } } -/* Const maker (given a id, create a fun without args) */ -func MakerConst(id Id) Fun { - return MakeFun(id, Lib.NewList[Ty](), Lib.NewList[Term](), Lib.EmptySet[Meta]()) +func MakeFunSimple(p Id, ty_args Lib.List[Ty], args Lib.List[Term], metas Lib.Set[Meta]) Fun { + return Fun{p, ty_args, args, Lib.MkCache(metas, Fun.forceGetMetas)} } -/* Fun maker, with given id and args */ -func MakerFun(id Id, ty_args Lib.List[Ty], terms Lib.List[Term]) Fun { - return MakeFun(id, ty_args, terms, Lib.EmptySet[Meta]()) +func MakeFun(p Id, ty_args Lib.List[Ty], args Lib.List[Term]) Fun { + return MakeFunSimple(p, ty_args, args, Lib.EmptySet[Meta]()) +} + +/* Const maker (given a id, create a fun without args) */ +func MakeConst(id Id) Fun { + return MakeFun(id, Lib.NewList[Ty](), Lib.NewList[Term]()) } diff --git a/src/AST/quantifiers.go b/src/AST/quantifiers.go index da324069..1e6d4b41 100644 --- a/src/AST/quantifiers.go +++ b/src/AST/quantifiers.go @@ -157,7 +157,7 @@ func (q quantifier) renameVariables() quantifier { newTyBv := Lib.NewList[Lib.Pair[TyBound, Ty]]() for _, v := range q.GetVarList().GetSlice() { - newVar := MakerVar(v.GetName()) + newVar := MakeVar(v.GetName()) newVarList.Append(MkTypedVar(newVar.name, v.ty)) f, replaced := newForm.ReplaceTermByTerm(v.ToBoundVar(), newVar) if !replaced { diff --git a/src/AST/term.go b/src/AST/term.go index 6087336a..80ff05b8 100644 --- a/src/AST/term.go +++ b/src/AST/term.go @@ -59,27 +59,6 @@ type Term interface { Less(any) bool } -/*** Makers ***/ -func MakeId(s string) Id { - return Id{s} -} - -func MakeQuotedId(s string) Id { - return Id{"" + s + "'"} -} - -func MakeVar(s string) Var { - return Var{s} -} - -func MakeMeta(index, occurence int, s string, f int, ty Ty) Meta { - return Meta{index, occurence, s, f, ty} -} - -func MakeFun(p Id, ty_args Lib.List[Ty], args Lib.List[Term], metas Lib.Set[Meta]) Fun { - return Fun{p, ty_args, args, Lib.MkCache(metas, Fun.forceGetMetas)} -} - /*** Functions **/ func TermEquals(x, y Term) bool { diff --git a/src/AST/terms-def.go b/src/AST/terms-def.go index 71c2af4e..4c36194a 100644 --- a/src/AST/terms-def.go +++ b/src/AST/terms-def.go @@ -144,11 +144,11 @@ func (f Fun) Equals(t any) bool { } func (f Fun) Copy() Term { - return MakeFun(f.GetP(), Lib.ListCpy(f.GetTyArgs()), Lib.ListCpy(f.GetArgs()), f.metas.Raw()) + return MakeFunSimple(f.GetP(), Lib.ListCpy(f.GetTyArgs()), Lib.ListCpy(f.GetArgs()), f.metas.Raw()) } func (f Fun) PointerCopy() *Fun { - nf := MakeFun(f.GetP(), f.GetTyArgs(), f.GetArgs(), f.metas.Raw()) + nf := MakeFunSimple(f.GetP(), f.GetTyArgs(), f.GetArgs(), f.metas.Raw()) return &nf } @@ -186,7 +186,7 @@ func (f Fun) ReplaceSubTermBy(oldTerm, newTerm Term) Term { return newTerm.Copy() } else { tl, res := replaceFirstOccurrenceTermList(f.GetArgs(), oldTerm, newTerm) - nf := MakeFun(f.GetID(), f.GetTyArgs(), tl, f.metas.Raw()) + nf := MakeFunSimple(f.GetID(), f.GetTyArgs(), tl, f.metas.Raw()) if !res && !f.metas.NeedsUpd() { nf.metas.AvoidUpd() } @@ -203,7 +203,7 @@ func (f Fun) SubstTy(old TyGenVar, new Ty) Term { f.args, func(t Term) Term { return t.SubstTy(old, new) }, ) - return MakeFun( + return MakeFunSimple( f.GetID(), typed_args, args, @@ -216,7 +216,7 @@ func (f Fun) ReplaceAllSubTerm(oldTerm, newTerm Term) Term { return newTerm.Copy() } else { tl, res := ReplaceOccurrence(f.GetArgs(), oldTerm, newTerm) - nf := MakeFun(f.GetID(), f.GetTyArgs(), tl, f.metas.Raw()) + nf := MakeFunSimple(f.GetID(), f.GetTyArgs(), tl, f.metas.Raw()) if !res && !f.metas.NeedsUpd() { nf.metas.AvoidUpd() } @@ -348,7 +348,7 @@ func (m Meta) Equals(t any) bool { } func (m Meta) Copy() Term { - return MakeMeta(m.index, m.GetOccurence(), m.GetName(), m.GetFormula(), m.GetTy()) + return Meta{m.index, m.GetOccurence(), m.GetName(), m.GetFormula(), m.GetTy()} } func (m Meta) ReplaceSubTermBy(original_term, new_term Term) Term { @@ -385,7 +385,7 @@ func (m Meta) Less(u any) bool { } func MakeEmptyMeta() Meta { - return MakeMeta(-1, -1, "-1", -1, TIndividual()) + return Meta{-1, -1, "-1", -1, TIndividual()} } func MetaEquals(x, y Meta) bool { diff --git a/src/AST/ty-syntax.go b/src/AST/ty-syntax.go index e21dd3e3..352c38aa 100644 --- a/src/AST/ty-syntax.go +++ b/src/AST/ty-syntax.go @@ -126,7 +126,7 @@ func (m TyMeta) SubstTy(v TyGenVar, new Ty) Ty { return m } -func (m TyMeta) ToTermMeta() Meta { return MakeMeta(m.index, 0, m.name, m.formula, tType) } +func (m TyMeta) ToTermMeta() Meta { return Meta{m.index, 0, m.name, m.formula, tType} } func TyMetaFromMeta(m Meta) TyMeta { return TyMeta{ @@ -453,8 +453,8 @@ func TyToTerm(ty Ty) Term { case TyMeta: return nty.ToTermMeta() case TyConstr: - return MakerFun( - MakerId(nty.symbol), + return MakeFun( + MakeId(nty.symbol), Lib.NewList[Ty](), Lib.ListMap(nty.args, TyToTerm), ) diff --git a/src/Core/Sko/inner-skolemization.go b/src/Core/Sko/inner-skolemization.go index 3f8d43d0..b9794ac2 100644 --- a/src/Core/Sko/inner-skolemization.go +++ b/src/Core/Sko/inner-skolemization.go @@ -68,7 +68,7 @@ func (sko InnerSkolemization) Skolemize( internalMetas := form.GetMetas().Elements() - skolemFunc := AST.MakerFun( + skolemFunc := AST.MakeFun( symbol, Lib.NewList[AST.Ty](), Lib.ListMap(internalMetas, Glob.To[AST.Term]), diff --git a/src/Core/Sko/interface.go b/src/Core/Sko/interface.go index f2e92c7c..a9b3ebfc 100644 --- a/src/Core/Sko/interface.go +++ b/src/Core/Sko/interface.go @@ -61,7 +61,7 @@ type Skolemization interface { * a fresh symbol for sure. Otherwise, nothing is guaranteed. */ func genFreshSymbol(existingSymbols *Lib.Set[AST.Id]) AST.Id { - symbol := AST.MakerId( + symbol := AST.MakeId( fmt.Sprintf("skolem@%d", existingSymbols.Cardinal()), ) *existingSymbols = existingSymbols.Add(symbol) diff --git a/src/Core/Sko/outer-skolemization.go b/src/Core/Sko/outer-skolemization.go index c4bc2abf..1d8a062a 100644 --- a/src/Core/Sko/outer-skolemization.go +++ b/src/Core/Sko/outer-skolemization.go @@ -68,7 +68,7 @@ func (sko OuterSkolemization) Skolemize( metas := fvs.Elements() - skolemFunc := AST.MakerFun( + skolemFunc := AST.MakeFun( symbol, Lib.NewList[AST.Ty](), Lib.ListMap(metas, Glob.To[AST.Term]), diff --git a/src/Core/Sko/preinner-skolemization.go b/src/Core/Sko/preinner-skolemization.go index 9944a7d6..c343f711 100644 --- a/src/Core/Sko/preinner-skolemization.go +++ b/src/Core/Sko/preinner-skolemization.go @@ -71,7 +71,7 @@ func (sko PreInnerSkolemization) Skolemize( sko.mu.Lock() if val, ok := sko.linkedSymbols.Find( func(p Glob.Pair[AST.Form, AST.Id]) bool { return p.Fst.Equals(realDelta) }, - Glob.MakePair(Glob.To[AST.Form](AST.MakerBot()), AST.MakeId("")), + Glob.MakePair(Glob.To[AST.Form](AST.MakeBot()), AST.MakeId("")), ); ok { symbol = val.Snd } else { @@ -82,7 +82,7 @@ func (sko PreInnerSkolemization) Skolemize( internalMetas := form.GetMetas().Elements() - skolemFunc := AST.MakerFun( + skolemFunc := AST.MakeFun( symbol, Lib.NewList[AST.Ty](), Lib.ListMap(internalMetas, Glob.To[AST.Term]), @@ -193,7 +193,7 @@ func alphaConvertTerm(t AST.Term, substitution map[string]AST.Var) AST.Term { func(trm AST.Term) AST.Term { return alphaConvertTerm(trm, substitution) }) - return AST.MakerFun( + return AST.MakeFun( nt.GetID(), nt.GetTyArgs(), mappedTerms, diff --git a/src/Core/instanciation.go b/src/Core/instanciation.go index 4b1373b3..2ea05de8 100644 --- a/src/Core/instanciation.go +++ b/src/Core/instanciation.go @@ -86,7 +86,7 @@ func RealInstantiate( subForm = subForm.SubstTy(v.ToTyBoundVar(), meta) m = Lib.MkNone[AST.Meta]() } else { - meta := AST.MakerMeta(strings.ToUpper(v.GetName()), index, v.GetTy()) + meta := AST.MakeMeta(strings.ToUpper(v.GetName()), index, v.GetTy()) subForm = subForm.SubstituteVarByMeta(v.ToBoundVar(), meta) terms = terms.Copy(AST.Term.Copy) terms.Add( @@ -98,14 +98,14 @@ func RealInstantiate( if varList.Len() > 1 { if status == is_exists { - ex := AST.MakerEx(varList.Slice(1, varList.Len()), subForm) - subForm = AST.MakerNot(ex) + ex := AST.MakeEx(varList.Slice(1, varList.Len()), subForm) + subForm = AST.MakeNot(ex) } else { - subForm = AST.MakerAll(varList.Slice(1, varList.Len()), subForm) + subForm = AST.MakeAll(varList.Slice(1, varList.Len()), subForm) } } else { if status == is_exists { - subForm = AST.MakerNot(subForm) + subForm = AST.MakeNot(subForm) } } diff --git a/src/Core/skolemisation.go b/src/Core/skolemisation.go index 66a7341c..0949b8bc 100644 --- a/src/Core/skolemisation.go +++ b/src/Core/skolemisation.go @@ -133,7 +133,7 @@ func realSkolemize( if AST.IsTType(x.GetTy()) { ty_mutex.Lock() - id := AST.MakerId(fmt.Sprintf("skoTy@%d", ty_index)) + id := AST.MakeId(fmt.Sprintf("skoTy@%d", ty_index)) ty_index++ ty_mutex.Unlock() res = deltaForm.SubstTy(x.ToTyBoundVar(), AST.MkTyConst(id.ToString())) @@ -149,12 +149,12 @@ func realSkolemize( switch typ { case isNegAll: if allVars.Len() > 1 { - res = AST.MakerAll(allVars.Slice(1, allVars.Len()), res) + res = AST.MakeAll(allVars.Slice(1, allVars.Len()), res) } - res = AST.MakerNot(res) + res = AST.MakeNot(res) case isExists: if allVars.Len() > 1 { - res = AST.MakerEx(allVars.Slice(1, allVars.Len()), res) + res = AST.MakeEx(allVars.Slice(1, allVars.Len()), res) } default: Glob.Anomaly("Skolemization", "impossible reconstruction case") diff --git a/src/Core/substitutions_search.go b/src/Core/substitutions_search.go index b241d6c5..709ae16f 100644 --- a/src/Core/substitutions_search.go +++ b/src/Core/substitutions_search.go @@ -240,7 +240,7 @@ func ApplySubstitutionOnTerm(old_symbol AST.Meta, new_symbol, t AST.Term) AST.Te res = new_symbol.Copy() } case AST.Fun: - res = AST.MakerFun( + res = AST.MakeFun( nf.GetP(), nf.GetTyArgs(), ApplySubstitutionOnTermList(old_symbol, new_symbol, nf.GetArgs()), diff --git a/src/Engine/syntax-translation.go b/src/Engine/syntax-translation.go index 62cd659a..e1158d11 100644 --- a/src/Engine/syntax-translation.go +++ b/src/Engine/syntax-translation.go @@ -161,9 +161,9 @@ func elaborateForm(con Context, f, source_form Parser.PForm) (Context, AST.Form, case Parser.PConst: switch pform.PConstant { case Parser.PTop: - return con, AST.MakerTop(), false + return con, AST.MakeTop(), false case Parser.PBot: - return con, AST.MakerBot(), false + return con, AST.MakeBot(), false } case Parser.PPred: @@ -188,8 +188,8 @@ func elaborateForm(con Context, f, source_form Parser.PForm) (Context, AST.Form, is_typed = !typed_args.Empty() } - return con, AST.MakerPred( - AST.MakerId(pform.Symbol()), + return con, AST.MakePred( + AST.MakeId(pform.Symbol()), Lib.ListMap( typed_args, func(pty Parser.PType) AST.Ty { @@ -202,7 +202,7 @@ func elaborateForm(con Context, f, source_form Parser.PForm) (Context, AST.Form, switch pform.PUnaryOp { case Parser.PUnaryNeg: new_con, nf, b := elaborateForm(con, pform.PForm, source_form) - return new_con, AST.MakerNot(nf), b + return new_con, AST.MakeNot(nf), b } case Parser.PBin: @@ -214,11 +214,11 @@ func elaborateForm(con Context, f, source_form Parser.PForm) (Context, AST.Form, case Parser.PBinaryImp: con1, lft, b1 := elaborateForm(con, pform.Left(), source_form) new_con, rgt, b2 := elaborateForm(con1, pform.Right(), source_form) - return new_con, AST.MakerImp(lft, rgt), b1 || b2 + return new_con, AST.MakeImp(lft, rgt), b1 || b2 case Parser.PBinaryEqu: con1, lft, b1 := elaborateForm(con, pform.Left(), source_form) new_con, rgt, b2 := elaborateForm(con1, pform.Right(), source_form) - return new_con, AST.MakerEqu(lft, rgt), b1 || b2 + return new_con, AST.MakeEqu(lft, rgt), b1 || b2 } case Parser.PQuant: @@ -233,7 +233,7 @@ func elaborateForm(con Context, f, source_form Parser.PForm) (Context, AST.Form, ) new_con, form, b := elaborateForm(append(con, actualVars.GetSlice()...), pform.PForm, source_form) if !vars.Empty() { - form = AST.MakerAll(vars, form) + form = AST.MakeAll(vars, form) } return new_con, form, b @@ -252,7 +252,7 @@ func elaborateForm(con Context, f, source_form Parser.PForm) (Context, AST.Form, ) new_con, form, b := elaborateForm(append(con, actualVars.GetSlice()...), pform.PForm, source_form) if !vars.Empty() { - form = AST.MakerEx(vars, form) + form = AST.MakeEx(vars, form) } return new_con, form, b } @@ -267,7 +267,7 @@ func elaborateForm(con Context, f, source_form Parser.PForm) (Context, AST.Form, func maybeFlattenOr(con Context, f Parser.PBin, source_form Parser.PForm) (Context, AST.Form, bool) { return maybeFlattenBin( con, f, source_form, - func(ls Lib.List[AST.Form]) AST.Form { return AST.MakerOr(ls) }, + func(ls Lib.List[AST.Form]) AST.Form { return AST.MakeOr(ls) }, Parser.PBinaryOr, ) } @@ -275,7 +275,7 @@ func maybeFlattenOr(con Context, f Parser.PBin, source_form Parser.PForm) (Conte func maybeFlattenAnd(con Context, f Parser.PBin, source_form Parser.PForm) (Context, AST.Form, bool) { return maybeFlattenBin( con, f, source_form, - func(ls Lib.List[AST.Form]) AST.Form { return AST.MakerAnd(ls) }, + func(ls Lib.List[AST.Form]) AST.Form { return AST.MakeAnd(ls) }, Parser.PBinaryAnd, ) } @@ -329,7 +329,7 @@ func elaborateTerm(con Context, t, source_term Parser.PTerm) (Context, AST.Term, switch pterm := t.(type) { case Parser.PVar: - return con, AST.MakerVar(pterm.Name()), false + return con, AST.MakeVar(pterm.Name()), false case Parser.PFun: typed_arguments := pretype(con, pterm.Args()) @@ -353,8 +353,8 @@ func elaborateTerm(con Context, t, source_term Parser.PTerm) (Context, AST.Term, is_typed = !typed_args.Empty() } - fun := AST.MakerFun( - AST.MakerId(pterm.Symbol()), + fun := AST.MakeFun( + AST.MakeId(pterm.Symbol()), Lib.ListMap( typed_args, func(pty Parser.PType) AST.Ty { @@ -384,7 +384,7 @@ func elaborateTerm(con Context, t, source_term Parser.PTerm) (Context, AST.Term, func elaborateParsingType(pty Lib.Pair[string, Parser.PType]) Core.TFFAtomTyping { return Core.TFFAtomTyping{ - Literal: AST.MakerId(pty.Fst), + Literal: AST.MakeId(pty.Fst), Ty: elaborateType(pty.Snd, pty.Snd, true), } } diff --git a/src/Mods/CertifUtils/utils.go b/src/Mods/CertifUtils/utils.go index d3e8442e..e5b2b072 100644 --- a/src/Mods/CertifUtils/utils.go +++ b/src/Mods/CertifUtils/utils.go @@ -68,7 +68,7 @@ func GetTargetFormIndex(applied_on AST.Form, hypotheses Lib.List[AST.Form]) int case Lib.Some[int]: return t.Val case Lib.None[int]: - if !IsPredEqual(applied_on) && !applied_on.Equals(AST.MakerTop()) { + if !IsPredEqual(applied_on) && !applied_on.Equals(AST.MakeTop()) { Glob.Anomaly( "certif-utils", fmt.Sprintf("index of %s not found in { %s }", applied_on.ToString(), Lib.ListToString(hypotheses, " ;; ", "")), diff --git a/src/Mods/desko/proof.go b/src/Mods/desko/proof.go index 14100f80..7cd16d26 100644 --- a/src/Mods/desko/proof.go +++ b/src/Mods/desko/proof.go @@ -266,7 +266,7 @@ func desko_inner( } } for _, delayed := range term_delayed_weakening { - node = gen_weaken(node, delayed, AST.MakerTop()) + node = gen_weaken(node, delayed, AST.MakeTop()) } debug( diff --git a/src/Mods/dmt/axiom_registration.go b/src/Mods/dmt/axiom_registration.go index 9bcbc094..03d4bb79 100644 --- a/src/Mods/dmt/axiom_registration.go +++ b/src/Mods/dmt/axiom_registration.go @@ -102,7 +102,7 @@ func printDebugRewriteRule(polarity bool, axiom, cons AST.Form) { if polarity { ax, co = axiom.ToString(), cons.ToString() } else { - ax, co = AST.MakerNot(axiom).ToString(), cons.ToString() + ax, co = AST.MakeNot(axiom).ToString(), cons.ToString() } debug( Lib.MkLazy(func() string { return fmt.Sprintf("Rewrite rule: %s ---> %s\n", ax, co) }), @@ -134,8 +134,8 @@ func makeRewriteRuleFromAtomic(atomic AST.Form) bool { } func makeRewriteRuleFromPred(pred AST.Pred) bool { - addPosRewriteRule(pred, AST.MakerTop()) - addNegRewriteRule(pred, AST.MakerNot(AST.MakerTop())) + addPosRewriteRule(pred, AST.MakeTop()) + addNegRewriteRule(pred, AST.MakeNot(AST.MakeTop())) return true } @@ -143,8 +143,8 @@ func makeRewriteRuleFromNegatedAtom(atom AST.Not) bool { if isEquality(atom.GetForm().(AST.Pred)) { return false } - addNegRewriteRule(atom, AST.MakerNot(AST.MakerBot())) - addPosRewriteRule(atom, AST.MakerBot()) + addNegRewriteRule(atom, AST.MakeNot(AST.MakeBot())) + addPosRewriteRule(atom, AST.MakeBot()) return true } @@ -202,11 +202,11 @@ func addEquRewriteRuleIfNotEquality(f1, f2 AST.Form) bool { func addEquivalenceRewriteRule(axiom, cons AST.Form) { if Glob.Is[AST.Not](axiom) { - addPosRewriteRule(axiom, AST.MakerNot(cons)) + addPosRewriteRule(axiom, AST.MakeNot(cons)) addNegRewriteRule(axiom, cons) } else { addPosRewriteRule(axiom, cons) - addNegRewriteRule(axiom, AST.MakerNot(cons)) + addNegRewriteRule(axiom, AST.MakeNot(cons)) } } @@ -241,9 +241,9 @@ func makeRewriteRuleFromImplication(impForm AST.Imp) bool { // an equality atom on the right-side of the formula. if isAtomic(phi2) && !isEqualityPred(phi2) { if Glob.Is[AST.Pred](phi2) { - addNegRewriteRule(phi2, AST.MakerNot(phi1)) + addNegRewriteRule(phi2, AST.MakeNot(phi1)) } else { - addPosRewriteRule(predFromNegatedAtom(phi2), AST.MakerNot(phi1)) + addPosRewriteRule(predFromNegatedAtom(phi2), AST.MakeNot(phi1)) } } diff --git a/src/Mods/dmt/rewrite.go b/src/Mods/dmt/rewrite.go index 4663eefe..098f84db 100644 --- a/src/Mods/dmt/rewrite.go +++ b/src/Mods/dmt/rewrite.go @@ -223,7 +223,7 @@ func insert( list Lib.List[AST.Form], unif Unif.MatchingSubstitutions, ) []Unif.MatchingSubstitutions { - if Lib.ListMem(AST.MakerTop().Copy(), list) || Lib.ListMem(AST.MakerBot().Copy(), list) { + if Lib.ListMem(AST.MakeTop().Copy(), list) || Lib.ListMem(AST.MakeBot().Copy(), list) { sortedUnifs = insertFirst(sortedUnifs, unif) } else { sortedUnifs = append(sortedUnifs, unif) diff --git a/src/Mods/equality/bse/equality_problem_list.go b/src/Mods/equality/bse/equality_problem_list.go index fce98743..8bbe0787 100644 --- a/src/Mods/equality/bse/equality_problem_list.go +++ b/src/Mods/equality/bse/equality_problem_list.go @@ -220,10 +220,10 @@ func buildEqualityProblemMultiListFromPredList(pred AST.Pred, tn Unif.DataStruct } for i, arg := range pred.GetArgs().GetSlice() { - metas = Lib.ListAdd(metas, AST.MakerMeta("METAEQ_"+arg.ToString(), -1, tys.At(i))) + metas = Lib.ListAdd(metas, AST.MakeMeta("METAEQ_"+arg.ToString(), -1, tys.At(i))) } - newTerm := AST.MakerPred( + newTerm := AST.MakePred( predId.Copy().(AST.Id), pred.GetTyArgs(), AST.MetaListToTermList(metas), diff --git a/src/Mods/equality/bse/equality_types.go b/src/Mods/equality/bse/equality_types.go index 71e47682..98e75a7a 100644 --- a/src/Mods/equality/bse/equality_types.go +++ b/src/Mods/equality/bse/equality_types.go @@ -121,10 +121,10 @@ func (equs Equalities) removeHalf() Equalities { func retrieveEqualities(dt Unif.DataStructure) Equalities { res := Equalities{} meta_ty := AST.MkTyMeta("META_TY_EQ", -1) - MetaEQ1 := AST.MakerMeta("METAEQ1", -1, meta_ty) - MetaEQ2 := AST.MakerMeta("METAEQ2", -1, meta_ty) + MetaEQ1 := AST.MakeMeta("METAEQ1", -1, meta_ty) + MetaEQ2 := AST.MakeMeta("METAEQ2", -1, meta_ty) - eq_pred := AST.MakerPred(AST.Id_eq, Lib.NewList[AST.Ty](), Lib.NewList[AST.Term]()) + eq_pred := AST.MakePred(AST.Id_eq, Lib.NewList[AST.Ty](), Lib.NewList[AST.Term]()) eq_pred = AST.MakePred( AST.Id_eq, Lib.MkListV[AST.Ty](meta_ty), @@ -151,10 +151,10 @@ func retrieveEqualities(dt Unif.DataStructure) Equalities { func retrieveInequalities(dt Unif.DataStructure) Inequalities { res := Inequalities{} meta_ty := AST.MkTyMeta("META_TY_NEQ", -1) - MetaNEQ1 := AST.MakerMeta("META_NEQ_1", -1, meta_ty) - MetaNEQ2 := AST.MakerMeta("META_NEQ_2", -1, meta_ty) + MetaNEQ1 := AST.MakeMeta("META_NEQ_1", -1, meta_ty) + MetaNEQ2 := AST.MakeMeta("META_NEQ_2", -1, meta_ty) - neq_pred := AST.MakerPred(AST.Id_eq, Lib.NewList[AST.Ty](), Lib.NewList[AST.Term]()) + neq_pred := AST.MakePred(AST.Id_eq, Lib.NewList[AST.Ty](), Lib.NewList[AST.Term]()) neq_pred = AST.MakePred( AST.Id_eq, Lib.MkListV(meta_ty), diff --git a/src/Mods/equality/sateq/subsgatherer.go b/src/Mods/equality/sateq/subsgatherer.go index 41b30cff..26e9907c 100644 --- a/src/Mods/equality/sateq/subsgatherer.go +++ b/src/Mods/equality/sateq/subsgatherer.go @@ -83,7 +83,7 @@ func translate(toTranslate *eqClass, correspondence map[*eqClass]*termRecord) AS for i, s := range tr.args { args.Upd(i, translate(s, correspondence)) } - return AST.MakerFun(tr.symbolId, tr.tyArgs, args) + return AST.MakeFun(tr.symbolId, tr.tyArgs, args) } } diff --git a/src/Mods/lambdapi/context.go b/src/Mods/lambdapi/context.go index 25b5c368..fa7cb638 100644 --- a/src/Mods/lambdapi/context.go +++ b/src/Mods/lambdapi/context.go @@ -47,7 +47,7 @@ func makeContextIfNeeded(root AST.Form, metaList Lib.List[AST.Meta]) string { if Glob.IsLoaded("dmt") { registeredAxioms := dmt.GetRegisteredAxioms() registeredAxioms.Append(root) - root = AST.MakerAnd(registeredAxioms) + root = AST.MakeAnd(registeredAxioms) } // if AST.EmptyGlobalContext() { diff --git a/src/Mods/lambdapi/proof.go b/src/Mods/lambdapi/proof.go index 3455ae4b..8cdbb936 100644 --- a/src/Mods/lambdapi/proof.go +++ b/src/Mods/lambdapi/proof.go @@ -143,7 +143,7 @@ func getPosAndNeg(target AST.Form) (pos, neg AST.Form) { if neg, ok := target.(AST.Not); ok { return neg.GetForm(), neg } - return target, AST.MakerNot(target) + return target, AST.MakeNot(target) } func refineGenericRule( @@ -311,14 +311,14 @@ func getFormattedChild(form AST.Form) string { case AST.All: return format(nf.GetVarList(), nf.GetForm(), func(vl Lib.List[AST.TypedVar], f AST.Form) AST.Form { if !vl.Empty() { - f = AST.MakerAll(vl, f) + f = AST.MakeAll(vl, f) } return f }) case AST.Ex: return format(nf.GetVarList(), nf.GetForm(), func(vl Lib.List[AST.TypedVar], f AST.Form) AST.Form { if !vl.Empty() { - f = AST.MakerEx(vl, f) + f = AST.MakeEx(vl, f) } return f }) @@ -326,14 +326,14 @@ func getFormattedChild(form AST.Form) string { case AST.All: return format(f.GetVarList(), f.GetForm(), func(vl Lib.List[AST.TypedVar], f AST.Form) AST.Form { if !vl.Empty() { - f = AST.MakerAll(vl, f) + f = AST.MakeAll(vl, f) } return f }) case AST.Ex: return format(f.GetVarList(), f.GetForm(), func(vl Lib.List[AST.TypedVar], f AST.Form) AST.Form { if !vl.Empty() { - f = AST.MakerEx(vl, f) + f = AST.MakeEx(vl, f) } return f }) @@ -421,7 +421,7 @@ func processMainFormula(form AST.Form) (Lib.List[AST.Form], AST.Form) { func makeTheorem(axioms Lib.List[AST.Form], conjecture AST.Form) (string, Lib.List[AST.Form]) { problemName := CertifUtils.SanitizedTheoremName() axioms = Lib.ListCpy(axioms) - axioms.Append(AST.MakerNot(conjecture)) + axioms.Append(AST.MakeNot(conjecture)) formattedProblem := makeImpChain(axioms) return "symbol goeland_" + problemName + " : \n" + formattedProblem + " → ϵ ⊥ ≔ \n", axioms } diff --git a/src/Mods/rocq/context.go b/src/Mods/rocq/context.go index 6a6fbd39..96d31df7 100644 --- a/src/Mods/rocq/context.go +++ b/src/Mods/rocq/context.go @@ -57,7 +57,7 @@ func makeContextIfNeeded(root AST.Form, metaList Lib.List[AST.Meta]) string { if Glob.IsLoaded("dmt") { registeredAxioms := dmt.GetRegisteredAxioms() registeredAxioms.Append(root) - root = AST.MakerAnd(registeredAxioms) + root = AST.MakeAnd(registeredAxioms) } // if AST.EmptyGlobalContext() { diff --git a/src/Mods/rocq/proof.go b/src/Mods/rocq/proof.go index f37cd22d..2b54fd24 100644 --- a/src/Mods/rocq/proof.go +++ b/src/Mods/rocq/proof.go @@ -74,7 +74,7 @@ func makeRocqProofFromIProof(proof Search.IProof) string { proof = proof.Children().At(0) } } - index, hypotheses := introduce(AST.MakerNot(conjecture), hypotheses) + index, hypotheses := introduce(AST.MakeNot(conjecture), hypotheses) resultingString += "intro " + introName(index) + ". " debug( @@ -91,7 +91,7 @@ func makeRocqProofFromIProof(proof Search.IProof) string { func(t AST.Term) AST.Term { switch id := AST.GetSymbol(t).(type) { case Lib.Some[AST.Id]: - return AST.MakerConst(id.Val) + return AST.MakeConst(id.Val) } raise_anomaly(fmt.Sprintf("Expected %s to be a Skolem term", t.ToString())) return nil @@ -387,7 +387,7 @@ func rewriteStep( func makeTheorem(axioms Lib.List[AST.Form], conjecture AST.Form) string { problemName := CertifUtils.SanitizedTheoremName() axiomsWithConj := Lib.ListCpy(axioms) - axiomsWithConj.Append(AST.MakerNot(AST.MakerNot(conjecture))) + axiomsWithConj.Append(AST.MakeNot(AST.MakeNot(conjecture))) formattedProblem := makeImpChain(axiomsWithConj) return "Theorem goeland_proof_of_" + problemName + " : " + formattedProblem.ToString() + ".\n" } @@ -397,7 +397,7 @@ func makeImpChain(forms Lib.List[AST.Form]) AST.Form { last := forms.Len() - 1 form := forms.At(last) for i := last - 1; i >= 0; i-- { - form = AST.MakerImp(forms.At(i), form) + form = AST.MakeImp(forms.At(i), form) } return form } @@ -466,7 +466,7 @@ func cleanHypotheses(hypotheses Lib.List[AST.Form], form AST.Form) (string, []Li )) } - hypotheses.Upd(actualIndex, AST.MakerTop()) + hypotheses.Upd(actualIndex, AST.MakeTop()) result = fmt.Sprintf("clear %s. ", introName(actualIndex)) return result, []Lib.List[AST.Form]{hypotheses} } diff --git a/src/Mods/tptp/proof.go b/src/Mods/tptp/proof.go index 33eaeb85..5fc14a1c 100644 --- a/src/Mods/tptp/proof.go +++ b/src/Mods/tptp/proof.go @@ -56,7 +56,7 @@ var original_terms = Lib.NewList[Lib.Either[AST.Ty, AST.Term]]() var prefix_step = "f" var prefix_axiom_cut = "ac" var prefix_const = "sko_" -var dummyTerm = AST.MakerConst(AST.MakerId("Goeland_I")) +var dummyTerm = AST.MakeConst(AST.MakeId("Goeland_I")) var dummyType = AST.MkTyConst("Goeland_T") var epsilon CertifUtils.Epsilon var current_id = 0 @@ -64,7 +64,7 @@ var current_id = 0 func makeTPTPProofFromIProof(proof Search.IProof) string { axioms, conjecture := CertifUtils.ProcessMainFormula(proof.AppliedOn()) resultingString := makeTheorem(axioms, conjecture) - hypotheses := Lib.ListCpy(axioms).Push(AST.MakerNot(conjecture)) + hypotheses := Lib.ListCpy(axioms).Push(AST.MakeNot(conjecture)) cut_hypotheses := performCutAxiomStep(axioms, conjecture) first_steps, next_id := performFirstStep(axioms, conjecture) @@ -72,7 +72,7 @@ func makeTPTPProofFromIProof(proof Search.IProof) string { proof.AppliedOn().GetSubTerms(), func(term AST.Term) AST.Term { new_term_name := fmt.Sprintf("%s%d", prefix_const, original_terms.Len()) - new_term := AST.MakerConst(AST.MakerId(new_term_name)) + new_term := AST.MakeConst(AST.MakeId(new_term_name)) original_terms.Append(Lib.MkRight[AST.Ty, AST.Term](term)) return new_term }, @@ -507,10 +507,10 @@ func equStep( case AST.Equ: A = form.GetF1() B = form.GetF2() - notA = AST.MakerNot(A) - notB = AST.MakerNot(B) - A_imp_B = AST.MakerImp(A, B) - B_imp_A = AST.MakerImp(B, A) + notA = AST.MakeNot(A) + notB = AST.MakeNot(B) + A_imp_B = AST.MakeImp(A, B) + B_imp_A = AST.MakeImp(B, A) default: raise_anomaly(fmt.Sprintf("Expected %s to be an equivalence.", form.ToString())) @@ -620,8 +620,8 @@ func notEquStep( case AST.Equ: A = f.GetF1() B = f.GetF2() - not_A_imp_B = AST.MakerNot(AST.MakerImp(A, B)) - not_B_imp_A = AST.MakerNot(AST.MakerImp(B, A)) + not_A_imp_B = AST.MakeNot(AST.MakeImp(A, B)) + not_B_imp_A = AST.MakeNot(AST.MakeImp(B, A)) default: raise_anomaly(fmt.Sprintf("Expected formula %s to be an equivalence", f.ToString())) @@ -726,7 +726,7 @@ func performFirstStep( fmt.Sprintf("%s%d", prefix_step, cut_form_not_id), "plain", axioms, - Lib.MkListV[AST.Form](conjecture, AST.MakerNot(conjecture)), + Lib.MkListV[AST.Form](conjecture, AST.MakeNot(conjecture)), "rightNot", "1", Lib.MkListV( diff --git a/src/Search/incremental/rules.go b/src/Search/incremental/rules.go index 73ac26a0..2c84899a 100644 --- a/src/Search/incremental/rules.go +++ b/src/Search/incremental/rules.go @@ -243,7 +243,7 @@ func (ano *AlphaNotOr) apply() []RuleList { switch subForm := form.GetForm().(type) { case AST.Or: for _, subForm := range subForm.GetChildFormulas().GetSlice() { - resultRules = append(resultRules, makeCorrectRule(AST.MakerNot(subForm), ano.GetTerms())) + resultRules = append(resultRules, makeCorrectRule(AST.MakeNot(subForm), ano.GetTerms())) } } } @@ -264,7 +264,7 @@ func (ani *AlphaNotImp) apply() []RuleList { switch subForm := form.GetForm().(type) { case AST.Imp: resultRules = append(resultRules, makeCorrectRule(subForm.GetF1(), ani.GetTerms())) - resultRules = append(resultRules, makeCorrectRule(AST.MakerNot(subForm.GetF2()), ani.GetTerms())) + resultRules = append(resultRules, makeCorrectRule(AST.MakeNot(subForm.GetF2()), ani.GetTerms())) } } @@ -284,7 +284,7 @@ func (bna *BetaNotAnd) apply() []RuleList { switch subForm := form.GetForm().(type) { case AST.And: for _, andForm := range subForm.GetChildFormulas().GetSlice() { - resultRulesBeta = append(resultRulesBeta, RuleList{makeCorrectRule(AST.MakerNot(andForm), bna.GetTerms())}) + resultRulesBeta = append(resultRulesBeta, RuleList{makeCorrectRule(AST.MakeNot(andForm), bna.GetTerms())}) } } } @@ -305,11 +305,11 @@ func (bne *BetaNotEqu) apply() []RuleList { case AST.Not: switch subForm := form.GetForm().(type) { case AST.Equ: - resultRules1 = append(resultRules1, makeCorrectRule(AST.MakerNot(subForm.GetF1()), bne.GetTerms())) + resultRules1 = append(resultRules1, makeCorrectRule(AST.MakeNot(subForm.GetF1()), bne.GetTerms())) resultRules1 = append(resultRules1, makeCorrectRule(subForm.GetF2(), bne.GetTerms())) resultRules2 = append(resultRules2, makeCorrectRule(subForm.GetF1(), bne.GetTerms())) - resultRules2 = append(resultRules2, makeCorrectRule(AST.MakerNot(subForm.GetF2()), bne.GetTerms())) + resultRules2 = append(resultRules2, makeCorrectRule(AST.MakeNot(subForm.GetF2()), bne.GetTerms())) } } @@ -345,7 +345,7 @@ func (bi *BetaImp) apply() []RuleList { switch subForm := bi.GetForm().(type) { case AST.Imp: - resultRules1 = append(resultRules1, makeCorrectRule(AST.MakerNot(subForm.GetF1()), bi.GetTerms())) + resultRules1 = append(resultRules1, makeCorrectRule(AST.MakeNot(subForm.GetF1()), bi.GetTerms())) resultRules2 = append(resultRules2, makeCorrectRule(subForm.GetF2(), bi.GetTerms())) } @@ -366,8 +366,8 @@ func (be *BetaEqu) apply() []RuleList { resultRules1 = append(resultRules1, makeCorrectRule(form.GetF1(), be.GetTerms())) resultRules1 = append(resultRules1, makeCorrectRule(form.GetF2(), be.GetTerms())) - resultRules2 = append(resultRules2, makeCorrectRule(AST.MakerNot(form.GetF1()), be.GetTerms())) - resultRules2 = append(resultRules2, makeCorrectRule(AST.MakerNot(form.GetF2()), be.GetTerms())) + resultRules2 = append(resultRules2, makeCorrectRule(AST.MakeNot(form.GetF1()), be.GetTerms())) + resultRules2 = append(resultRules2, makeCorrectRule(AST.MakeNot(form.GetF2()), be.GetTerms())) } return []RuleList{resultRules2, resultRules1} diff --git a/src/Search/proof-adapter.go b/src/Search/proof-adapter.go index f6c5aa1e..9acd4aa8 100644 --- a/src/Search/proof-adapter.go +++ b/src/Search/proof-adapter.go @@ -261,7 +261,7 @@ func getTermAtOcc(form AST.Form, occurrence Lib.List[Lib.Int]) Lib.Either[AST.Ty func getCleanForm(form AST.Form) AST.Form { switch f := form.(type) { case AST.Not: - return AST.MakerNot(getCleanForm_rec(f.GetForm())) + return AST.MakeNot(getCleanForm_rec(f.GetForm())) } return getCleanForm_rec(form) } diff --git a/src/Search/proof.go b/src/Search/proof.go index 15e4460d..38250d0c 100644 --- a/src/Search/proof.go +++ b/src/Search/proof.go @@ -258,7 +258,7 @@ func (p *ProofStruct) SetResultFormulasProof(fl []IntFormAndTermsList) { func MakeEmptyProofStruct() ProofStruct { return ProofStruct{ - Core.MakeFormAndTerm(AST.MakerBot(), Lib.NewList[AST.Term]()), + Core.MakeFormAndTerm(AST.MakeBot(), Lib.NewList[AST.Term]()), -1, -1, "", "", []IntFormAndTermsList{}, [][]ProofStruct{}, } } diff --git a/src/Search/rules.go b/src/Search/rules.go index b9b490b3..7cdb0877 100644 --- a/src/Search/rules.go +++ b/src/Search/rules.go @@ -293,7 +293,7 @@ func applyAlphaNotOrRule( for i := range formWithoutNot.GetChildFormulas().GetSlice() { result = result.AppendIfNotContains( - Core.MakeFormAndTerm(AST.MakerNot(formWithoutNot.GetChildFormulas().At(i)), terms), + Core.MakeFormAndTerm(AST.MakeNot(formWithoutNot.GetChildFormulas().At(i)), terms), ) } @@ -309,7 +309,7 @@ func applyAlphaNotImpRule( setStateRules(state, "ALPHA", "NOT", "IMPLY") result = result.AppendIfNotContains(Core.MakeFormAndTerm(formWithoutNot.GetF1(), terms)) - result = result.AppendIfNotContains(Core.MakeFormAndTerm(AST.MakerNot(formWithoutNot.GetF2()), terms)) + result = result.AppendIfNotContains(Core.MakeFormAndTerm(AST.MakeNot(formWithoutNot.GetF2()), terms)) return result } @@ -387,7 +387,7 @@ func applyBetaNotAndRule( result = append( result, Core.MakeSingleElementFormAndTermList( - Core.MakeFormAndTerm(AST.MakerNot(formWithoutNot.GetChildFormulas().At(i)), terms))) + Core.MakeFormAndTerm(AST.MakeNot(formWithoutNot.GetChildFormulas().At(i)), terms))) } return result @@ -403,12 +403,12 @@ func applyBetaNotEquRule( result = append(result, Core.FormAndTermsList{ - Core.MakeFormAndTerm(AST.MakerNot(formWithoutNot.GetF1()), terms), + Core.MakeFormAndTerm(AST.MakeNot(formWithoutNot.GetF1()), terms), Core.MakeFormAndTerm(formWithoutNot.GetF2(), terms)}) result = append(result, Core.FormAndTermsList{ Core.MakeFormAndTerm(formWithoutNot.GetF1(), terms), - Core.MakeFormAndTerm(AST.MakerNot(formWithoutNot.GetF2()), terms)}) + Core.MakeFormAndTerm(AST.MakeNot(formWithoutNot.GetF2()), terms)}) return result } @@ -437,7 +437,7 @@ func applyBetaImpRule( ) []Core.FormAndTermsList { setStateRules(state, "BETA", "IMPLY") - result = append(result, Core.MakeSingleElementFormAndTermList(Core.MakeFormAndTerm(AST.MakerNot(formTyped.GetF1()), terms))) + result = append(result, Core.MakeSingleElementFormAndTermList(Core.MakeFormAndTerm(AST.MakeNot(formTyped.GetF1()), terms))) result = append(result, Core.MakeSingleElementFormAndTermList(Core.MakeFormAndTerm(formTyped.GetF2(), terms))) return result @@ -453,8 +453,8 @@ func applyBetaEquRule( result = append(result, Core.FormAndTermsList{ - Core.MakeFormAndTerm(AST.MakerNot(formTyped.GetF1()), terms), - Core.MakeFormAndTerm(AST.MakerNot(formTyped.GetF2()), terms)}) + Core.MakeFormAndTerm(AST.MakeNot(formTyped.GetF1()), terms), + Core.MakeFormAndTerm(AST.MakeNot(formTyped.GetF2()), terms)}) result = append(result, Core.FormAndTermsList{ Core.MakeFormAndTerm(formTyped.GetF1(), terms), diff --git a/src/Unif/matching.go b/src/Unif/matching.go index 5989f2ec..fca27ec0 100644 --- a/src/Unif/matching.go +++ b/src/Unif/matching.go @@ -74,7 +74,7 @@ func (m *Machine) unify(node Node, formula AST.Form) []MatchingSubstitutions { switch formula_type := formula.(type) { case AST.Pred: // Transform the predicate to a function to make the tool work properly - m.terms = Lib.MkListV[AST.Term](AST.MakerFun( + m.terms = Lib.MkListV[AST.Term](AST.MakeFun( formula_type.GetID(), Lib.NewList[AST.Ty](), getFunctionalArguments(formula_type.GetTyArgs(), formula_type.GetArgs()), diff --git a/src/Unif/matching_substitutions.go b/src/Unif/matching_substitutions.go index b268d21a..403210ac 100644 --- a/src/Unif/matching_substitutions.go +++ b/src/Unif/matching_substitutions.go @@ -116,7 +116,7 @@ func translateTermRec(term AST.Term) AST.Term { args := trm.GetArgs() args = trm.GetArgs().Slice(ty_args.Len(), trm.GetArgs().Len()) - return AST.MakerFun( + return AST.MakeFun( trm.GetID(), ty_args, Lib.ListMap(args, translateTermRec), diff --git a/src/Unif/parsing.go b/src/Unif/parsing.go index c50f6246..9b1d97e5 100644 --- a/src/Unif/parsing.go +++ b/src/Unif/parsing.go @@ -106,7 +106,7 @@ func MakerTermForm(t AST.Term) TermForm { switch trm := t.(type) { case AST.Fun: args := getFunctionalArguments(trm.GetTyArgs(), trm.GetArgs()) - t = AST.MakerFun(trm.GetID(), Lib.NewList[AST.Ty](), args) + t = AST.MakeFun(trm.GetID(), Lib.NewList[AST.Ty](), args) } return makeTermForm(t.Copy()) } @@ -161,7 +161,7 @@ func getFunctionalArguments( case AST.Meta: args.Append(arg) case AST.Fun: - args.Append(AST.MakerFun( + args.Append(AST.MakeFun( term.GetID(), Lib.NewList[AST.Ty](), getFunctionalArguments(term.GetTyArgs(), term.GetArgs()), diff --git a/src/Unif/substitutions_type.go b/src/Unif/substitutions_type.go index 4d69ee69..98a69bb2 100644 --- a/src/Unif/substitutions_type.go +++ b/src/Unif/substitutions_type.go @@ -315,7 +315,7 @@ func eliminateInside( } case AST.Fun: - new_value := AST.MakerFun( + new_value := AST.MakeFun( value_2_type.GetP(), value_2_type.GetTyArgs(), eliminateList(key, value, value_2_type.GetArgs(), &has_changed), @@ -361,7 +361,7 @@ func eliminateList( tempList.Append(elementList) } case AST.Fun: // If its a function, reccursive call for the arguments - tempList.Append(AST.MakerFun( + tempList.Append(AST.MakeFun( lt.GetP(), lt.GetTyArgs(), eliminateList(key, value, lt.GetArgs(), &hasChanged), diff --git a/src/main.go b/src/main.go index 7c321112..5072f050 100644 --- a/src/main.go +++ b/src/main.go @@ -296,13 +296,13 @@ func StatementListToFormula( case and_list.Empty() && not_form == nil: return nil, bound, containsEquality, is_typed_problem case and_list.Empty(): - return AST.MakerNot(not_form), bound, containsEquality, is_typed_problem + return AST.MakeNot(not_form), bound, containsEquality, is_typed_problem case not_form == nil: - return AST.MakerAnd(and_list), bound, containsEquality, is_typed_problem + return AST.MakeAnd(and_list), bound, containsEquality, is_typed_problem default: flattened := AST.LsFlatten(and_list) - flattened.Append(AST.MakerNot(not_form)) - return AST.MakerAnd(flattened), bound, containsEquality, is_typed_problem + flattened.Append(AST.MakeNot(not_form)) + return AST.MakeAnd(flattened), bound, containsEquality, is_typed_problem } } From d28bf89252da267f951def3b8c5353934fc3eb44 Mon Sep 17 00:00:00 2001 From: Johann Rosain Date: Fri, 20 Mar 2026 16:04:29 +0100 Subject: [PATCH 27/30] clean: remove the useless method RenameVariables --- src/AST/forms-def.go | 32 -------------------------------- src/AST/formula.go | 11 ----------- src/AST/quantifiers.go | 33 --------------------------------- src/Unif/parsing.go | 7 +++---- src/main.go | 12 ++++-------- 5 files changed, 7 insertions(+), 88 deletions(-) diff --git a/src/AST/forms-def.go b/src/AST/forms-def.go index 4032ae28..765a3413 100644 --- a/src/AST/forms-def.go +++ b/src/AST/forms-def.go @@ -106,10 +106,6 @@ func (a All) Copy() Form { return All{a.quantifier.copy()} } -func (a All) RenameVariables() Form { - return All{a.quantifier.renameVariables()} -} - func (a All) ReplaceTermByTerm(old Term, new Term) (Form, bool) { quant, isReplaced := a.quantifier.replaceTermByTerm(old, new) return All{quant}, isReplaced @@ -165,10 +161,6 @@ func (e Ex) Copy() Form { return Ex{e.quantifier.copy()} } -func (e Ex) RenameVariables() Form { - return Ex{e.quantifier.renameVariables()} -} - func (e Ex) ReplaceTermByTerm(old Term, new Term) (Form, bool) { quant, isReplaced := e.quantifier.replaceTermByTerm(old, new) return Ex{quant}, isReplaced @@ -279,10 +271,6 @@ func (o Or) SubstTy(old TyGenVar, new Ty) Form { return MakeOrSimple(formList, o.metas.Raw()) } -func (o Or) RenameVariables() Form { - return MakeOr(renameFormList(o.forms)) -} - func (o Or) SubstituteVarByMeta(old Var, new Meta) Form { newFormList, newMetas := substVarByMetaInFormList(old, new, o.forms, o.metas.Raw()) return MakeOrSimple(newFormList, newMetas) @@ -408,10 +396,6 @@ func (a And) SubstTy(old TyGenVar, new Ty) Form { return MakeAndSimple(formList, a.metas.Raw()) } -func (a And) RenameVariables() Form { - return MakeAnd(renameFormList(a.forms)) -} - func (a And) SubstituteVarByMeta(old Var, new Meta) Form { newFormList, newMetas := substVarByMetaInFormList(old, new, a.forms, a.metas.Raw()) return MakeAndSimple(newFormList, newMetas) @@ -514,10 +498,6 @@ func (e Equ) SubstTy(old TyGenVar, new Ty) Form { ) } -func (e Equ) RenameVariables() Form { - return MakeEqu(e.GetF1().RenameVariables(), e.GetF2().RenameVariables()) -} - func (e Equ) GetSubTerms() Lib.Set[Term] { return e.GetF1().GetSubTerms().Union(e.GetF2().GetSubTerms()) } @@ -634,10 +614,6 @@ func (i Imp) SubstTy(old TyGenVar, new Ty) Form { ) } -func (i Imp) RenameVariables() Form { - return MakeImp(i.GetF1().RenameVariables(), i.GetF2().RenameVariables()) -} - func (i Imp) GetSubTerms() Lib.Set[Term] { return i.GetF1().GetSubTerms().Union(i.GetF2().GetSubTerms()) } @@ -755,10 +731,6 @@ func (n Not) SubstTy(old TyGenVar, new Ty) Form { ) } -func (n Not) RenameVariables() Form { - return MakeNot(n.f.RenameVariables()) -} - func (n Not) ReplaceMetaByTerm(meta Meta, term Term) Form { return MakeNot(n.f.ReplaceMetaByTerm(meta, term)) } @@ -855,8 +827,6 @@ func (p Pred) GetArgs() Lib.List[Term] { return p.args } /* Formula methods */ -func (p Pred) RenameVariables() Form { return p } - func (p Pred) ToString() string { return printer.StrFunctional( p.id, @@ -1042,7 +1012,6 @@ func (Top) Equals(f any) bool { _, isTop := f.(Top); func (Top) GetMetas() Lib.Set[Meta] { return Lib.EmptySet[Meta]() } func (t Top) ReplaceTermByTerm(Term, Term) (Form, bool) { return MakeTop(), false } func (t Top) SubstTy(TyGenVar, Ty) Form { return t } -func (t Top) RenameVariables() Form { return MakeTop() } func (t Top) GetSubTerms() Lib.Set[Term] { return Lib.EmptySet[Term]() } func (t Top) GetSymbols() Lib.Set[Id] { return Lib.EmptySet[Id]() } func (t Top) SubstituteVarByMeta(Var, Meta) Form { return t } @@ -1072,7 +1041,6 @@ func (Bot) Equals(f any) bool { _, isBot := f.(Bot); func (Bot) GetMetas() Lib.Set[Meta] { return Lib.EmptySet[Meta]() } func (b Bot) ReplaceTermByTerm(Term, Term) (Form, bool) { return MakeBot(), false } func (b Bot) SubstTy(TyGenVar, Ty) Form { return b } -func (b Bot) RenameVariables() Form { return MakeBot() } func (b Bot) GetSubTerms() Lib.Set[Term] { return Lib.EmptySet[Term]() } func (b Bot) GetSymbols() Lib.Set[Id] { return Lib.EmptySet[Id]() } func (b Bot) SubstituteVarByMeta(Var, Meta) Form { return b } diff --git a/src/AST/formula.go b/src/AST/formula.go index ea2a3e1f..84ceaa0c 100644 --- a/src/AST/formula.go +++ b/src/AST/formula.go @@ -57,7 +57,6 @@ type Form interface { ReplaceTermByTerm(old Term, new Term) (Form, bool) SubstTy(old TyGenVar, new Ty) Form - RenameVariables() Form SubstituteVarByMeta(old Var, new Meta) Form ReplaceMetaByTerm(meta Meta, term Term) Form } @@ -137,16 +136,6 @@ func replaceTyVarInFormList(oldForms Lib.List[Form], old TyGenVar, new Ty) Lib.L ) } -func renameFormList(forms Lib.List[Form]) Lib.List[Form] { - newForms := Lib.MkList[Form](forms.Len()) - - for i, form := range forms.GetSlice() { - newForms.Upd(i, form.RenameVariables()) - } - - return newForms -} - // Comparisons func qLess(vars1, vars2 Lib.List[TypedVar], f1, f2 Form) bool { diff --git a/src/AST/quantifiers.go b/src/AST/quantifiers.go index 1e6d4b41..1838d53d 100644 --- a/src/AST/quantifiers.go +++ b/src/AST/quantifiers.go @@ -151,39 +151,6 @@ func (q quantifier) replaceTyVar(old TyGenVar, new Ty) quantifier { ) } -func (q quantifier) renameVariables() quantifier { - newVarList := Lib.NewList[TypedVar]() - newForm := q.GetForm().RenameVariables() - - newTyBv := Lib.NewList[Lib.Pair[TyBound, Ty]]() - for _, v := range q.GetVarList().GetSlice() { - newVar := MakeVar(v.GetName()) - newVarList.Append(MkTypedVar(newVar.name, v.ty)) - f, replaced := newForm.ReplaceTermByTerm(v.ToBoundVar(), newVar) - if !replaced { - newBv := MkTyBV(newVar.name) - f = f.SubstTy(v.ToTyBoundVar(), newBv) - newTyBv.Append(Lib.MkPair(v.ToTyBoundVar(), newBv)) - } - newForm = f - } - - return makeQuantifier( - Lib.ListMap( - newVarList, - func(p TypedVar) TypedVar { - for _, pair := range newTyBv.GetSlice() { - p = p.SubstTy(pair.Fst, pair.Snd) - } - return p - }, - ), - newForm, - q.metas.Raw().Copy(), - q.symbol, - ) -} - func (q quantifier) substituteVarByMeta(old Var, new Meta) quantifier { if Lib.ListMem(old, Lib.ListMap(q.varList, func(x TypedVar) Var { return x.ToBoundVar() })) { return q diff --git a/src/Unif/parsing.go b/src/Unif/parsing.go index 9b1d97e5..b0d00963 100644 --- a/src/Unif/parsing.go +++ b/src/Unif/parsing.go @@ -41,10 +41,9 @@ type TermForm struct { t AST.Term } -func (t TermForm) ToString() string { return t.ToString() } -func (t TermForm) GetTerm() AST.Term { return t.t.Copy() } -func (t TermForm) Copy() AST.Form { return makeTermForm(t.GetTerm()) } -func (t TermForm) RenameVariables() AST.Form { return t } +func (t TermForm) ToString() string { return t.ToString() } +func (t TermForm) GetTerm() AST.Term { return t.t.Copy() } +func (t TermForm) Copy() AST.Form { return makeTermForm(t.GetTerm()) } func (t TermForm) ReplaceTermByTerm(AST.Term, AST.Term) (AST.Form, bool) { return t, false } diff --git a/src/main.go b/src/main.go index 5072f050..bd457ebb 100644 --- a/src/main.go +++ b/src/main.go @@ -307,21 +307,17 @@ func StatementListToFormula( } func doAxiomStatement(andList Lib.List[AST.Form], f AST.Form) Lib.List[AST.Form] { - newForm := f.RenameVariables() - // FIXME: dmt should be a plugin and therefore not checked here. // Ideally, we want to be able to define a hook here and let the plugins do // whatever they want, returning only whether they consumed the axiom or // not. It would also avoid duplicated code. if !Glob.IsLoaded("dmt") { - andList.Append(newForm) - return andList + return andList.Push(f) } - consumed := dmt.RegisterAxiom(newForm.Copy()) + consumed := dmt.RegisterAxiom(f.Copy()) if !consumed { - andList.Append(newForm) - return andList + return andList.Push(f) } return andList @@ -329,7 +325,7 @@ func doAxiomStatement(andList Lib.List[AST.Form], f AST.Form) Lib.List[AST.Form] func doConjectureStatement(f AST.Form) AST.Form { Glob.SetConjecture(true) - return f.RenameVariables() + return f } func doTypeStatement(atomTyping Core.TFFAtomTyping) { From b23a76be0e7124d308a82ba7562ec4bce438e01a Mon Sep 17 00:00:00 2001 From: Johann Rosain Date: Mon, 23 Mar 2026 18:18:12 +0100 Subject: [PATCH 28/30] clean: remove TermForm and unify terms --- src/AST/ty-syntax.go | 4 + .../equality/bse/equality_rules_try_apply.go | 2 +- src/Unif/code-trees.go | 89 ++++++---- src/Unif/data_structure.go | 12 ++ src/Unif/machine.go | 4 +- src/Unif/matching.go | 130 ++++++++------ src/Unif/matching_substitutions.go | 65 ++++++- src/Unif/parsing.go | 158 ++++-------------- src/Unif/sequence.go | 41 ++++- src/Unif/substitutions_tree.go | 104 ++++++------ 10 files changed, 339 insertions(+), 270 deletions(-) diff --git a/src/AST/ty-syntax.go b/src/AST/ty-syntax.go index 352c38aa..213a6128 100644 --- a/src/AST/ty-syntax.go +++ b/src/AST/ty-syntax.go @@ -281,6 +281,10 @@ func (p TyPi) VarsLen() int { return p.vars.Len() } +func (p TyPi) Ty() Ty { + return p.ty +} + // Makers func MkTyVar(repr string) Ty { diff --git a/src/Mods/equality/bse/equality_rules_try_apply.go b/src/Mods/equality/bse/equality_rules_try_apply.go index 375ad322..21fcd9c3 100644 --- a/src/Mods/equality/bse/equality_rules_try_apply.go +++ b/src/Mods/equality/bse/equality_rules_try_apply.go @@ -267,7 +267,7 @@ func checkUnifInTree(t AST.Term, tree Unif.DataStructure) (bool, Lib.List[AST.Te return fmt.Sprintf("Unif found with: %s", subst.ToString()) }), ) - result_list.Append(subst.GetForm().(Unif.TermForm).GetTerm()) + result_list.Append(subst.Term()) } return result_list.Len() > 0, result_list diff --git a/src/Unif/code-trees.go b/src/Unif/code-trees.go index 6beb3371..3a7e25d1 100644 --- a/src/Unif/code-trees.go +++ b/src/Unif/code-trees.go @@ -58,11 +58,11 @@ func (c CodeBlock) Copy() CodeBlock { type Node struct { value CodeBlock children []*Node - formulas Lib.List[AST.Form] + leafFor Lib.List[Lib.Either[AST.Term, AST.Form]] } func NewNode() *Node { - return &Node{CodeBlock{}, []*Node{}, Lib.NewList[AST.Form]()} + return &Node{CodeBlock{}, []*Node{}, Lib.NewList[Lib.Either[AST.Term, AST.Form]]()} } func (n Node) getValue() CodeBlock { @@ -71,38 +71,48 @@ func (n Node) getValue() CodeBlock { func (n Node) getChildren() []*Node { return CopyNodeList(n.children) } -func (n Node) getFormulas() Lib.List[AST.Form] { - return Lib.ListCpy(n.formulas) -} /* Check if a node is empty */ func (n Node) IsEmpty() bool { return (len(n.value) == 0) } -/* Make data struct */ +func MakeUnifProblem(l Lib.List[AST.Form], is_pos bool) DataStructure { + return NewNode().MakeDataStruct(l, is_pos) +} + +func MakeTermUnifProblem(l Lib.List[AST.Term]) DataStructure { + root := makeNode(nil) + + for _, t := range l.GetSlice() { + root.insert(ParseTerm(transformTerm(t))) + } + + return root +} + func (n Node) MakeDataStruct(fl Lib.List[AST.Form], is_pos bool) DataStructure { return makeCodeTreeFromAtomic(fl, is_pos) } /* Copy a datastruct */ func (n Node) Copy() DataStructure { - return Node{n.getValue(), n.getChildren(), n.getFormulas()} + return Node{n.getValue(), n.getChildren(), n.leafFor.Copy(Lib.EitherCpy[AST.Term, AST.Form])} } /********************/ /* Helper functions */ /********************/ -/* The Node is a leaf when it contains at least one formulae. */ +/* The Node is a leaf whenever one formula or term ends here. */ func (n Node) isLeaf() bool { - return n.getFormulas().Len() > 0 + return n.leafFor.Len() > 0 } -/* Make two code trees (tree_pos and tree_neg) from st.atomic */ func makeCodeTreeFromAtomic(lf Lib.List[AST.Form], is_pos bool) *Node { form := Lib.NewList[AST.Form]() + // fixme: why are we doing this here? for _, f := range lf.GetSlice() { switch nf := f.(type) { case AST.Pred: @@ -116,9 +126,6 @@ func makeCodeTreeFromAtomic(lf Lib.List[AST.Form], is_pos bool) *Node { form.Append(nf.GetForm()) } } - case TermForm: - // EQUALITY - To build a tree of terms - form.Append(nf.Copy()) } } @@ -152,7 +159,7 @@ func makeNode(block CodeBlock) *Node { n := new(Node) n.value = block.Copy() n.children = []*Node{} - n.formulas = Lib.NewList[AST.Form]() + n.leafFor = Lib.NewList[Lib.Either[AST.Term, AST.Form]]() return n } @@ -198,8 +205,17 @@ func (n Node) printAux(tab int) { } if n.isLeaf() { - for _, form := range n.formulas.GetSlice() { - debug(Lib.MkLazy(func() string { return strings.Repeat("\t", tab+1) + form.ToString() })) + for _, tof := range n.leafFor.GetSlice() { + debug( + Lib.MkLazy( + func() string { + return strings.Repeat( + "\t", + tab+1, + ) + tofToString(tof) + }, + ), + ) } } debug(Lib.MkLazy(func() string { return "\n" })) @@ -214,17 +230,17 @@ func (n Node) printAux(tab int) { func (n *Node) insert(sequence Sequence) { if len(n.value) == 0 { n.value = sequence.GetInstructions() - n.formulas = Lib.MkListV(sequence.GetFormula()) + n.leafFor = Lib.MkListV(sequence.GetBase()) } else { - n.followInstructions(sequence.GetInstructions(), sequence.GetFormula()) + n.followInstructions(sequence.GetInstructions(), sequence.GetBase()) } } /* Auxiliary function to follow the sequence of instructions to insert in the Node. */ -func (n *Node) followInstructions(instructions []Instruction, form AST.Form) { +func (n *Node) followInstructions(instructions []Instruction, tof Lib.Either[AST.Term, AST.Form]) { // Initialization of the node we will be working on and of a counter. current := n - oui := 0 + cnt := 0 // For each instruction, there are 2 cases: // * The current instruction is equivalent to the instruction stored in the CodeBlock of the current node at the index of the counter. @@ -234,11 +250,12 @@ func (n *Node) followInstructions(instructions []Instruction, form AST.Form) { // If it's equivalent, there are 2 cases: // * It's the end of the sequence & the end of the CodeBlock. In this case, it's a full match, just add the formulae to the leaf. // * It's the end of the CodeBlock, but not of the sequence. In this case, check if the following instruction matches with any child. - if instr.IsEquivalent(current.value[oui]) { - oui += 1 - if i == len(instructions)-1 && oui == len(current.value) && !Lib.ListMem(form, current.formulas) { - current.formulas.Append(form) - } else if i < len(instructions)-1 && oui == len(current.value) { + if instr.IsEquivalent(current.value[cnt]) { + cnt += 1 + if i == len(instructions)-1 && cnt == len(current.value) && + !current.leafFor.Contains(tof, tofCmp) { + current.leafFor.Append(tof) + } else if i < len(instructions)-1 && cnt == len(current.value) { // If the instruction matches, then continue the algorithm with the child as the current node. // If it doesn't, we have a new leaf with the following instructions of the sequence. @@ -246,13 +263,13 @@ func (n *Node) followInstructions(instructions []Instruction, form AST.Form) { for _, child := range current.children { if instructions[i+1].IsEquivalent(child.value[0]) { current = child - oui = 0 + cnt = 0 found = true } } if !found { newNode := makeNode(instructions[i+1:]) - newNode.formulas = Lib.MkListV(form) + newNode.leafFor = Lib.MkListV(tof) current.children = append(current.children, newNode) break } @@ -261,15 +278,15 @@ func (n *Node) followInstructions(instructions []Instruction, form AST.Form) { // Split the current CodeBlock in 2 parts: // * The first one will contain the remaining instructions of the current CodeBlock, and it will inherit the current's children and formulaes. // * The second one contains the remaining instructions of the sequence plus the formulae. - child1 := makeNode(current.value[oui:]) + child1 := makeNode(current.value[cnt:]) child2 := makeNode(instructions[i:]) - child2.formulas = Lib.MkListV(form) + child2.leafFor = Lib.MkListV(tof) child1.children = current.children - child1.formulas = current.formulas + child1.leafFor = current.leafFor - current.value = current.value[:oui] - current.formulas = Lib.NewList[AST.Form]() + current.value = current.value[:cnt] + current.leafFor = Lib.NewList[Lib.Either[AST.Term, AST.Form]]() current.children = []*Node{child1, child2} break @@ -279,12 +296,12 @@ func (n *Node) followInstructions(instructions []Instruction, form AST.Form) { // It's the end of the sequence, but there are still instructions in the CodeBlock. // In this case, we have to split the CodeBlock in 2 parts. The first one will be a leaf containing the current sequence's formulae. // The second will be the rest of the CodeBlock's instructions, with the current's children and formulaes. - if oui < len(current.value)-1 { - child1 := makeNode(current.value[oui:]) + if cnt < len(current.value)-1 { + child1 := makeNode(current.value[cnt:]) child1.children = current.children - current.value = current.value[:oui] + current.value = current.value[:cnt] current.children = []*Node{child1} - current.formulas = Lib.MkListV(form.Copy()) + current.leafFor = Lib.MkListV(tofCopy(tof)) } } diff --git a/src/Unif/data_structure.go b/src/Unif/data_structure.go index c3d9f2a7..7678be98 100644 --- a/src/Unif/data_structure.go +++ b/src/Unif/data_structure.go @@ -47,6 +47,18 @@ type DataStructure interface { IsEmpty() bool MakeDataStruct(Lib.List[AST.Form], bool) DataStructure InsertFormulaListToDataStructure(Lib.List[AST.Form]) DataStructure + Unify(AST.Form) (bool, []MixedSubstitutions) + UnifyTerm(AST.Term) (bool, []MixedTermSubstitutions) + // FIXME: + // When the unification gets reworked, think a bit more about the exposed interface. + // We want to index on _terms_ while keeping the ability to unify _predicates_. + // (we can easily coerce a predicate to a function) + // We probably want to expose two functions --- one to unify predicates, and the other + // one to unify terms. But maybe we should say that unifying predicates is the "weird" + // case instead of the other way around. + // + // We should also find a more explicit name over `DataStructure`... + Copy() DataStructure } diff --git a/src/Unif/machine.go b/src/Unif/machine.go index 99f6e689..32c0e309 100644 --- a/src/Unif/machine.go +++ b/src/Unif/machine.go @@ -68,7 +68,7 @@ type Machine struct { subst []SubstPair terms Lib.List[AST.Term] meta Substitutions - failure []MatchingSubstitutions + failure []MixMatchSubstitutions topLevelTot int topLevelCount int } @@ -85,7 +85,7 @@ func makeMachine() Machine { subst: []SubstPair{}, terms: Lib.NewList[AST.Term](), meta: Substitutions{}, - failure: []MatchingSubstitutions{}, + failure: []MixMatchSubstitutions{}, topLevelTot: 0, topLevelCount: 0, } diff --git a/src/Unif/matching.go b/src/Unif/matching.go index fca27ec0..140cef9e 100644 --- a/src/Unif/matching.go +++ b/src/Unif/matching.go @@ -56,58 +56,67 @@ func InitDebugger() { /* Helper function to avoid using MakeMachine() outside of this file. */ func (n Node) Unify(formula AST.Form) (bool, []MixedSubstitutions) { machine := makeMachine() - res := machine.unify(n, formula) + var term AST.Term + + if formula_type, is_pred := formula.(AST.Pred); is_pred { + term = transformPred(formula_type) + } else { + Glob.Anomaly("unification", fmt.Sprintf("Expected predicate, got %s", formula.ToString())) + } + + res, matching_substs := machine.unify(n, term) + // As we have transformed type metas to terms, we get everything in a term substitution. // But externally, we want to have a substitution of both (term) metas to terms and (type) metas to types. // We use MixedSubstitution to properly manage things internally. mixed_substs := []MixedSubstitutions{} - for _, subst := range res { + for _, subst := range matching_substs { mixed_substs = append(mixed_substs, subst.toMixed()) } - return !reflect.DeepEqual(machine.failure, res), mixed_substs + + return res, mixed_substs } -/* Tries to find the substitutions needed to unify the formulae with the one described by the sequence of instructions. */ -func (m *Machine) unify(node Node, formula AST.Form) []MatchingSubstitutions { - var result []MatchingSubstitutions - // The formula has to be a predicate. - switch formula_type := formula.(type) { - case AST.Pred: - // Transform the predicate to a function to make the tool work properly - m.terms = Lib.MkListV[AST.Term](AST.MakeFun( - formula_type.GetID(), - Lib.NewList[AST.Ty](), - getFunctionalArguments(formula_type.GetTyArgs(), formula_type.GetArgs()), - )) - result = m.unifyAux(node) - - if !reflect.DeepEqual(m.failure, result) { - filteredResult := []MatchingSubstitutions{} - for _, matchingSubst := range result { - filteredResult = append(filteredResult, - MakeMatchingSubstitutions(matchingSubst.GetForm(), matchingSubst.GetSubst())) - } - result = filteredResult - } - case TermForm: - m.terms = Lib.MkListV(formula_type.GetTerm()) - result = m.unifyAux(node) - default: - result = m.failure +func (n Node) UnifyTerm(t AST.Term) (bool, []MixedTermSubstitutions) { + m := makeMachine() + + res, matching_substs := m.unify( + n, + transformTerm(t), + ) + + mixed_substs := []MixedTermSubstitutions{} + for _, subst := range matching_substs { + mixed_substs = append(mixed_substs, subst.toMixedTerm()) } - return result + return res, mixed_substs +} + +/* Tries to find the substitutions needed to unify the formulae with the one described by the sequence of instructions. */ +func (m *Machine) unify(node Node, t AST.Term) (bool, []MixMatchSubstitutions) { + m.terms = Lib.MkListV(t) + res := m.unifyAux(node) + return !reflect.DeepEqual(m.failure, res), res } /*** Unify aux ***/ -func (m *Machine) unifyAux(node Node) []MatchingSubstitutions { +func (m *Machine) unifyAux(node Node) []MixMatchSubstitutions { for _, instr := range node.value { debug(Lib.MkLazy(func() string { return "------------------------" })) debug(Lib.MkLazy(func() string { return fmt.Sprintf("Instr: %v", instr.ToString()) })) debug(Lib.MkLazy(func() string { return fmt.Sprintf("Meta : %v", m.meta.ToString()) })) - debug(Lib.MkLazy(func() string { return fmt.Sprintf("Subst : %v", SubstPairListToString(m.subst)) })) - debug(Lib.MkLazy(func() string { return fmt.Sprintf("Post : %v", IntPairistToString(m.post)) })) + debug( + Lib.MkLazy( + func() string { return fmt.Sprintf("Subst : %v", SubstPairListToString(m.subst)) }, + ), + ) + debug( + Lib.MkLazy( + func() string { return fmt.Sprintf("Post : %v", IntPairistToString(m.post)) }, + ), + ) debug(Lib.MkLazy(func() string { return fmt.Sprintf("IsLocked : %v", m.isLocked()) })) debug(Lib.MkLazy(func() string { return fmt.Sprintf("HasPushed : %v", m.hasPushed) })) debug(Lib.MkLazy(func() string { return fmt.Sprintf("HasPoped : %v", m.hasPoped) })) @@ -131,7 +140,9 @@ func (m *Machine) unifyAux(node Node) []MatchingSubstitutions { Lib.MkLazy(func() string { return fmt.Sprintf("Cursor: %v/%v", m.q, m.terms.Len()) }), ) debug( - Lib.MkLazy(func() string { return fmt.Sprintf("m.terms[cursor] : %v", m.terms.At(m.q).ToString()) }), + Lib.MkLazy( + func() string { return fmt.Sprintf("m.terms[cursor] : %v", m.terms.At(m.q).ToString()) }, + ), ) debug( Lib.MkLazy(func() string { @@ -173,26 +184,29 @@ func (m *Machine) unifyAux(node Node) []MatchingSubstitutions { } } - matching := []MatchingSubstitutions{} + matching := []MixMatchSubstitutions{} if node.isLeaf() { - for _, f := range node.formulas.GetSlice() { - if reflect.TypeOf(f) == reflect.TypeOf(AST.Pred{}) || reflect.TypeOf(f) == reflect.TypeOf(TermForm{}) { - // Rebuild final substitution between meta and subst - final_subst := computeSubstitutions(CopySubstPairList(m.subst), m.meta.Copy(), f.Copy()) - if !final_subst.Equals(Failure()) { - matching = append(matching, MakeMatchingSubstitutions(f, final_subst)) - } + for _, f := range node.leafFor.GetSlice() { + // Rebuild final substitution between meta and subst + final_subst := computeSubstitutions( + CopySubstPairList(m.subst), + m.meta.Copy(), + tofMetaList(f), + ) + if !final_subst.Equals(Failure()) { + matching = append(matching, MixMatchSubstitutions{tof: f, subst: final_subst}) } } } + matching = append(matching, m.launchChildrenSearch(node)...) return matching } /* Unify on goroutines - to manage die message */ /* TODO : remove when debug ok */ -func (m *Machine) unifyAuxOnGoroutine(n Node, ch chan []MatchingSubstitutions, father_id uint64) { +func (m *Machine) unifyAuxOnGoroutine(n Node, ch chan []MixMatchSubstitutions, father_id uint64) { debug( Lib.MkLazy(func() string { return fmt.Sprintf("Child of %v, Unify Aux", father_id) }), ) @@ -202,23 +216,37 @@ func (m *Machine) unifyAuxOnGoroutine(n Node, ch chan []MatchingSubstitutions, f } /* Launches each child of the current node in a goroutine. */ -func (m *Machine) launchChildrenSearch(node Node) []MatchingSubstitutions { - channels := []chan []MatchingSubstitutions{} +func (m *Machine) launchChildrenSearch(node Node) []MixMatchSubstitutions { + channels := []chan []MixMatchSubstitutions{} for _, c := range node.children { debug( - Lib.MkLazy(func() string { return fmt.Sprintf("Next symbol = %v", c.getValue()[0].ToString()) }), + Lib.MkLazy( + func() string { return fmt.Sprintf("Next symbol = %v", c.getValue()[0].ToString()) }, + ), ) - channels = append(channels, make(chan []MatchingSubstitutions)) + channels = append(channels, make(chan []MixMatchSubstitutions)) } - matching := []MatchingSubstitutions{} + matching := []MixMatchSubstitutions{} for i, n := range node.children { ch := channels[i] st := m.terms.Copy(AST.Term.Copy) ip := CopyIntPairList(m.post) sc := CopySubstPairList(m.subst) - copy := Machine{subst: sc, beginLock: m.beginLock, terms: st, meta: m.meta.Copy(), q: m.q, beginCount: m.beginCount, hasPushed: m.hasPushed, hasPoped: m.hasPoped, post: ip, topLevelTot: m.topLevelTot, topLevelCount: m.topLevelCount} + copy := Machine{ + subst: sc, + beginLock: m.beginLock, + terms: st, + meta: m.meta.Copy(), + q: m.q, + beginCount: m.beginCount, + hasPushed: m.hasPushed, + hasPoped: m.hasPoped, + post: ip, + topLevelTot: m.topLevelTot, + topLevelCount: m.topLevelCount, + } go copy.unifyAuxOnGoroutine(*n, ch, Glob.GetGID()) Glob.IncrGoRoutine(1) @@ -232,7 +260,7 @@ func (m *Machine) launchChildrenSearch(node Node) []MatchingSubstitutions { for cpt_remaining_children > 0 { _, value, _ := reflect.Select(cases) - matching = append(matching, value.Interface().([]MatchingSubstitutions)...) + matching = append(matching, value.Interface().([]MixMatchSubstitutions)...) cpt_remaining_children-- } diff --git a/src/Unif/matching_substitutions.go b/src/Unif/matching_substitutions.go index 403210ac..7b2bfadf 100644 --- a/src/Unif/matching_substitutions.go +++ b/src/Unif/matching_substitutions.go @@ -106,11 +106,12 @@ func translateTermRec(term AST.Term) AST.Term { opt_ty := Typing.QueryGlobalEnv(trm.GetName()) switch ty := opt_ty.(type) { case Lib.Some[AST.Ty]: - switch t := ty.Val.(type) { - case AST.TyPi: - for i := 0; i < t.VarsLen(); i++ { - ty_args.Append(AST.TermToTy(trm.GetArgs().At(i))) - } + t := ty.Val + i := 0 + for Glob.Is[AST.TyPi](t) { + ty_args.Append(AST.TermToTy(trm.GetArgs().At(i))) + t = t.(AST.TyPi).Ty() + i += 1 } } args := trm.GetArgs() @@ -268,6 +269,56 @@ func (m MixedSubstitutions) MatchingSubstitutions() MatchingSubstitutions { return MakeMatchingSubstitutions(m.form, m.GetTrmSubsts()) } +type MixMatchSubstitutions struct { + tof Lib.Either[AST.Term, AST.Form] + subst Substitutions +} + +// Pre-requisite: only formulas in the tof +func (s MixMatchSubstitutions) toMatching() MatchingSubstitutions { + switch tof := s.tof.(type) { + case Lib.Left[AST.Term, AST.Form]: + Glob.Anomaly("unification", "expected unification between formulas, got unification between terms") + case Lib.Right[AST.Term, AST.Form]: + return MakeMatchingSubstitutions(tof.Val, s.subst) + } + + Glob.Anomaly("unification", "reached an unreachable case") + return MakeMatchingSubstitutions(AST.MakerTop(), MakeEmptySubstitution()) +} + +func (s MixMatchSubstitutions) toMixed() MixedSubstitutions { + return s.toMatching().toMixed() +} + +type MixedTermSubstitutions struct { + term AST.Term + substs []MixedSubstitution +} + +func (s MixedTermSubstitutions) Term() AST.Term { return s.term } + +func (s MixedTermSubstitutions) ToString() string { + substs_list := Lib.MkListV(s.substs...) + return s.term.ToString() + " {" + Lib.ListToString(substs_list, Lib.WithEmpty("")) + "}" +} + +func (s MixMatchSubstitutions) toMixedTerm() MixedTermSubstitutions { + switch tof := s.tof.(type) { + case Lib.Left[AST.Term, AST.Form]: + substs := []MixedSubstitution{} + for _, subst := range s.subst { + substs = append(substs, translateFromSubst(subst)) + } + return MixedTermSubstitutions{tof.Val, substs} + case Lib.Right[AST.Term, AST.Form]: + Glob.Anomaly("unification", "expected unification between terms, got unification between formulas") + } + + Glob.Anomaly("unification", "reached an unreachable case") + return MixedTermSubstitutions{nil, []MixedSubstitution{}} +} + func translateToSubst(subst MixedSubstitution) Substitution { switch s := subst.s.(type) { case Lib.Left[TySubstitution, Substitution]: @@ -283,7 +334,9 @@ func translateToSubst(subst MixedSubstitution) Substitution { return MakeSubstitution(AST.MakeEmptyMeta(), nil) } -func MergeMixedSubstitutions(substs1, substs2 Lib.List[MixedSubstitution]) (Lib.List[MixedSubstitution], bool) { +func MergeMixedSubstitutions( + substs1, substs2 Lib.List[MixedSubstitution], +) (Lib.List[MixedSubstitution], bool) { translated_substs1 := Lib.ListMap(substs1, translateToSubst).GetSlice() translated_substs2 := Lib.ListMap(substs2, translateToSubst).GetSlice() diff --git a/src/Unif/parsing.go b/src/Unif/parsing.go index b0d00963..5e8d080d 100644 --- a/src/Unif/parsing.go +++ b/src/Unif/parsing.go @@ -34,84 +34,30 @@ package Unif import ( "github.com/GoelandProver/Goeland/AST" + "github.com/GoelandProver/Goeland/Glob" "github.com/GoelandProver/Goeland/Lib" ) -type TermForm struct { - t AST.Term +func transformPred(p AST.Pred) AST.Term { + return transformTerm(AST.MakerFun(p.GetID(), p.GetTyArgs(), p.GetArgs())) } -func (t TermForm) ToString() string { return t.ToString() } -func (t TermForm) GetTerm() AST.Term { return t.t.Copy() } -func (t TermForm) Copy() AST.Form { return makeTermForm(t.GetTerm()) } -func (t TermForm) ReplaceTermByTerm(AST.Term, AST.Term) (AST.Form, bool) { - return t, false -} -func (t TermForm) SubstTy(AST.TyGenVar, AST.Ty) AST.Form { - return t -} -func (t TermForm) SubstituteVarByMeta(AST.Var, AST.Meta) AST.Form { return t } -func (t TermForm) GetInternalMetas() Lib.List[AST.Meta] { return Lib.NewList[AST.Meta]() } -func (t TermForm) SetInternalMetas(Lib.List[AST.Meta]) AST.Form { return t } -func (t TermForm) GetSubFormulasRecur() Lib.List[AST.Form] { return Lib.NewList[AST.Form]() } -func (t TermForm) GetChildFormulas() Lib.List[AST.Form] { return Lib.NewList[AST.Form]() } - -func (t TermForm) Equals(t2 any) bool { - switch nt := t2.(type) { - case TermForm: - return t.GetTerm().Equals(nt.GetTerm()) - default: - return false - } -} - -func (t TermForm) GetMetas() Lib.Set[AST.Meta] { - switch nt := t.GetTerm().(type) { - case AST.Meta: - return Lib.Singleton(nt) - case AST.Fun: - res := Lib.EmptySet[AST.Meta]() - - for _, m := range nt.GetArgs().GetSlice() { - switch mt := m.(type) { - case AST.Meta: - res = res.Add(mt) - } - } - - return res - default: - return Lib.EmptySet[AST.Meta]() - } -} - -func (t TermForm) GetSubTerms() Lib.Set[AST.Term] { - return t.GetTerm().GetSubTerms() -} - -func (t TermForm) GetSymbols() Lib.Set[AST.Id] { - return t.GetTerm().GetSymbols() -} - -func (t TermForm) Less(oth any) bool { - return t.GetTerm().Less(oth) -} - -func (t TermForm) ReplaceMetaByTerm(meta AST.Meta, term AST.Term) AST.Form { - return t -} - -func MakerTermForm(t AST.Term) TermForm { - switch trm := t.(type) { +func transformTerm(t AST.Term) AST.Term { + switch term := t.(type) { + case AST.Id, AST.Meta, AST.Var: + return t case AST.Fun: - args := getFunctionalArguments(trm.GetTyArgs(), trm.GetArgs()) - t = AST.MakeFun(trm.GetID(), Lib.NewList[AST.Ty](), args) + args := Lib.ListMap(term.GetTyArgs(), AST.TyToTerm) + args.Append(Lib.ListMap(term.GetArgs(), transformTerm).GetSlice()...) + return AST.MakerFun( + term.GetID(), + Lib.NewList[AST.Ty](), + args, + ) } - return makeTermForm(t.Copy()) -} -func makeTermForm(t AST.Term) TermForm { - return TermForm{t.Copy()} + Glob.Anomaly("unif parsing", "Unknown term") + return nil } /* Parses a formulae to a sequence of instructions. */ @@ -120,26 +66,17 @@ func ParseFormula(formula AST.Form) Sequence { // The formula has to be a predicate switch formula_type := formula.(type) { case AST.Pred: - instructions := Sequence{formula: formula_type} + instructions := Sequence{base: Lib.MkRight[AST.Term, AST.Form](formula)} - instructions.add(Begin{}) - parsePred(formula_type, &instructions) - instructions.add(End{}) + switch term := transformPred(formula_type).(type) { + case AST.Fun: + instructions.add(Begin{}) + parsePred(formula_type.GetID(), term.GetArgs(), &instructions) + instructions.add(End{}) - return instructions - case TermForm: - instructions := Sequence{formula: formula} - varCount := 0 - postCount := 0 - instructions.add(Begin{}) - parseTerms( - Lib.MkListV(formula_type.GetTerm().Copy()), - &instructions, - Lib.NewList[AST.Meta](), - &varCount, - &postCount, - ) - instructions.add(End{}) + default: + Glob.Anomaly("unification", "error when translating in internal representation") + } return instructions @@ -148,38 +85,15 @@ func ParseFormula(formula AST.Form) Sequence { } } -/* Parses a predicate to machine instructions */ -func getFunctionalArguments( - ty_args Lib.List[AST.Ty], - trm_args Lib.List[AST.Term], -) Lib.List[AST.Term] { - args := Lib.ListMap(ty_args, AST.TyToTerm) - - for _, arg := range trm_args.GetSlice() { - switch term := arg.(type) { - case AST.Meta: - args.Append(arg) - case AST.Fun: - args.Append(AST.MakeFun( - term.GetID(), - Lib.NewList[AST.Ty](), - getFunctionalArguments(term.GetTyArgs(), term.GetArgs()), - )) - } - } - - return args -} - -func parsePred(p AST.Pred, instructions *Sequence) { - instructions.add(makeCheck(p.GetID())) - if !p.GetTyArgs().Empty() || !p.GetArgs().Empty() { +func parsePred(i AST.Id, args Lib.List[AST.Term], instructions *Sequence) { + instructions.add(makeCheck(i)) + if !args.Empty() { instructions.add(Begin{}) instructions.add(Down{}) varCount := 0 postCount := 0 parseTerms( - getFunctionalArguments(p.GetTyArgs(), p.GetArgs()), + args, instructions, Lib.NewList[AST.Meta](), &varCount, @@ -224,7 +138,7 @@ func parseTerms( instructions.add(Right{}) } case AST.Fun: - instructions.add(Begin{}) // TEST 33 + instructions.add(Begin{}) instructions.add(makeCheck(t.GetID())) if downDefined(t.GetArgs()) { @@ -233,18 +147,20 @@ func parseTerms( *postCount++ } instructions.add(Down{}) - subTerms := getFunctionalArguments(t.GetTyArgs(), t.GetArgs()) - subst = parseTerms(subTerms, instructions, subst, varCount, postCount) + if !t.GetTyArgs().Empty() { + Glob.Anomaly("unif parsing", "found type arguments at an unexpected place") + } + subst = parseTerms(t.GetArgs(), instructions, subst, varCount, postCount) if rightDefined(terms, i) { *postCount-- instructions.add(Pop{*postCount}) } instructions.add(makeEnd(t)) } else if rightDefined(terms, i) { - instructions.add(makeEnd(t)) // TEST33 + instructions.add(makeEnd(t)) instructions.add(Right{}) } else { - instructions.add(makeEnd(t)) // TEST33 + instructions.add(makeEnd(t)) } } } @@ -262,6 +178,6 @@ func ParseTerm(term AST.Term) Sequence { &varCount, &postCount, ) - instructions.formula = MakerTermForm(term) + instructions.base = Lib.MkLeft[AST.Term, AST.Form](term) return instructions } diff --git a/src/Unif/sequence.go b/src/Unif/sequence.go index 76a3717a..93ebf324 100644 --- a/src/Unif/sequence.go +++ b/src/Unif/sequence.go @@ -40,13 +40,42 @@ import ( "fmt" "github.com/GoelandProver/Goeland/AST" + "github.com/GoelandProver/Goeland/Glob" + "github.com/GoelandProver/Goeland/Lib" ) /*** Sequence ***/ +func tofToString(tof Lib.Either[AST.Term, AST.Form]) string { + return Lib.EitherToString[AST.Term, AST.Form](tof, "Trm", "Form") +} + +func tofCopy(tof Lib.Either[AST.Term, AST.Form]) Lib.Either[AST.Term, AST.Form] { + return Lib.EitherCpy[AST.Term, AST.Form](tof) +} + +func tofCmp(tof1, tof2 Lib.Either[AST.Term, AST.Form]) bool { + return Lib.EitherEquals[AST.Term, AST.Form](tof1, tof2) +} + +func tofMetaList(tof Lib.Either[AST.Term, AST.Form]) Lib.List[AST.Meta] { + switch tof := tof.(type) { + case Lib.Left[AST.Term, AST.Form]: + return transformTerm(tof.Val).GetMetaList() + case Lib.Right[AST.Term, AST.Form]: + switch f := tof.Val.(type) { + case AST.Pred: + return transformPred(f).GetMetaList() + } + } + + Glob.Anomaly("unification", "Unification has not been launched on terms or on a predicate") + return Lib.NewList[AST.Meta]() +} + type Sequence struct { instructions []Instruction - formula AST.Form + base Lib.Either[AST.Term, AST.Form] } /*** Sequence's methods ***/ @@ -55,22 +84,22 @@ func (s *Sequence) GetInstructions() []Instruction { return CopyInstructionList(s.instructions) } -func (s *Sequence) GetFormula() AST.Form { - return s.formula.Copy() +func (s *Sequence) GetBase() Lib.Either[AST.Term, AST.Form] { + return s.base } func (s *Sequence) add(instr Instruction) { s.instructions = append(s.instructions, instr) } -// ILL TODO: Should not print directly, should return a string that is then printed +// FIXME: Should not print directly, should return a string that is then printed func (s Sequence) Print() { for _, instr := range s.instructions { fmt.Printf("%v", instr) } - fmt.Printf(" - " + s.formula.ToString()) + fmt.Printf(" - " + tofToString(s.base)) } func (s Sequence) Copy() Sequence { - return Sequence{s.GetInstructions(), s.GetFormula()} + return Sequence{s.GetInstructions(), tofCopy(s.base)} } diff --git a/src/Unif/substitutions_tree.go b/src/Unif/substitutions_tree.go index 5a9be9e7..e1d03121 100644 --- a/src/Unif/substitutions_tree.go +++ b/src/Unif/substitutions_tree.go @@ -49,7 +49,11 @@ import ( * MetaToSubs : (meta, term) : meta in formula, term in tree * Merge both of them **/ -func computeSubstitutions(subs []SubstPair, metasToSubs Substitutions, form AST.Form) Substitutions { +func computeSubstitutions( + subs []SubstPair, + metasToSubs Substitutions, + metaList Lib.List[AST.Meta], +) Substitutions { debug( Lib.MkLazy(func() string { return fmt.Sprintf( @@ -57,56 +61,47 @@ func computeSubstitutions(subs []SubstPair, metasToSubs Substitutions, form AST. SubstPairListToString(subs), metasToSubs.ToString()) }), ) - metasFromTreeForm := Lib.NewList[AST.Meta]() treeSubs := Substitutions{} - // Retrieve all the meta of from the tree formula - switch typedForm := form.(type) { - case AST.Pred: - trms := getFunctionalArguments(typedForm.GetTyArgs(), typedForm.GetArgs()) - for _, trm := range trms.GetSlice() { - metasFromTreeForm.Append(trm.GetMetaList().GetSlice()...) - } - case TermForm: - metasFromTreeForm.Append(typedForm.GetTerm().GetMetaList().GetSlice()...) - default: - return Failure() - } - // Transform subst tree into a real substitution for _, value := range subs { - currentMeta := metasFromTreeForm.At(value.GetIndex()) - currentValue := value.GetTerm() - debug( - Lib.MkLazy(func() string { - return fmt.Sprintf( - "Iterate on subst : %v and %v", - currentMeta.ToString(), - currentValue.ToString()) - }), - ) + if value.GetIndex() < metaList.Len() { + currentMeta := metaList.At(value.GetIndex()) + currentValue := value.GetTerm() + debug( + Lib.MkLazy(func() string { + return fmt.Sprintf( + "Iterate on subst : %v and %v", + currentMeta.ToString(), + currentValue.ToString()) + }), + ) - if !currentMeta.Equals(currentValue) { - // Si current_meta a déjà une association dans metas - metaGet, index := metasToSubs.Get(currentMeta) - if HasSubst(metasToSubs, currentMeta) && (index != -1) && !currentValue.Equals(metaGet) { - // On cherche a unifier les deux valeurs - treeSubs.Set(currentMeta, currentValue) - new_unif := AddUnification(currentValue.Copy(), metaGet.Copy(), treeSubs.Copy()) - if new_unif.Equals(Failure()) { - return Failure() - } else { - treeSubs = new_unif - metasToSubs.Remove(index) // Remove from meta + if !currentMeta.Equals(currentValue) { + // Si current_meta a déjà une association dans metas + metaGet, index := metasToSubs.Get(currentMeta) + if HasSubst(metasToSubs, currentMeta) && (index != -1) && + !currentValue.Equals(metaGet) { + // On cherche a unifier les deux valeurs + treeSubs.Set(currentMeta, currentValue) + new_unif := AddUnification(currentValue.Copy(), metaGet.Copy(), treeSubs.Copy()) + if new_unif.Equals(Failure()) { + return Failure() + } else { + treeSubs = new_unif + metasToSubs.Remove(index) // Remove from meta + } + } else { // Ne pas ajouter la susbtitution égalité + treeSubs.Set(currentMeta, currentValue) } - } else { // Ne pas ajouter la susbtitution égalité - treeSubs.Set(currentMeta, currentValue) } } } debug( - Lib.MkLazy(func() string { return fmt.Sprintf("before meta : %v", metasToSubs.ToString()) }), + Lib.MkLazy( + func() string { return fmt.Sprintf("before meta : %v", metasToSubs.ToString()) }, + ), ) // Metas_subst eliminate EliminateMeta(&metasToSubs) @@ -114,10 +109,14 @@ func computeSubstitutions(subs []SubstPair, metasToSubs Substitutions, form AST. if metasToSubs.Equals(Failure()) { return Failure() } - debug(Lib.MkLazy(func() string { return fmt.Sprintf("After meta : %v", metasToSubs.ToString()) })) + debug( + Lib.MkLazy(func() string { return fmt.Sprintf("After meta : %v", metasToSubs.ToString()) }), + ) debug( - Lib.MkLazy(func() string { return fmt.Sprintf("before tree_subst : %v", treeSubs.ToString()) }), + Lib.MkLazy( + func() string { return fmt.Sprintf("before tree_subst : %v", treeSubs.ToString()) }, + ), ) // Tree subst elminate EliminateMeta(&treeSubs) @@ -126,7 +125,9 @@ func computeSubstitutions(subs []SubstPair, metasToSubs Substitutions, form AST. return Failure() } debug( - Lib.MkLazy(func() string { return fmt.Sprintf("after tree_subst : %v", treeSubs.ToString()) }), + Lib.MkLazy( + func() string { return fmt.Sprintf("after tree_subst : %v", treeSubs.ToString()) }, + ), ) // Fusion @@ -152,7 +153,9 @@ func computeSubstitutions(subs []SubstPair, metasToSubs Substitutions, form AST. /* Call addUnification and returns a status - modify m.meta */ func (m *Machine) trySubstituteMeta(i AST.Term, j AST.Term) Status { debug( - Lib.MkLazy(func() string { return fmt.Sprintf("Try substitute : %v and %v", i.ToString(), j.ToString()) }), + Lib.MkLazy( + func() string { return fmt.Sprintf("Try substitute : %v and %v", i.ToString(), j.ToString()) }, + ), ) new_meta := AddUnification(i, j, m.meta.Copy()) if new_meta.Equals(Failure()) { @@ -172,6 +175,9 @@ func AddUnification(term1, term2 AST.Term, subst Substitutions) Substitutions { subst.ToString()) }), ) + term1 = transformTerm(term1) + term2 = transformTerm(term2) + // unify with ct only if the term already has an unification or if there is 2 fun. Just add it and eliminate otherwise. t1v, _ := subst.Get(term1.ToMeta()) t2v, _ := subst.Get(term2.ToMeta()) @@ -213,12 +219,16 @@ func (m *Machine) addUnifications(term1, term2 AST.Term) Status { term2.ToString()) }), ) - meta := tryUnification(term1.Copy(), term2.Copy(), m.meta.Copy()) // Return empty or an array of 1 matching substitution, which is m.meta improved wit (term1, term2) + meta := tryUnification( + term1.Copy(), + term2.Copy(), + m.meta.Copy(), + ) // Return empty or an array of 1 matching substitution, which is m.meta improved wit (term1, term2) if len(meta) == 0 { return Status(ERROR) } else { - m.meta = meta[0].GetSubst() + m.meta = meta[0].subst EliminateMeta(&m.meta) Eliminate(&m.meta) } @@ -227,7 +237,7 @@ func (m *Machine) addUnifications(term1, term2 AST.Term) Status { } /* Tries to unify term1 with term2, depending on the substitutions already found by the parent unification process. */ -func tryUnification(term1, term2 AST.Term, meta Substitutions) []MatchingSubstitutions { +func tryUnification(term1, term2 AST.Term, meta Substitutions) []MixMatchSubstitutions { debug( Lib.MkLazy(func() string { return fmt.Sprintf( From ed4d701de5d29be7abd677fa8b2aee36018426e7 Mon Sep 17 00:00:00 2001 From: Johann Rosain Date: Thu, 26 Mar 2026 14:16:46 +0100 Subject: [PATCH 29/30] clean: nameless bound variables --- src/AST/bin-form.go | 100 +++ src/AST/form-list.go | 8 - src/AST/forms-def.go | 749 +++++------------- src/AST/formula.go | 103 +-- src/AST/maker.go | 67 +- src/AST/modular-printing.go | 46 +- src/AST/{typed-vars.go => nari-forms.go} | 63 +- src/AST/printers.go | 10 +- src/AST/quantifiers.go | 122 ++- src/AST/term-list.go | 49 -- src/AST/term.go | 18 +- src/AST/terms-def.go | 227 +++--- src/AST/ty-syntax.go | 385 +++++---- src/Core/FormListDS.go | 10 +- src/Core/Sko/inner-skolemization.go | 6 +- src/Core/Sko/interface.go | 1 - src/Core/Sko/outer-skolemization.go | 6 +- src/Core/Sko/preinner-skolemization.go | 121 +-- src/Core/form_and_terms.go | 9 +- .../{instanciation.go => instantiation.go} | 32 +- src/Core/skolemisation.go | 27 +- src/Core/substitutions_search.go | 22 +- src/Engine/pretyper.go | 26 +- src/Engine/syntax-translation.go | 177 +++-- src/Engine/tptp-defined-types.go | 16 +- src/Lib/list.go | 5 + src/Lib/pair.go | 4 + .../CertifUtils/epsilon-terms-management.go | 4 +- src/Mods/dmt/rewritten.go | 2 +- src/Mods/equality/bse/equality_problem.go | 29 +- .../equality/bse/equality_problem_list.go | 66 +- src/Mods/equality/bse/equality_rules_apply.go | 64 +- .../equality/bse/equality_rules_try_apply.go | 2 +- src/Mods/equality/bse/equality_types.go | 12 +- src/Mods/lambdapi/output.go | 7 +- src/Mods/lambdapi/proof.go | 60 +- src/Mods/rocq/output.go | 7 +- src/Search/destructive.go | 721 ++++++++++++++--- src/Search/incremental/rules.go | 26 +- src/Search/nonDestructiveSearch.go | 131 ++- src/Search/proof-adapter.go | 88 +- src/Search/rules.go | 39 +- src/Typing/env-and-context.go | 74 +- src/Typing/init.go | 35 +- src/Typing/rules.go | 85 +- src/Unif/matching_substitutions.go | 4 +- src/Unif/parsing.go | 4 +- 47 files changed, 2101 insertions(+), 1768 deletions(-) create mode 100644 src/AST/bin-form.go rename src/AST/{typed-vars.go => nari-forms.go} (58%) rename src/Core/{instanciation.go => instantiation.go} (77%) diff --git a/src/AST/bin-form.go b/src/AST/bin-form.go new file mode 100644 index 00000000..7e18d3c2 --- /dev/null +++ b/src/AST/bin-form.go @@ -0,0 +1,100 @@ +/** +* Copyright 2022 by the authors (see AUTHORS). +* +* Goéland is an automated theorem prover for first order logic. +* +* This software is governed by the CeCILL license under French law and +* abiding by the rules of distribution of free software. You can use, +* modify and/ or redistribute the software under the terms of the CeCILL +* license as circulated by CEA, CNRS and INRIA at the following URL +* "http://www.cecill.info". +* +* As a counterpart to the access to the source code and rights to copy, +* modify and redistribute granted by the license, users are provided only +* with a limited warranty and the software's author, the holder of the +* economic rights, and the successive licensors have only limited +* liability. +* +* In this respect, the user's attention is drawn to the risks associated +* with loading, using, modifying and/or developing or reproducing the +* software by the user in light of its specific status of free software, +* that may mean that it is complicated to manipulate, and that also +* therefore means that it is reserved for developers and experienced +* professionals having in-depth computer knowledge. Users are therefore +* encouraged to load and test the software's suitability as regards their +* requirements in conditions enabling the security of their systems and/or +* data to be ensured and, more generally, to use and operate it in the +* same conditions as regards security. +* +* The fact that you are presently reading this means that you have had +* knowledge of the CeCILL license and that you accept its terms. +**/ + +/** + * This file implements binary formulas (imp, equ) + **/ + +package AST + +import ( + "fmt" + + "github.com/GoelandProver/Goeland/Lib" +) + +type bin_form struct { + left Form + right Form +} + +func makeBinForm(left, right Form) bin_form { + return bin_form{left, right} +} + +func (b bin_form) GetF1() Form { + return b.left +} + +func (b bin_form) GetF2() Form { + return b.right +} + +func (b bin_form) copy() bin_form { + return makeBinForm(b.left.Copy(), b.right.Copy()) +} + +func (b bin_form) GetChildFormulas() Lib.List[Form] { + return Lib.MkListV(b.left, b.right) +} + +func (b bin_form) GetMetas() Lib.Set[Meta] { + return listUnion(b.GetChildFormulas(), Form.GetMetas) +} + +func (b bin_form) toString(n int, conn Connective) string { + return printer.Str(fmt.Sprintf("%s %s %s", + printer.Str(printer.SurroundChild(b.left.toString(n))), + printer.StrConn(conn), + printer.Str(printer.SurroundChild(b.right.toString(n))), + )) +} + +func (b bin_form) equals(oth bin_form) bool { + return b.left.Equals(oth.left) && b.right.Equals(oth.right) +} + +func (b bin_form) applyOnArgs(f func(Form) Form) bin_form { + return makeBinForm(f(b.left), f(b.right)) +} + +func (b bin_form) GetSubTerms() Lib.Set[Term] { + return listUnion(b.GetChildFormulas(), Form.GetSubTerms) +} + +func (b bin_form) GetSymbols() Lib.Set[Id] { + return listUnion(b.GetChildFormulas(), Form.GetSymbols) +} + +func (b bin_form) less(oth bin_form) bool { + return b.left.Less(oth.left) || (b.left.Equals(oth.left) && b.right.Less(oth.right)) +} diff --git a/src/AST/form-list.go b/src/AST/form-list.go index 8c023ac8..42aede55 100644 --- a/src/AST/form-list.go +++ b/src/AST/form-list.go @@ -40,14 +40,6 @@ import ( "github.com/GoelandProver/Goeland/Lib" ) -// ex-name: ReplaceMetaByTerm -func LsSubstByTerm(formulas Lib.List[Form], meta Meta, term Term) Lib.List[Form] { - for i, f := range formulas.GetSlice() { - formulas.Upd(i, f.ReplaceMetaByTerm(meta, term)) - } - return formulas -} - func LsFlatten(formulas Lib.List[Form]) Lib.List[Form] { result := Lib.NewList[Form]() diff --git a/src/AST/forms-def.go b/src/AST/forms-def.go index 765a3413..ab56fa08 100644 --- a/src/AST/forms-def.go +++ b/src/AST/forms-def.go @@ -39,7 +39,6 @@ package AST import ( "fmt" - "github.com/GoelandProver/Goeland/Glob" "github.com/GoelandProver/Goeland/Lib" ) @@ -54,32 +53,6 @@ func getAllSubFormulasAppended(f Form) Lib.List[Form] { return subforms } -func substVarByMetaInFormList( - old Var, - new Meta, - formList Lib.List[Form], - metas Lib.Set[Meta], -) (replacedFormList Lib.List[Form], newMetas Lib.Set[Meta]) { - replacedFormList = Lib.NewList[Form]() - newMetas = metas.Copy() - found := false - - for _, form := range formList.GetSlice() { - replacedForm := form.SubstituteVarByMeta(old, new) - replacedFormList.Append(replacedForm) - - if replacedForm.GetMetas().Contains(new) { - found = true - } - } - - if found { - newMetas.Add(new) - } - - return replacedFormList, newMetas -} - // ----------------------------------------------------------------------------- // Forall @@ -87,8 +60,8 @@ type All struct { quantifier } -func MakeAllSimple(vars Lib.List[TypedVar], forms Form, metas Lib.Set[Meta]) All { - return All{makeQuantifier(vars, forms, metas, ConnAll)} +func MakeAllSimple(ty Ty, forms Form) All { + return All{makeQuantifier(ty, forms, ConnAll)} } func (a All) Equals(other any) bool { @@ -103,31 +76,40 @@ func (a All) GetSubFormulasRecur() Lib.List[Form] { } func (a All) Copy() Form { - return All{a.quantifier.copy()} + return All{a.copy()} +} + +func (a All) Subst(x Meta, t Term) Form { + return All{a.applyOnSubForm(func(f Form) Form { return f.Subst(x, t) })} } -func (a All) ReplaceTermByTerm(old Term, new Term) (Form, bool) { - quant, isReplaced := a.quantifier.replaceTermByTerm(old, new) - return All{quant}, isReplaced +func (a All) Instantiate(x Var, t Term) Form { + return All{a.applyOnSubForm(func(f Form) Form { return f.Instantiate(x.increase(), t) })} } -func (a All) SubstTy(old TyGenVar, new Ty) Form { - return All{a.quantifier.replaceTyVar(old, new)} +func (a All) SubstTy(old TyMeta, new Ty) Form { + return All{ + a.applyOnSubForm(func(f Form) Form { return f.SubstTy(old, new) }). + applyOnTy(func(t Ty) Ty { return t.SubstTy(old, new) }), + } } -func (a All) SubstituteVarByMeta(old Var, new Meta) Form { - return All{a.quantifier.substituteVarByMeta(old, new)} +func (a All) InstantiateTy(old TyBound, new Ty) Form { + return All{ + a.applyOnSubForm(func(f Form) Form { return f.InstantiateTy(old.Increase(), new) }). + applyOnTy(func(t Ty) Ty { return t.Instantiate(old.Increase(), new) }), + } } -func (a All) ReplaceMetaByTerm(meta Meta, term Term) Form { - return All{a.quantifier.replaceMetaByTerm(meta, term)} +func (a All) ReplaceTerm(t, u Term) Form { + return All{a.applyOnSubForm(func(f Form) Form { return f.ReplaceTerm(t, u) })} } func (a All) Less(oth any) bool { if form, is_form := oth.(Form); is_form { switch f := form.(type) { case All: - return qLess(a.varList, f.varList, a.subForm, f.subForm) + return qLess(a.ty, f.ty, a.subForm, f.subForm) default: return false } @@ -142,10 +124,6 @@ type Ex struct { quantifier } -func MakeExSimple(vars Lib.List[TypedVar], forms Form, metas Lib.Set[Meta]) Ex { - return Ex{makeQuantifier(vars, forms, metas, ConnEx)} -} - func (e Ex) Equals(other any) bool { if typed, ok := other.(Ex); ok { return e.quantifier.Equals(typed.quantifier) @@ -158,24 +136,33 @@ func (e Ex) GetSubFormulasRecur() Lib.List[Form] { } func (e Ex) Copy() Form { - return Ex{e.quantifier.copy()} + return Ex{e.copy()} } -func (e Ex) ReplaceTermByTerm(old Term, new Term) (Form, bool) { - quant, isReplaced := e.quantifier.replaceTermByTerm(old, new) - return Ex{quant}, isReplaced +func (e Ex) Instantiate(x Var, t Term) Form { + return Ex{e.applyOnSubForm(func(f Form) Form { return f.Instantiate(x.increase(), t) })} } -func (e Ex) SubstTy(old TyGenVar, new Ty) Form { - return Ex{e.quantifier.replaceTyVar(old, new)} +func (e Ex) Subst(x Meta, t Term) Form { + return Ex{e.applyOnSubForm(func(f Form) Form { return f.Subst(x, t) })} } -func (e Ex) SubstituteVarByMeta(old Var, new Meta) Form { - return Ex{e.quantifier.substituteVarByMeta(old, new)} +func (e Ex) ReplaceTerm(t, u Term) Form { + return Ex{e.applyOnSubForm(func(f Form) Form { return f.ReplaceTerm(t, u) })} } -func (e Ex) ReplaceMetaByTerm(meta Meta, term Term) Form { - return Ex{e.quantifier.replaceMetaByTerm(meta, term)} +func (e Ex) SubstTy(old TyMeta, new Ty) Form { + return Ex{ + e.applyOnSubForm(func(f Form) Form { return f.SubstTy(old, new) }). + applyOnTy(func(t Ty) Ty { return t.SubstTy(old, new) }), + } +} + +func (e Ex) InstantiateTy(old TyBound, new Ty) Form { + return Ex{ + e.applyOnSubForm(func(f Form) Form { return f.InstantiateTy(old.Increase(), new) }). + applyOnTy(func(t Ty) Ty { return t.Instantiate(old.Increase(), new) }), + } } func (e Ex) Less(oth any) bool { @@ -184,7 +171,7 @@ func (e Ex) Less(oth any) bool { case All: return true case Ex: - return qLess(e.varList, f.varList, e.subForm, f.subForm) + return qLess(e.ty, f.ty, e.subForm, f.subForm) default: return false } @@ -196,96 +183,48 @@ func (e Ex) Less(oth any) bool { // Or type Or struct { - forms Lib.List[Form] - metas Lib.Cache[Lib.Set[Meta], Or] -} - -/** Constructors **/ - -func MakeOrSimple(forms Lib.List[Form], metas Lib.Set[Meta]) Or { - return Or{forms, Lib.MkCache(metas, Or.forceGetMetas)} -} - -/** Methods **/ - -/** - Form interface Methods **/ - -func (o Or) forceGetMetas() Lib.Set[Meta] { - return metasUnion(o.forms) -} - -func (o Or) GetMetas() Lib.Set[Meta] { - return o.metas.Get(o) -} - -func (o Or) GetSubTerms() Lib.Set[Term] { - res := Lib.EmptySet[Term]() - - for _, tl := range o.forms.GetSlice() { - res = res.Union(tl.GetSubTerms()) - } - - return res -} - -func (o Or) GetSymbols() Lib.Set[Id] { - res := Lib.EmptySet[Id]() - - for _, tl := range o.forms.GetSlice() { - res = res.Union(tl.GetSymbols()) - } - - return res + nari_form } func (o Or) Equals(f any) bool { oth, isOr := f.(Or) - return isOr && Lib.ListEquals(oth.forms, o.forms) + return isOr && o.equals(oth.nari_form) } func (o Or) Copy() Form { - return Or{ - Lib.ListCpy(o.forms), - o.metas.Copy(Lib.Set[Meta].Copy), - } + return Or{o.copy()} +} + +func (o Or) toString(n int) string { + return o.nari_form.toString(n, ConnOr) } func (o Or) ToString() string { - return o.forms.ToString( - func(f Form) string { return printer.Str(printer.SurroundChild(f.ToString())) }, - printer.StrConn(ConnOr), "", - ) + return o.toString(0) } -func (o Or) ReplaceTermByTerm(old Term, new Term) (Form, bool) { - formList, res := replaceTermInFormList(o.forms, old, new) - no := MakeOrSimple(formList, o.metas.Raw()) - if !res && !o.metas.NeedsUpd() { - no.metas.AvoidUpd() - } - return no, res +func (o Or) Subst(x Meta, t Term) Form { + return Or{o.applyOnArgs(func(f Form) Form { return f.Subst(x, t) })} } -func (o Or) SubstTy(old TyGenVar, new Ty) Form { - formList := replaceTyVarInFormList(o.forms, old, new) - return MakeOrSimple(formList, o.metas.Raw()) +func (o Or) Instantiate(x Var, t Term) Form { + return Or{o.applyOnArgs(func(f Form) Form { return f.Instantiate(x, t) })} } -func (o Or) SubstituteVarByMeta(old Var, new Meta) Form { - newFormList, newMetas := substVarByMetaInFormList(old, new, o.forms, o.metas.Raw()) - return MakeOrSimple(newFormList, newMetas) +func (o Or) SubstTy(old TyMeta, new Ty) Form { + return Or{o.applyOnArgs(func(f Form) Form { return f.SubstTy(old, new) })} } -func (o Or) GetSubFormulasRecur() Lib.List[Form] { - return getAllSubFormulasAppended(o) +func (o Or) InstantiateTy(old TyBound, new Ty) Form { + return Or{o.applyOnArgs(func(f Form) Form { return f.InstantiateTy(old, new) })} } -func (o Or) GetChildFormulas() Lib.List[Form] { - return o.forms +func (o Or) ReplaceTerm(t, u Term) Form { + return Or{o.applyOnArgs(func(f Form) Form { return f.ReplaceTerm(t, u) })} } -func (o Or) ReplaceMetaByTerm(meta Meta, term Term) Form { - return MakeOr(LsSubstByTerm(o.forms, meta, term)) +func (o Or) GetSubFormulasRecur() Lib.List[Form] { + return getAllSubFormulasAppended(o) } func (o Or) Less(oth any) bool { @@ -294,7 +233,7 @@ func (o Or) Less(oth any) bool { case All, Ex: return true case Or: - return bLess(o.forms, f.forms) + return o.less(f.nari_form) default: return false } @@ -306,120 +245,57 @@ func (o Or) Less(oth any) bool { // And type And struct { - forms Lib.List[Form] - metas Lib.Cache[Lib.Set[Meta], And] -} - -/** Constructors **/ - -func MakeAndSimple(forms Lib.List[Form], metas Lib.Set[Meta]) And { - return And{forms, Lib.MkCache(metas, And.forceGetMetas)} -} - -func MakeAndSimpleBinary(forms Lib.List[Form], metas Lib.Set[Meta]) And { - switch forms.Len() { - // FIXME: case 0 and 1 should error, no? - case 0, 1, 2: - return MakeAndSimple(forms, metas) - default: - return MakeAndSimple( - Lib.MkListV[Form](forms.At(0), MakeAnd(forms.Slice(1, forms.Len()), true)), - metas) - } + nari_form } -/** Methods **/ - -/** - Form interface Methods **/ - -func (a And) forceGetMetas() Lib.Set[Meta] { - return metasUnion(a.forms) -} - -func (a And) GetMetas() Lib.Set[Meta] { - return a.metas.Get(a) +func (a And) Equals(f any) bool { + oth, isAnd := f.(And) + return isAnd && a.equals(oth.nari_form) } -func (a And) GetSubTerms() Lib.Set[Term] { - res := Lib.EmptySet[Term]() - - for _, tl := range a.forms.GetSlice() { - res = res.Union(tl.GetSubTerms()) - } - - return res +func (a And) Copy() Form { + return And{a.copy()} } -func (a And) GetSymbols() Lib.Set[Id] { - res := Lib.EmptySet[Id]() - - for _, tl := range a.forms.GetSlice() { - res = res.Union(tl.GetSymbols()) - } - - return res +func (a And) toString(n int) string { + return a.nari_form.toString(n, ConnAnd) } -func (a And) Equals(other any) bool { - if typed, ok := other.(And); ok { - return Lib.ListEquals(typed.forms, a.forms) - } - - return false +func (a And) ToString() string { + return a.toString(0) } -func (a And) Copy() Form { - return And{ - Lib.ListCpy(a.forms), - a.metas.Copy(Lib.Set[Meta].Copy), - } +func (a And) Subst(x Meta, t Term) Form { + return And{a.applyOnArgs(func(f Form) Form { return f.Subst(x, t) })} } -func (a And) ToString() string { - return a.forms.ToString( - func(f Form) string { return printer.Str(printer.SurroundChild(f.ToString())) }, - printer.StrConn(ConnAnd), "", - ) +func (a And) Instantiate(x Var, t Term) Form { + return And{a.applyOnArgs(func(f Form) Form { return f.Instantiate(x, t) })} } -func (a And) ReplaceTermByTerm(old Term, new Term) (Form, bool) { - varList, res := replaceTermInFormList(a.forms, old, new) - na := MakeAndSimple(varList, a.metas.Raw()) - if !res && !a.metas.NeedsUpd() { - na.metas.AvoidUpd() - } - return na, res +func (a And) SubstTy(old TyMeta, new Ty) Form { + return And{a.applyOnArgs(func(f Form) Form { return f.SubstTy(old, new) })} } -func (a And) SubstTy(old TyGenVar, new Ty) Form { - formList := replaceTyVarInFormList(a.forms, old, new) - return MakeAndSimple(formList, a.metas.Raw()) +func (a And) InstantiateTy(old TyBound, new Ty) Form { + return And{a.applyOnArgs(func(f Form) Form { return f.InstantiateTy(old, new) })} } -func (a And) SubstituteVarByMeta(old Var, new Meta) Form { - newFormList, newMetas := substVarByMetaInFormList(old, new, a.forms, a.metas.Raw()) - return MakeAndSimple(newFormList, newMetas) +func (a And) ReplaceTerm(t, u Term) Form { + return And{a.applyOnArgs(func(f Form) Form { return f.ReplaceTerm(t, u) })} } func (a And) GetSubFormulasRecur() Lib.List[Form] { return getAllSubFormulasAppended(a) } -func (a And) GetChildFormulas() Lib.List[Form] { - return a.forms -} - -func (a And) ReplaceMetaByTerm(meta Meta, term Term) Form { - return MakeAnd(LsSubstByTerm(a.forms, meta, term)) -} - func (a And) Less(oth any) bool { if form, is_form := oth.(Form); is_form { switch f := form.(type) { case All, Ex, Or: return true case And: - return bLess(a.forms, f.forms) + return a.less(f.nari_form) default: return false } @@ -431,108 +307,57 @@ func (a And) Less(oth any) bool { // Equivalence type Equ struct { - f1, f2 Form - metas Lib.Cache[Lib.Set[Meta], Equ] + bin_form } -func MakeEquSimple(firstForm, secondForm Form, metas Lib.Set[Meta]) Equ { - return Equ{ - firstForm, - secondForm, - Lib.MkCache(metas, Equ.forceGetMetas), - } -} - -func (e Equ) GetF1() Form { return e.f1.Copy() } -func (e Equ) GetF2() Form { return e.f2.Copy() } func (e Equ) Copy() Form { - return Equ{ - e.GetF1(), - e.GetF2(), - e.metas.Copy(Lib.Set[Meta].Copy), - } -} - -func (e Equ) forceGetMetas() Lib.Set[Meta] { - allMetas := e.f1.GetMetas().Copy() - allMetas = allMetas.Union(e.f2.GetMetas()) - - return allMetas + return Equ{e.copy()} } -func (e Equ) GetMetas() Lib.Set[Meta] { - return e.metas.Get(e) +func (e Equ) toString(n int) string { + return e.bin_form.toString(n, ConnEqu) } func (e Equ) ToString() string { - return printer.Str(fmt.Sprintf("%s %s %s", - printer.Str(printer.SurroundChild(e.f1.ToString())), - printer.StrConn(ConnEqu), - printer.Str(printer.SurroundChild(e.f2.ToString())), - )) + return e.toString(0) } func (e Equ) Equals(f any) bool { oth, isEqu := f.(Equ) - return isEqu && - e.f1.Equals(oth.f1) && e.f2.Equals(oth.f2) + return isEqu && e.equals(oth.bin_form) } -func (e Equ) ReplaceTermByTerm(old Term, new Term) (Form, bool) { - f1, res1 := e.GetF1().ReplaceTermByTerm(old, new) - f2, res2 := e.GetF2().ReplaceTermByTerm(old, new) - ne := MakeEquSimple(f1, f2, e.metas.Raw()) - - if !res1 && !res2 && !e.metas.NeedsUpd() { - e.metas.AvoidUpd() - } - - return ne, res1 || res2 +func (e Equ) Instantiate(x Var, t Term) Form { + return Equ{e.applyOnArgs(func(f Form) Form { return f.Instantiate(x, t) })} } -func (e Equ) SubstTy(old TyGenVar, new Ty) Form { - return MakeEquSimple( - e.f1.SubstTy(old, new), - e.f2.SubstTy(old, new), - e.metas.Raw(), - ) +func (e Equ) Subst(x Meta, t Term) Form { + return Equ{e.applyOnArgs(func(f Form) Form { return f.Subst(x, t) })} } -func (e Equ) GetSubTerms() Lib.Set[Term] { - return e.GetF1().GetSubTerms().Union(e.GetF2().GetSubTerms()) +func (e Equ) SubstTy(old TyMeta, new Ty) Form { + return Equ{e.applyOnArgs(func(f Form) Form { return f.SubstTy(old, new) })} } -func (e Equ) GetSymbols() Lib.Set[Id] { - return e.GetF1().GetSymbols().Union(e.GetF2().GetSymbols()) +func (e Equ) InstantiateTy(old TyBound, new Ty) Form { + return Equ{e.applyOnArgs(func(f Form) Form { return f.InstantiateTy(old, new) })} } -func (e Equ) SubstituteVarByMeta(old Var, new Meta) Form { - fl, metas := substVarByMetaInFormList(old, new, Lib.MkListV(e.f1, e.f2), e.metas.Raw()) - return MakeEquSimple(fl.At(0), fl.At(1), metas) +func (e Equ) ReplaceTerm(t, u Term) Form { + return Equ{e.applyOnArgs(func(f Form) Form { return f.ReplaceTerm(t, u) })} } func (e Equ) GetSubFormulasRecur() Lib.List[Form] { return getAllSubFormulasAppended(e) } -func (e Equ) GetChildFormulas() Lib.List[Form] { - return Lib.MkListV(e.f1, e.f2) -} - -func (e Equ) ReplaceMetaByTerm(meta Meta, term Term) Form { - return MakeEqu( - e.f1.ReplaceMetaByTerm(meta, term), - e.f2.ReplaceMetaByTerm(meta, term), - ) -} - func (e Equ) Less(oth any) bool { if form, is_form := oth.(Form); is_form { switch f := form.(type) { case All, Ex, Or, And: return true case Equ: - return bLess(Lib.MkListV(e.f1, e.f2), Lib.MkListV(f.f1, f.f2)) + return e.less(f.bin_form) default: return false } @@ -544,111 +369,57 @@ func (e Equ) Less(oth any) bool { // Implication type Imp struct { - f1, f2 Form - metas Lib.Cache[Lib.Set[Meta], Imp] -} - -func MakeImpSimple(firstForm, secondForm Form, metas Lib.Set[Meta]) Imp { - return Imp{ - firstForm, - secondForm, - Lib.MkCache(metas, Imp.forceGetMetas), - } + bin_form } -func (i Imp) GetF1() Form { return i.f1.Copy() } -func (i Imp) GetF2() Form { return i.f2.Copy() } func (i Imp) Copy() Form { - return Imp{ - i.GetF1(), - i.GetF2(), - i.metas.Copy(Lib.Set[Meta].Copy), - } -} - -func (i Imp) forceGetMetas() Lib.Set[Meta] { - allMetas := i.f1.GetMetas().Copy() - allMetas = allMetas.Union(i.f2.GetMetas()) - - return allMetas + return Imp{i.copy()} } -func (i Imp) GetMetas() Lib.Set[Meta] { - return i.metas.Get(i) +func (i Imp) toString(n int) string { + return i.bin_form.toString(n, ConnImp) } func (i Imp) ToString() string { - return printer.Str(fmt.Sprintf("%s %s %s", - printer.Str(printer.SurroundChild(i.f1.ToString())), - printer.StrConn(ConnImp), - printer.Str(printer.SurroundChild(i.f2.ToString())), - )) + return i.toString(0) } -func (i Imp) Equals(other any) bool { - if typed, ok := other.(Imp); ok { - return i.f1.Equals(typed.f1) && i.f2.Equals(typed.f2) - } - - return false +func (i Imp) Equals(f any) bool { + oth, isImp := f.(Imp) + return isImp && i.equals(oth.bin_form) } -func (i Imp) ReplaceTermByTerm(old Term, new Term) (Form, bool) { - f1, res1 := i.GetF1().ReplaceTermByTerm(old, new) - f2, res2 := i.GetF2().ReplaceTermByTerm(old, new) - - ni := MakeImpSimple(f1, f2, i.metas.Raw()) - - if !res1 && !res2 && !i.metas.NeedsUpd() { - ni.metas.AvoidUpd() - } - - return ni, res1 || res2 +func (i Imp) Instantiate(x Var, t Term) Form { + return Imp{i.applyOnArgs(func(f Form) Form { return f.Instantiate(x, t) })} } -func (i Imp) SubstTy(old TyGenVar, new Ty) Form { - return MakeImpSimple( - i.f1.SubstTy(old, new), - i.f2.SubstTy(old, new), - i.metas.Raw(), - ) +func (i Imp) Subst(x Meta, t Term) Form { + return Imp{i.applyOnArgs(func(f Form) Form { return f.Subst(x, t) })} } -func (i Imp) GetSubTerms() Lib.Set[Term] { - return i.GetF1().GetSubTerms().Union(i.GetF2().GetSubTerms()) +func (i Imp) SubstTy(old TyMeta, new Ty) Form { + return Imp{i.applyOnArgs(func(f Form) Form { return f.SubstTy(old, new) })} } -func (i Imp) GetSymbols() Lib.Set[Id] { - return i.GetF1().GetSymbols().Union(i.GetF2().GetSymbols()) +func (i Imp) InstantiateTy(old TyBound, new Ty) Form { + return Imp{i.applyOnArgs(func(f Form) Form { return f.InstantiateTy(old, new) })} } -func (i Imp) SubstituteVarByMeta(old Var, new Meta) Form { - fl, metas := substVarByMetaInFormList(old, new, Lib.MkListV(i.f1, i.f2), i.metas.Raw()) - return MakeImpSimple(fl.At(0), fl.At(1), metas) +func (i Imp) ReplaceTerm(t, u Term) Form { + return Imp{i.applyOnArgs(func(f Form) Form { return f.ReplaceTerm(t, u) })} } func (i Imp) GetSubFormulasRecur() Lib.List[Form] { return getAllSubFormulasAppended(i) } -func (i Imp) GetChildFormulas() Lib.List[Form] { - return Lib.MkListV(i.f1, i.f2) -} - -func (i Imp) ReplaceMetaByTerm(meta Meta, term Term) Form { - return MakeImp( - i.f1.ReplaceMetaByTerm(meta, term), - i.f2.ReplaceMetaByTerm(meta, term), - ) -} - func (i Imp) Less(oth any) bool { if form, is_form := oth.(Form); is_form { switch f := form.(type) { case All, Ex, Or, And, Equ: return true case Imp: - return bLess(Lib.MkListV(i.f1, i.f2), Lib.MkListV(f.f1, f.f2)) + return i.less(f.bin_form) default: return false } @@ -660,34 +431,23 @@ func (i Imp) Less(oth any) bool { // Not type Not struct { - f Form - metas Lib.Cache[Lib.Set[Meta], Not] -} - -/** Constructors **/ - -func MakeNotSimple(form Form, metas Lib.Set[Meta]) Not { - return Not{form, Lib.MkCache(metas, Not.forceGetMetas)} + f Form } /** Methods **/ /** - Form interface Methods **/ -func (n Not) forceGetMetas() Lib.Set[Meta] { - return n.GetForm().GetMetas() -} - func (n Not) GetMetas() Lib.Set[Meta] { - return n.metas.Get(n) + return n.f.GetMetas() } func (n Not) GetSubTerms() Lib.Set[Term] { - return n.GetForm().GetSubTerms() + return n.f.GetSubTerms() } func (n Not) GetSymbols() Lib.Set[Id] { - return n.GetForm().GetSymbols() + return n.f.GetSymbols() } func (n Not) Equals(other any) bool { @@ -699,40 +459,38 @@ func (n Not) Equals(other any) bool { } func (n Not) Copy() Form { - nn := MakeNotSimple(n.GetForm(), n.metas.Raw().Copy()) - if !n.metas.NeedsUpd() { - nn.metas.AvoidUpd() - } - return nn + return Not{n.f.Copy()} } -func (n Not) ToString() string { +func (n Not) toString(i int) string { return printer.Str(fmt.Sprintf("%s%s", printer.StrConn(ConnNot), - printer.Str(printer.SurroundChild(n.f.ToString())), + printer.Str(printer.SurroundChild(n.f.toString(i))), )) } -func (n Not) ReplaceTermByTerm(old Term, new Term) (Form, bool) { - f, res := n.f.ReplaceTermByTerm(old, new) +func (n Not) ToString() string { + return n.toString(0) +} - nn := MakeNotSimple(f, n.metas.Raw()) - if !res && !n.metas.NeedsUpd() { - nn.metas.AvoidUpd() - } +func (n Not) Instantiate(x Var, t Term) Form { + return MakeNot(n.f.Instantiate(x, t)) +} - return nn, res +func (n Not) Subst(x Meta, t Term) Form { + return MakeNot(n.f.Subst(x, t)) } -func (n Not) SubstTy(old TyGenVar, new Ty) Form { - return MakeNotSimple( - n.f.SubstTy(old, new), - n.metas.Raw(), - ) +func (n Not) SubstTy(old TyMeta, new Ty) Form { + return MakeNot(n.f.SubstTy(old, new)) +} + +func (n Not) InstantiateTy(old TyBound, new Ty) Form { + return MakeNot(n.f.InstantiateTy(old, new)) } -func (n Not) ReplaceMetaByTerm(meta Meta, term Term) Form { - return MakeNot(n.f.ReplaceMetaByTerm(meta, term)) +func (n Not) ReplaceTerm(t, u Term) Form { + return MakeNot(n.f.ReplaceTerm(t, u)) } /** - Other Methods **/ @@ -741,11 +499,6 @@ func (n Not) GetForm() Form { return n.f.Copy() } -func (n Not) SubstituteVarByMeta(old Var, new Meta) Form { - f := n.GetForm().SubstituteVarByMeta(old, new) - return MakeNotSimple(f, f.GetMetas().Copy()) -} - func (n Not) GetSubFormulasRecur() Lib.List[Form] { return getAllSubFormulasAppended(n) } @@ -756,7 +509,7 @@ func (n Not) GetChildFormulas() Lib.List[Form] { /** Utils **/ -/* Gives a new Form that isn't a Not */ +/* Recursively removes negations until getting the base formula */ func RemoveNeg(form Form) Form { form, _ = getDeepFormWithoutNot(form, true) return form @@ -773,6 +526,7 @@ func SimplifyNegations(form Form) Form { return form } +// FIXME: this function does two things and is thus not named properly func getDeepFormWithoutNot(form Form, isEven bool) (Form, bool) { if not, isNot := form.(Not); isNot { return getDeepFormWithoutNot(not.GetForm(), !isEven) @@ -799,24 +553,9 @@ func (n Not) Less(oth any) bool { // Predicates type Pred struct { - id Id - tys Lib.List[Ty] - args Lib.List[Term] - metas Lib.Cache[Lib.Set[Meta], Pred] -} - -func MakePredSimple( - id Id, - tys Lib.List[Ty], - terms Lib.List[Term], - metas Lib.Set[Meta], -) Pred { - return Pred{ - id, - tys, - terms, - Lib.MkCache(metas, Pred.forceGetMetas), - } + id Id + tys Lib.List[Ty] + args Lib.List[Term] } /* Pred attributes getters */ @@ -827,27 +566,20 @@ func (p Pred) GetArgs() Lib.List[Term] { return p.args } /* Formula methods */ -func (p Pred) ToString() string { +func (p Pred) toString(n int) string { return printer.StrFunctional( p.id, - Lib.ListMap(p.tys, Ty.ToString), - Lib.ListMap(p.args, Term.ToString), + Lib.ListMap(p.tys, func(t Ty) string { return t.toString(n) }), + Lib.ListMap(p.args, func(t Term) string { return t.toString(n) }), ) } -func (p Pred) Copy() Form { - np := MakePredSimple( - p.id, - p.GetTyArgs(), - p.GetArgs(), - p.metas.Raw().Copy(), - ) - - if !p.metas.NeedsUpd() { - np.metas.AvoidUpd() - } +func (p Pred) ToString() string { + return p.toString(0) +} - return p +func (p Pred) Copy() Form { + return MakePred(p.id, Lib.ListCpy(p.tys), Lib.ListCpy(p.args)) } func (p Pred) Equals(other any) bool { @@ -860,18 +592,8 @@ func (p Pred) Equals(other any) bool { return false } -func (p Pred) forceGetMetas() Lib.Set[Meta] { - res := Lib.EmptySet[Meta]() - - for _, m := range p.GetArgs().GetSlice() { - res = res.Union(m.GetMetas()) - } - - return res -} - func (p Pred) GetMetas() Lib.Set[Meta] { - return p.metas.Get(p) + return listUnion(p.args, Term.GetMetas) } func (p Pred) GetMetaList() Lib.List[Meta] { @@ -889,79 +611,42 @@ func (p Pred) GetMetaList() Lib.List[Meta] { return metas } -func (p Pred) ReplaceTermByTerm(old Term, new Term) (Form, bool) { - termList, res := replaceTermInTermList(p.GetArgs(), old, new) - - np := MakePredSimple( - p.GetID(), - p.GetTyArgs(), - termList, - p.metas.Raw(), - ) - - if !res && !p.metas.NeedsUpd() { - np.metas.AvoidUpd() - } - - return np, res +func (p Pred) applyOnTerms(f func(Term) Term) Pred { + return MakePred(p.id, p.tys, Lib.ListMap(p.args, f)) } -func (p Pred) SubstTy(old TyGenVar, new Ty) Form { - typed_args := Lib.ListMap( - p.tys, - func(t Ty) Ty { return t.SubstTy(old, new) }, - ) - args := Lib.ListMap( - p.args, - func(t Term) Term { return t.SubstTy(old, new) }, - ) - return MakePredSimple( - p.GetID(), - typed_args, - args, - p.metas.Raw(), - ) +func (p Pred) applyOnTys(f func(Ty) Ty) Pred { + return MakePred(p.id, Lib.ListMap(p.tys, f), p.args) } -func (p Pred) GetSubTerms() Lib.Set[Term] { - res := Lib.EmptySet[Term]() - - for _, t := range p.GetArgs().GetSlice() { - res = res.Add(t).Union(t.GetSubTerms()) - } - - return res +func (p Pred) Instantiate(x Var, t Term) Form { + return p.applyOnTerms(func(u Term) Term { return u.Instantiate(x, t) }) } -func (p Pred) GetSymbols() Lib.Set[Id] { - res := Lib.EmptySet[Id]() +func (p Pred) Subst(x Meta, t Term) Form { + return p.applyOnTerms(func(u Term) Term { return u.Subst(x, t) }) +} - for _, t := range p.GetArgs().GetSlice() { - res = res.Union(t.GetSymbols()) - } +func (p Pred) SubstTy(old TyMeta, new Ty) Form { + return p.applyOnTerms(func(t Term) Term { return t.SubstTy(old, new) }). + applyOnTys(func(t Ty) Ty { return t.SubstTy(old, new) }) +} - return res +func (p Pred) InstantiateTy(old TyBound, new Ty) Form { + return p.applyOnTerms(func(t Term) Term { return t.InstantiateTy(old, new) }). + applyOnTys(func(t Ty) Ty { return t.Instantiate(old, new) }) } -func (p Pred) SubstituteVarByMeta(old Var, new Meta) Form { - f, res := p.ReplaceTermByTerm(old, new) +func (p Pred) ReplaceTerm(t, u Term) Form { + return p.applyOnTerms(func(v Term) Term { return v.ReplaceTerm(t, u) }) +} - switch nf := f.(type) { - case Pred: - if res { - return MakePredSimple( - nf.id, - nf.tys, - nf.args, - nf.metas.Raw(), - ) - } - return nf - default: - Glob.Anomaly("Substitution", "should return a Pred") - } +func (p Pred) GetSubTerms() Lib.Set[Term] { + return listUnion(p.args, Term.GetSubTerms) +} - return f +func (p Pred) GetSymbols() Lib.Set[Id] { + return listUnion(p.args, Term.GetSymbols) } func (p Pred) GetSubFormulasRecur() Lib.List[Form] { @@ -972,14 +657,6 @@ func (p Pred) GetChildFormulas() Lib.List[Form] { return Lib.NewList[Form]() } -func (p Pred) ReplaceMetaByTerm(meta Meta, term Term) Form { - return MakePred( - p.id, - p.tys, - Lib.ListMap(p.args, func(t Term) Term { return t.ReplaceSubTermBy(meta, term) }), - ) -} - func (p Pred) Less(oth any) bool { if form, is_form := oth.(Form); is_form { switch f := form.(type) { @@ -1003,22 +680,22 @@ func (p Pred) Less(oth any) bool { // ----------------------------------------------------------------------------- // True and False -type Top struct { -} - -func (Top) ToString() string { return printer.StrConn(ConnTop) } -func (t Top) Copy() Form { return MakeTop() } -func (Top) Equals(f any) bool { _, isTop := f.(Top); return isTop } -func (Top) GetMetas() Lib.Set[Meta] { return Lib.EmptySet[Meta]() } -func (t Top) ReplaceTermByTerm(Term, Term) (Form, bool) { return MakeTop(), false } -func (t Top) SubstTy(TyGenVar, Ty) Form { return t } -func (t Top) GetSubTerms() Lib.Set[Term] { return Lib.EmptySet[Term]() } -func (t Top) GetSymbols() Lib.Set[Id] { return Lib.EmptySet[Id]() } -func (t Top) SubstituteVarByMeta(Var, Meta) Form { return t } -func (t Top) GetInternalMetas() Lib.Set[Meta] { return Lib.EmptySet[Meta]() } -func (t Top) GetSubFormulasRecur() Lib.List[Form] { return Lib.MkListV[Form](t) } -func (t Top) GetChildFormulas() Lib.List[Form] { return Lib.NewList[Form]() } -func (t Top) ReplaceMetaByTerm(meta Meta, term Term) Form { return t } +type Top struct{} + +func (Top) toString(int) string { return printer.StrConn(ConnTop) } +func (t Top) ToString() string { return t.toString(0) } +func (t Top) Copy() Form { return MakeTop() } +func (Top) Equals(f any) bool { _, isTop := f.(Top); return isTop } +func (Top) GetMetas() Lib.Set[Meta] { return Lib.EmptySet[Meta]() } +func (Top) Instantiate(Var, Term) Form { return MakeTop() } +func (Top) Subst(Meta, Term) Form { return MakeTop() } +func (Top) ReplaceTerm(Term, Term) Form { return MakeTop() } +func (t Top) SubstTy(TyMeta, Ty) Form { return t } +func (t Top) InstantiateTy(TyBound, Ty) Form { return t } +func (t Top) GetSubTerms() Lib.Set[Term] { return Lib.EmptySet[Term]() } +func (t Top) GetSymbols() Lib.Set[Id] { return Lib.EmptySet[Id]() } +func (t Top) GetSubFormulasRecur() Lib.List[Form] { return Lib.MkListV[Form](t) } +func (t Top) GetChildFormulas() Lib.List[Form] { return Lib.NewList[Form]() } func (t Top) Less(oth any) bool { if form, is_form := oth.(Form); is_form { switch form.(type) { @@ -1032,22 +709,22 @@ func (t Top) Less(oth any) bool { } /* Bot (always false) definition */ -type Bot struct { -} - -func (Bot) ToString() string { return printer.StrConn(ConnBot) } -func (b Bot) Copy() Form { return MakeBot() } -func (Bot) Equals(f any) bool { _, isBot := f.(Bot); return isBot } -func (Bot) GetMetas() Lib.Set[Meta] { return Lib.EmptySet[Meta]() } -func (b Bot) ReplaceTermByTerm(Term, Term) (Form, bool) { return MakeBot(), false } -func (b Bot) SubstTy(TyGenVar, Ty) Form { return b } -func (b Bot) GetSubTerms() Lib.Set[Term] { return Lib.EmptySet[Term]() } -func (b Bot) GetSymbols() Lib.Set[Id] { return Lib.EmptySet[Id]() } -func (b Bot) SubstituteVarByMeta(Var, Meta) Form { return b } -func (b Bot) GetInternalMetas() Lib.Set[Meta] { return Lib.EmptySet[Meta]() } -func (b Bot) GetSubFormulasRecur() Lib.List[Form] { return Lib.MkListV[Form](b) } -func (b Bot) GetChildFormulas() Lib.List[Form] { return Lib.NewList[Form]() } -func (b Bot) ReplaceMetaByTerm(meta Meta, term Term) Form { return b } +type Bot struct{} + +func (Bot) toString(int) string { return printer.StrConn(ConnBot) } +func (b Bot) ToString() string { return b.toString(0) } +func (b Bot) Copy() Form { return MakeBot() } +func (Bot) Equals(f any) bool { _, isBot := f.(Bot); return isBot } +func (Bot) GetMetas() Lib.Set[Meta] { return Lib.EmptySet[Meta]() } +func (Bot) Instantiate(Var, Term) Form { return MakeBot() } +func (Bot) Subst(Meta, Term) Form { return MakeBot() } +func (Bot) ReplaceTerm(Term, Term) Form { return MakeBot() } +func (b Bot) SubstTy(TyMeta, Ty) Form { return b } +func (b Bot) InstantiateTy(TyBound, Ty) Form { return b } +func (b Bot) GetSubTerms() Lib.Set[Term] { return Lib.EmptySet[Term]() } +func (b Bot) GetSymbols() Lib.Set[Id] { return Lib.EmptySet[Id]() } +func (b Bot) GetSubFormulasRecur() Lib.List[Form] { return Lib.MkListV[Form](b) } +func (b Bot) GetChildFormulas() Lib.List[Form] { return Lib.NewList[Form]() } func (b Bot) Less(oth any) bool { if form, is_form := oth.(Form); is_form { switch form.(type) { diff --git a/src/AST/formula.go b/src/AST/formula.go index 84ceaa0c..7e30b122 100644 --- a/src/AST/formula.go +++ b/src/AST/formula.go @@ -37,6 +37,8 @@ package AST import ( + "fmt" + "github.com/GoelandProver/Goeland/Glob" "github.com/GoelandProver/Goeland/Lib" ) @@ -55,93 +57,52 @@ type Form interface { Lib.Comparable Lib.Ordered - ReplaceTermByTerm(old Term, new Term) (Form, bool) - SubstTy(old TyGenVar, new Ty) Form - SubstituteVarByMeta(old Var, new Meta) Form - ReplaceMetaByTerm(meta Meta, term Term) Form + SubstTy(old TyMeta, new Ty) Form + InstantiateTy(old TyBound, new Ty) Form + Instantiate(x Var, t Term) Form + Subst(x Meta, t Term) Form + ReplaceTerm(Term, Term) Form + + toString(int) string } -/* Replace a term by a term inside a function. */ -func replaceTermInTermList( - terms Lib.List[Term], - oldTerm Term, - newTerm Term, -) (Lib.List[Term], bool) { - res := false - newTermList := Lib.MkList[Term](terms.Len()) - - for i, val := range terms.GetSlice() { - if oldTerm.Equals(val) { - newTermList.Upd(i, newTerm) - res = true - } else { - switch nf := val.(type) { - case Var, Meta: - newTermList.Upd(i, val) - case Fun: - termList, r := replaceTermInTermList( - nf.GetArgs(), - oldTerm, - newTerm, - ) - newTermList.Upd(i, MakeFun( - nf.GetID(), - nf.GetTyArgs(), - termList, - )) - res = res || r - default: - Glob.Anomaly("ReplaceTermInTermList", "Term is not a Var, a Fun, or a Meta") - } - } +// Instantiates the _quantified_ formula [f] with the given term. +// Throws an anomaly if [f] is _not_ quantified. +func Instantiate(f Form, t Term) Form { + switch f := f.(type) { + case All: + return f.subForm.Instantiate(0, t) + case Ex: + return f.subForm.Instantiate(0, t) } - return newTermList, res + Glob.Anomaly( + "formula.Instantiate", + fmt.Sprintf("Tried to instantiate the non-quantified formula %s", f.ToString()), + ) + return nil +} + +func FormToStringOffset(f Form) string { + return f.Instantiate(0, Meta{-1, 0, printer.StrBound(0), TIndividual()}).toString(1) } /* Utils */ -func metasUnion(forms Lib.List[Form]) Lib.Set[Meta] { - res := Lib.EmptySet[Meta]() +func listUnion[T any, U Lib.Ordered](ls Lib.List[T], f func(T) Lib.Set[U]) Lib.Set[U] { + res := Lib.EmptySet[U]() - for _, form := range forms.GetSlice() { - res = res.Union(form.GetMetas()) + for _, x := range ls.GetSlice() { + res = res.Union(f(x)) } return res } -// Returns whether the term has been replaced in a subformula or not -func replaceTermInFormList( - oldForms Lib.List[Form], - oldTerm Term, - newTerm Term, -) (Lib.List[Form], bool) { - newForms := Lib.MkList[Form](oldForms.Len()) - res := false - - for i, form := range oldForms.GetSlice() { - newForm, r := form.ReplaceTermByTerm(oldTerm, newTerm) - res = res || r - newForms.Upd(i, newForm) - } - - return newForms, res -} - -func replaceTyVarInFormList(oldForms Lib.List[Form], old TyGenVar, new Ty) Lib.List[Form] { - return Lib.ListMap( - oldForms, - func(f Form) Form { return f.SubstTy(old, new) }, - ) -} - // Comparisons -func qLess(vars1, vars2 Lib.List[TypedVar], f1, f2 Form) bool { - return vars1.Len() < vars2.Len() || - (vars1.Len() == vars2.Len() && - f1.Less(f2)) +func qLess(ty1, ty2 Ty, f1, f2 Form) bool { + return ty1.Less(ty2) || (ty1.Equals(ty2) && f1.Less(f2)) } func bLess(fs1, fs2 Lib.List[Form]) bool { diff --git a/src/AST/maker.go b/src/AST/maker.go index f8fcf0c0..25bb1dd5 100644 --- a/src/AST/maker.go +++ b/src/AST/maker.go @@ -45,7 +45,6 @@ import ( ) /* Datas */ -var occurenceMeta map[string]int = make(map[string]int) var lock_term sync.Mutex var meta_id int @@ -76,41 +75,51 @@ func Reset() { /* Reset the metavariable table (useful when the IDDFS stop and restart) */ func ResetMeta() { meta_id = 0 - occurenceMeta = map[string]int{} } // Formulas makers -func MakeAll(vars Lib.List[TypedVar], forms Form) All { - return MakeAllSimple(vars, forms, Lib.EmptySet[Meta]()) +func MakeAll(ty Ty, forms Form) All { + return All{makeQuantifier(ty, forms, ConnAll)} } -func MakeEx(vars Lib.List[TypedVar], forms Form) Ex { - return MakeExSimple(vars, forms, Lib.EmptySet[Meta]()) +func MakeEx(ty Ty, forms Form) Ex { + return Ex{makeQuantifier(ty, forms, ConnEx)} } func MakeOr(forms Lib.List[Form]) Or { - return MakeOrSimple(forms, Lib.EmptySet[Meta]()) + return Or{makeNAriForm(forms)} } func MakeAnd(forms Lib.List[Form], binary ...bool) And { if binary != nil { - return MakeAndSimpleBinary(forms, Lib.EmptySet[Meta]()) + return MakeBinaryAnd(forms, Lib.EmptySet[Meta]()) } else { - return MakeAndSimple(forms, Lib.EmptySet[Meta]()) + return And{makeNAriForm(forms)} + } +} + +func MakeBinaryAnd(forms Lib.List[Form], metas Lib.Set[Meta]) And { + switch forms.Len() { + case 0, 1, 2: + return MakeAnd(forms) + default: + return MakeAnd( + Lib.MkListV[Form](forms.At(0), MakeAnd(forms.Slice(1, forms.Len()), true)), + ) } } func MakeEqu(firstForm, secondForm Form) Equ { - return MakeEquSimple(firstForm, secondForm, Lib.EmptySet[Meta]()) + return Equ{makeBinForm(firstForm, secondForm)} } func MakeImp(firstForm, secondForm Form) Imp { - return MakeImpSimple(firstForm, secondForm, Lib.EmptySet[Meta]()) + return Imp{makeBinForm(firstForm, secondForm)} } func MakeNot(form Form) Not { - return MakeNotSimple(form, Lib.EmptySet[Meta]()) + return Not{form} } func MakePred( @@ -118,12 +127,11 @@ func MakePred( tys Lib.List[Ty], terms Lib.List[Term], ) Pred { - return MakePredSimple( + return Pred{ id, tys, terms, - Lib.EmptySet[Meta](), - ) + } } func MakeTop() Top { @@ -137,42 +145,27 @@ func MakeBot() Bot { // Terms makers func MakeId(s string) Id { - return Id{s} + return Id(s) } func MakeQuotedId(s string) Id { - return Id{"" + s + "'"} + return Id("'" + s + "'") } -func MakeVar(s string) Var { - return Var{s} +func MakeVar(i int) Var { + return Var(i) } -func MakeMeta(s string, f int, ty Ty) Meta { +func MakeMeta(formula int, ty Ty) Meta { lock_term.Lock() new_id := meta_id meta_id++ - i, ok := occurenceMeta[s] lock_term.Unlock() - if ok { - lock_term.Lock() - occurenceMeta[s] = i + 1 - lock_term.Unlock() - return Meta{new_id, i, fmt.Sprintf("%s%d", s, new_id), f, ty} - } else { - lock_term.Lock() - occurenceMeta[s] = 1 - lock_term.Unlock() - return Meta{new_id, 0, fmt.Sprintf("%s%d", s, new_id), f, ty} - } -} - -func MakeFunSimple(p Id, ty_args Lib.List[Ty], args Lib.List[Term], metas Lib.Set[Meta]) Fun { - return Fun{p, ty_args, args, Lib.MkCache(metas, Fun.forceGetMetas)} + return Meta{formula, new_id, fmt.Sprintf("M%d", new_id), ty} } func MakeFun(p Id, ty_args Lib.List[Ty], args Lib.List[Term]) Fun { - return MakeFunSimple(p, ty_args, args, Lib.EmptySet[Meta]()) + return Fun{p, ty_args, args} } /* Const maker (given a id, create a fun without args) */ diff --git a/src/AST/modular-printing.go b/src/AST/modular-printing.go index a4d90243..5e31efd4 100644 --- a/src/AST/modular-printing.go +++ b/src/AST/modular-printing.go @@ -66,10 +66,9 @@ var printer_debug Glob.Debugger type PrinterAction struct { genericAction func(string) string // Always executed actionOnId func(Id) string - actionOnBoundVar func(string) string actionOnMeta func(string, int) string actionOnType func(string) string - actionOnTypedVar func(Lib.Pair[string, Ty]) string + actionOnTypedVar func(Lib.Pair[string, string]) string actionOnFunctional func(id Id, tys Lib.List[string], args Lib.List[string]) string } @@ -77,16 +76,13 @@ func (p PrinterAction) Compose(oth PrinterAction) PrinterAction { return PrinterAction{ genericAction: func(s string) string { return oth.genericAction(p.genericAction(s)) }, actionOnId: func(i Id) string { return oth.actionOnId(MakeId(p.actionOnId(i))) }, - actionOnBoundVar: func(name string) string { - return oth.actionOnBoundVar(p.actionOnBoundVar(name)) - }, actionOnMeta: func(name string, index int) string { return oth.actionOnMeta(p.actionOnMeta(name, index), index) }, actionOnType: func(name string) string { return oth.actionOnType(p.actionOnType(name)) }, - actionOnTypedVar: func(pair Lib.Pair[string, Ty]) string { + actionOnTypedVar: func(pair Lib.Pair[string, string]) string { return oth.actionOnTypedVar(Lib.MkPair(p.actionOnTypedVar(pair), pair.Snd)) }, actionOnFunctional: func(id Id, tys Lib.List[string], args Lib.List[string]) string { @@ -103,8 +99,12 @@ func (p PrinterAction) StrId(i Id) string { return p.Str(p.actionOnId(i)) } -func (p PrinterAction) StrBound(name string) string { - return p.Str(p.actionOnBoundVar(name)) +func (p PrinterAction) StrBoundTy(index int) string { + return p.Str(fmt.Sprintf("T%d", index)) +} + +func (p PrinterAction) StrBound(index int) string { + return p.Str(fmt.Sprintf("X%d", index)) } func (p PrinterAction) StrMeta(name string, index int) string { @@ -115,7 +115,7 @@ func (p PrinterAction) StrTy(name string) string { return p.Str(p.actionOnType(name)) } -func (p PrinterAction) StrTyVar(pair Lib.Pair[string, Ty]) string { +func (p PrinterAction) StrTyVar(pair Lib.Pair[string, string]) string { return p.Str(p.actionOnTypedVar(pair)) } @@ -130,16 +130,14 @@ func PrinterIdentity2[T any](s string, _ T) string { return s } func MkPrinterAction( genericAction func(string) string, actionOnId func(Id) string, - actionOnBoundVar func(string) string, actionOnMeta func(string, int) string, actionOnType func(string) string, - actionOnTypedVar func(Lib.Pair[string, Ty]) string, + actionOnTypedVar func(Lib.Pair[string, string]) string, actionOnFunctional func(id Id, tys Lib.List[string], args Lib.List[string]) string, ) PrinterAction { return PrinterAction{ genericAction, actionOnId, - actionOnBoundVar, actionOnMeta, actionOnType, actionOnTypedVar, @@ -223,15 +221,10 @@ func (c PrinterConnective) DefaultOnFunctionalArgs( arguments := strings.Join(args.GetSlice(), c.StrConn(SepArgs)) if is_infix { - if args.Len() != 2 { - // Glob.Anomaly("Printer", fmt.Sprintf( - // "invalid number of infix arguments: expected 2, got %d (in <<%s>> for %s)", - // args.Len(), - // arguments, - // id.ToString(), - // )) + if args.Len() == 2 { + return fmt.Sprintf("%s %s %s", args.At(0), id.ToString(), args.At(1)) } - return fmt.Sprintf("%s %s %s", args.At(0), id.ToString(), args.At(1)) + return id.ToString() } else { if tys.Len() > 0 { arguments = types + c.StrConn(SepArgsTyArgs) + arguments @@ -323,6 +316,10 @@ var ( QuoteID PrinterAction ) +func bvPrinter(i int) string { + return fmt.Sprintf("X%d", i) +} + func initPrinters() { printer_debug = Glob.CreateDebugger("printer") @@ -356,16 +353,15 @@ func initPrinters() { QuoteID = PrinterAction{ genericAction: PrinterIdentity, actionOnId: func(i Id) string { - r, _ := utf8.DecodeRuneInString(i.name) + r, _ := utf8.DecodeRuneInString(i.GetName()) if unicode.IsUpper(r) { - return fmt.Sprintf("'%s'", i.name) + return fmt.Sprintf("'%s'", i.GetName()) } - return i.name + return i.GetName() }, - actionOnBoundVar: PrinterIdentity, actionOnMeta: PrinterIdentity2[int], actionOnType: PrinterIdentity, - actionOnTypedVar: PrinterIdentityPair[Ty], + actionOnTypedVar: func(p Lib.Pair[string, string]) string { return p.Fst }, } } diff --git a/src/AST/typed-vars.go b/src/AST/nari-forms.go similarity index 58% rename from src/AST/typed-vars.go rename to src/AST/nari-forms.go index cf0435c4..e02dd56d 100644 --- a/src/AST/typed-vars.go +++ b/src/AST/nari-forms.go @@ -31,60 +31,59 @@ **/ /** -* This file implements an interface for bound variables. -**/ + * This file implements n-ary formulas (or, and) + **/ package AST -import ( - "github.com/GoelandProver/Goeland/Lib" -) +import "github.com/GoelandProver/Goeland/Lib" -type TypedVar struct { - name string - ty Ty +type nari_form struct { + subforms Lib.List[Form] } -func (v TypedVar) Copy() TypedVar { - return TypedVar{v.name, v.ty.Copy()} +func makeNAriForm(subforms Lib.List[Form]) nari_form { + return nari_form{subforms} } -func (v TypedVar) Equals(oth any) bool { - if ov, ok := oth.(TypedVar); ok { - return v.name == ov.name && v.ty.Equals(ov.ty) - } - return false +func (f nari_form) GetMetas() Lib.Set[Meta] { + return listUnion(f.subforms, Form.GetMetas) } -func (v TypedVar) ToString() string { - return printer.StrTyVar(Lib.MkPair(v.name, v.ty)) +func (f nari_form) GetSubTerms() Lib.Set[Term] { + return listUnion(f.subforms, Form.GetSubTerms) + } -func (v TypedVar) GetName() string { - return v.name +func (f nari_form) GetSymbols() Lib.Set[Id] { + return listUnion(f.subforms, Form.GetSymbols) } -func (v TypedVar) GetTy() Ty { - return v.ty +func (f nari_form) equals(oth nari_form) bool { + return Lib.ListEquals(f.subforms, oth.subforms) } -func (v TypedVar) ToBoundVar() Var { - return MakeVar(v.name) +func (f nari_form) copy() nari_form { + return makeNAriForm(Lib.ListCpy(f.subforms)) } -func (v TypedVar) ToTyBoundVar() TyBound { - return MkTyBV(v.name).(TyBound) +func (f nari_form) toString(n int, conn Connective) string { + return f.subforms.ToString( + func(f Form) string { return printer.Str(printer.SurroundChild(f.toString(n))) }, + printer.StrConn(conn), "", + ) } -func (v TypedVar) SubstTy(old TyGenVar, new Ty) TypedVar { - return TypedVar{v.name, v.ty.SubstTy(old, new)} +func (f nari_form) applyOnArgs(g func(Form) Form) nari_form { + return makeNAriForm( + Lib.ListMap(f.subforms, g), + ) } -func MkTypedVar(name string, ty Ty) TypedVar { - return TypedVar{name, ty} +func (f nari_form) GetChildFormulas() Lib.List[Form] { + return f.subforms } -// Deprecated: use MkTypedVar instead -func MakerTypedVar(name string, ty Ty) TypedVar { - return MkTypedVar(name, ty) +func (f nari_form) less(g nari_form) bool { + return bLess(f.subforms, g.subforms) } diff --git a/src/AST/printers.go b/src/AST/printers.go index dbf22101..6bdca34e 100644 --- a/src/AST/printers.go +++ b/src/AST/printers.go @@ -73,11 +73,10 @@ func RemoveSuperfluousParenthesesAction(connectives PrinterConnective) PrinterAc return s }, - actionOnId: func(i Id) string { return i.name }, - actionOnBoundVar: func(s string) string { return s }, + actionOnId: func(i Id) string { return i.GetName() }, actionOnMeta: func(s string, index int) string { return s }, actionOnType: func(s string) string { return s }, - actionOnTypedVar: func(p Lib.Pair[string, Ty]) string { return p.Fst }, + actionOnTypedVar: func(p Lib.Pair[string, string]) string { return p.Fst }, actionOnFunctional: func(id Id, tys Lib.List[string], args Lib.List[string]) string { return connectives.DefaultOnFunctionalArgs(id, tys, args) }, @@ -92,11 +91,10 @@ func SanitizerAction(connectives PrinterConnective, forbidden_chars []string) Pr } return s }, - actionOnId: func(i Id) string { return i.name }, - actionOnBoundVar: func(s string) string { return s }, + actionOnId: func(i Id) string { return i.GetName() }, actionOnMeta: func(s string, index int) string { return s }, actionOnType: func(s string) string { return s }, - actionOnTypedVar: func(p Lib.Pair[string, Ty]) string { return p.Fst }, + actionOnTypedVar: func(p Lib.Pair[string, string]) string { return p.Fst }, actionOnFunctional: func(id Id, tys Lib.List[string], args Lib.List[string]) string { return connectives.DefaultOnFunctionalArgs(id, tys, args) }, diff --git a/src/AST/quantifiers.go b/src/AST/quantifiers.go index 1838d53d..7ea3874c 100644 --- a/src/AST/quantifiers.go +++ b/src/AST/quantifiers.go @@ -39,67 +39,97 @@ package AST import ( "fmt" + "github.com/GoelandProver/Goeland/Glob" "github.com/GoelandProver/Goeland/Lib" ) type quantifier struct { - metas Lib.Cache[Lib.Set[Meta], quantifier] - varList Lib.List[TypedVar] + ty Ty subForm Form symbol Connective } func makeQuantifier( - vars Lib.List[TypedVar], + ty Ty, subForm Form, - metas Lib.Set[Meta], symbol Connective, ) quantifier { return quantifier{ - Lib.MkCache(metas, quantifier.forceGetMetas), - vars, + ty, subForm, symbol, } } -func (q quantifier) GetVarList() Lib.List[TypedVar] { - return Lib.ListCpy(q.varList) -} - func (q quantifier) GetForm() Form { return q.subForm.Copy() } -func (q quantifier) forceGetMetas() Lib.Set[Meta] { +func (q quantifier) GetMetas() Lib.Set[Meta] { return q.subForm.GetMetas() } -func (q quantifier) GetMetas() Lib.Set[Meta] { - return q.metas.Get(q) +func (q quantifier) Ty() Ty { + return q.ty } -func (q quantifier) ToString() string { +func (q quantifier) toString(n int) string { + vars := Lib.NewList[Lib.Pair[int, string]]() + var test func(quantifier) bool + var next func(quantifier) quantifier + + switch q.symbol { + case ConnAll: + test = func(q quantifier) bool { return Glob.Is[All](q.subForm) } + next = func(q quantifier) quantifier { return q.subForm.(All).quantifier } + case ConnEx: + test = func(q quantifier) bool { return Glob.Is[Ex](q.subForm) } + next = func(q quantifier) quantifier { return q.subForm.(Ex).quantifier } + default: + Glob.Anomaly("formula", "Expected quantifier to be forall or exists") + } + + vars = vars.Push(Lib.MkPair(n, q.ty.toString(n))) + n += 1 + + for test(q) { + q = next(q) + vars = vars.Push(Lib.MkPair(n, q.ty.toString(n))) + n += 1 + } + return printer.Str(fmt.Sprintf( "%s %s%s%s", printer.StrConn(q.symbol), printer.SurroundQuantified( - Lib.ListMap(q.varList, func(t TypedVar) Lib.Pair[string, Ty] { - return Lib.MkPair(t.name, t.ty) - }).ToString(printer.StrTyVar, printer.StrConn(SepTyVars), ""), + vars.ToString( + func(p Lib.Pair[int, string]) string { + if p.Snd == tType.ToString() { + return printer.StrTyVar(Lib.MkPair(printer.StrBoundTy(p.Fst), p.Snd)) + } else { + return printer.StrTyVar(Lib.MkPair(printer.StrBound(p.Fst), p.Snd)) + } + }, + printer.StrConn(SepTyVars), + "", + ), ), printer.StrConn(SepVarsForm), - printer.Str(q.subForm.ToString()), + printer.Str(q.subForm.toString(n)), )) } +func (q quantifier) ToString() string { + return q.toString(0) +} + func (q quantifier) GetChildFormulas() Lib.List[Form] { return Lib.MkListV(q.GetForm()) } func (q quantifier) Equals(other any) bool { if typed, ok := other.(quantifier); ok { - return Lib.ListEquals(q.varList, typed.varList) && q.subForm.Equals(typed.subForm) + return q.ty.Equals(typed.ty) && q.subForm.Equals(typed.subForm) } return false @@ -115,62 +145,18 @@ func (q quantifier) GetSymbols() Lib.Set[Id] { func (q quantifier) copy() quantifier { nq := makeQuantifier( - Lib.ListCpy(q.varList), + q.ty.Copy(), q.GetForm(), - q.metas.Raw().Copy(), q.symbol, ) - if !q.metas.NeedsUpd() { - nq.metas.AvoidUpd() - } - return nq } -func (q quantifier) replaceTermByTerm(old Term, new Term) (quantifier, bool) { - f, res := q.GetForm().ReplaceTermByTerm(old, new) - return makeQuantifier( - q.GetVarList(), - f, - q.metas.Raw().Copy(), - q.symbol, - ), res -} - -func (q quantifier) replaceTyVar(old TyGenVar, new Ty) quantifier { - f := q.GetForm().SubstTy(old, new) - return makeQuantifier( - Lib.ListMap( - q.GetVarList(), - func(p TypedVar) TypedVar { return p.SubstTy(old, new) }, - ), - f, - q.metas.Raw().Copy(), - q.symbol, - ) +func (q quantifier) applyOnSubForm(f func(Form) Form) quantifier { + return makeQuantifier(q.ty, f(q.subForm), q.symbol) } -func (q quantifier) substituteVarByMeta(old Var, new Meta) quantifier { - if Lib.ListMem(old, Lib.ListMap(q.varList, func(x TypedVar) Var { return x.ToBoundVar() })) { - return q - } - - newForm := q.GetForm().SubstituteVarByMeta(old, new) - return makeQuantifier( - q.GetVarList(), - newForm, - newForm.GetMetas().Copy(), - q.symbol, - ) -} - -func (q quantifier) replaceMetaByTerm(meta Meta, term Term) quantifier { - newForm := q.GetForm().ReplaceMetaByTerm(meta, term) - return makeQuantifier( - q.GetVarList(), - newForm, - newForm.GetMetas().Copy(), - q.symbol, - ) +func (q quantifier) applyOnTy(f func(Ty) Ty) quantifier { + return makeQuantifier(f(q.ty), q.subForm, q.symbol) } diff --git a/src/AST/term-list.go b/src/AST/term-list.go index ab4d8823..9db8c84f 100644 --- a/src/AST/term-list.go +++ b/src/AST/term-list.go @@ -54,55 +54,6 @@ func GetMetasOfList(tl Lib.List[Term]) Lib.Set[Meta] { return res } -/* -Replace the first occurence of a term by another in the list -*/ -func replaceFirstOccurrenceTermList( - tl Lib.List[Term], - replaceThis, withThis Term, -) (Lib.List[Term], bool) { - res := Lib.MkList[Term](tl.Len()) - updated := false - - for i := range tl.GetSlice() { - candidate := tl.At(i) - - // FIXME: should [res.At(i)] be copied? I don't think so but we'll see. - modifiedTerm := candidate.ReplaceSubTermBy(replaceThis, withThis) - - if !tl.At(i).Equals(modifiedTerm) && !updated { - updated = true - candidate = modifiedTerm - } - - res.Upd(i, candidate) - } - - return res, updated -} - -/* -Replace all occurences of a term by another in the list -*/ -func ReplaceOccurrence( - tl Lib.List[Term], - replaceThis, withThis Term, -) (Lib.List[Term], bool) { - res := Lib.MkList[Term](tl.Len()) - hasUpdated := false - - for i := range tl.GetSlice() { - // FIXME: should [res.At(i)] be copied? I don't think so but we'll see. - trm := tl.At(i).ReplaceSubTermBy(replaceThis, withThis) - if !trm.Equals(tl.At(i)) { - hasUpdated = true - } - res.Upd(i, trm) - } - - return res, hasUpdated -} - func EqualsWithoutOrder(tl, other Lib.List[Term]) bool { if tl.Len() != other.Len() { return false diff --git a/src/AST/term.go b/src/AST/term.go index 80ff05b8..8636026b 100644 --- a/src/AST/term.go +++ b/src/AST/term.go @@ -44,19 +44,29 @@ import ( /* Term */ type Term interface { Lib.Comparable - Lib.Stringable + Less(any) bool + Lib.Copyable[Term] + + Lib.Stringable + toString(int) string + GetName() string IsMeta() bool IsFun() bool ToMeta() Meta + GetMetas() Lib.Set[Meta] GetMetaList() Lib.List[Meta] // Metas appearing in the term ORDERED GetSubTerms() Lib.Set[Term] GetSymbols() Lib.Set[Id] - ReplaceSubTermBy(original_term, new_term Term) Term - SubstTy(old TyGenVar, new Ty) Term - Less(any) bool + + Instantiate(x Var, t Term) Term + Subst(x Meta, t Term) Term + InstantiateTy(old TyBound, new Ty) Term + SubstTy(old TyMeta, new Ty) Term + + ReplaceTerm(Term, Term) Term } /*** Functions **/ diff --git a/src/AST/terms-def.go b/src/AST/terms-def.go index 4c36194a..fb03ef05 100644 --- a/src/AST/terms-def.go +++ b/src/AST/terms-def.go @@ -39,20 +39,20 @@ package AST import ( "strings" + "github.com/GoelandProver/Goeland/Glob" "github.com/GoelandProver/Goeland/Lib" ) // ----------------------------------------------------------------------------- // Predicates / functions symbols -type Id struct { - name string -} +type Id string -func (i Id) GetName() string { return i.name } +func (i Id) GetName() string { return string(i) } +func (i Id) toString(int) string { return i.GetName() } func (i Id) IsMeta() bool { return false } func (i Id) IsFun() bool { return false } -func (i Id) Copy() Term { return MakeId(i.GetName()) } +func (i Id) Copy() Term { return Id(strings.Clone(string(i))) } func (Id) ToMeta() Meta { return MakeEmptyMeta() } func (Id) GetMetas() Lib.Set[Meta] { return Lib.EmptySet[Meta]() } func (Id) GetMetaList() Lib.List[Meta] { return Lib.NewList[Meta]() } @@ -60,19 +60,16 @@ func (i Id) ToString() string { return printer.StrId(i) } func (i Id) Equals(t any) bool { if typed, ok := t.(Id); ok { - return typed.name == i.name + return typed == i } return false } -func (i Id) ReplaceSubTermBy(original_term, new_term Term) Term { - if i.Equals(original_term) { - return new_term.Copy() - } - return i -} +func (i Id) Instantiate(Var, Term) Term { return i } +func (i Id) Subst(Meta, Term) Term { return i } -func (i Id) SubstTy(TyGenVar, Ty) Term { return i } +func (i Id) InstantiateTy(TyBound, Ty) Term { return i } +func (i Id) SubstTy(TyMeta, Ty) Term { return i } func (i Id) GetSubTerms() Lib.Set[Term] { return Lib.Singleton[Term](i) @@ -82,15 +79,22 @@ func (i Id) GetSymbols() Lib.Set[Id] { return Lib.Singleton(i) } +func (i Id) ReplaceTerm(t, u Term) Term { + if i.Equals(t) { + return u + } + return i +} + func (i Id) CompareWith(other Id) int { - return strings.Compare(i.name, other.name) + return strings.Compare(string(i), string(other)) } func (i Id) Less(u any) bool { if t, is_term := u.(Term); is_term { switch trm := t.(type) { case Id: - return i.name < trm.name + return i < trm default: return false } @@ -102,20 +106,23 @@ func (i Id) Less(u any) bool { // n-ary functions type Fun struct { - p Id - tys Lib.List[Ty] - args Lib.List[Term] - metas Lib.Cache[Lib.Set[Meta], Fun] + p Id + tys Lib.List[Ty] + args Lib.List[Term] } -func (f Fun) ToString() string { +func (f Fun) toString(i int) string { return printer.StrFunctional( f.p, - Lib.ListMap(f.tys, Ty.ToString), - Lib.ListMap(f.args, Term.ToString), + Lib.ListMap(f.tys, func(t Ty) string { return t.toString(i) }), + Lib.ListMap(f.args, func(t Term) string { return t.toString(i) }), ) } +func (f Fun) ToString() string { + return f.toString(0) +} + func (f Fun) GetID() Id { return f.p.Copy().(Id) } func (f Fun) GetP() Id { return f.p.Copy().(Id) } func (f Fun) GetTyArgs() Lib.List[Ty] { return f.tys } @@ -144,26 +151,20 @@ func (f Fun) Equals(t any) bool { } func (f Fun) Copy() Term { - return MakeFunSimple(f.GetP(), Lib.ListCpy(f.GetTyArgs()), Lib.ListCpy(f.GetArgs()), f.metas.Raw()) + return MakeFun( + f.GetP(), + Lib.ListCpy(f.GetTyArgs()), + Lib.ListCpy(f.GetArgs()), + ) } func (f Fun) PointerCopy() *Fun { - nf := MakeFunSimple(f.GetP(), f.GetTyArgs(), f.GetArgs(), f.metas.Raw()) + nf := MakeFun(f.GetP(), f.GetTyArgs(), f.GetArgs()) return &nf } -func (f Fun) forceGetMetas() Lib.Set[Meta] { - metas := Lib.EmptySet[Meta]() - - for _, arg := range f.GetArgs().GetSlice() { - metas = metas.Union(arg.GetMetas()) - } - - return metas -} - func (f Fun) GetMetas() Lib.Set[Meta] { - return f.metas.Get(f) + return listUnion(f.args, Term.GetMetas) } func (f Fun) GetMetaList() Lib.List[Meta] { @@ -181,20 +182,36 @@ func (f Fun) GetMetaList() Lib.List[Meta] { return metas } -func (f Fun) ReplaceSubTermBy(oldTerm, newTerm Term) Term { - if f.Equals(oldTerm) { - return newTerm.Copy() - } else { - tl, res := replaceFirstOccurrenceTermList(f.GetArgs(), oldTerm, newTerm) - nf := MakeFunSimple(f.GetID(), f.GetTyArgs(), tl, f.metas.Raw()) - if !res && !f.metas.NeedsUpd() { - nf.metas.AvoidUpd() - } - return nf - } +func (f Fun) applyOnArgs(g func(Term) Term) Fun { + return MakeFun( + f.p, + f.tys, + Lib.ListMap(f.args, g), + ) +} + +func (f Fun) applyOnTyArgs(g func(Ty) Ty) Fun { + return MakeFun( + f.p, + Lib.ListMap(f.tys, g), + f.args, + ) +} + +func (f Fun) Subst(x Meta, t Term) Term { + return f.applyOnArgs(func(u Term) Term { return u.Subst(x, t) }) +} + +func (f Fun) Instantiate(x Var, t Term) Term { + return f.applyOnArgs(func(u Term) Term { return u.Instantiate(x, t) }) +} + +func (f Fun) InstantiateTy(old TyBound, new Ty) Term { + return f.applyOnArgs(func(u Term) Term { return u.InstantiateTy(old, new) }). + applyOnTyArgs(func(t Ty) Ty { return t.Instantiate(old, new) }) } -func (f Fun) SubstTy(old TyGenVar, new Ty) Term { +func (f Fun) SubstTy(old TyMeta, new Ty) Term { typed_args := Lib.ListMap( f.tys, func(t Ty) Ty { return t.SubstTy(old, new) }, @@ -203,45 +220,26 @@ func (f Fun) SubstTy(old TyGenVar, new Ty) Term { f.args, func(t Term) Term { return t.SubstTy(old, new) }, ) - return MakeFunSimple( + return MakeFun( f.GetID(), typed_args, args, - f.metas.Raw(), ) } -func (f Fun) ReplaceAllSubTerm(oldTerm, newTerm Term) Term { - if f.Equals(oldTerm) { - return newTerm.Copy() - } else { - tl, res := ReplaceOccurrence(f.GetArgs(), oldTerm, newTerm) - nf := MakeFunSimple(f.GetID(), f.GetTyArgs(), tl, f.metas.Raw()) - if !res && !f.metas.NeedsUpd() { - nf.metas.AvoidUpd() - } - return nf +func (f Fun) ReplaceTerm(t, u Term) Term { + if f.Equals(t) { + return u } + return f.applyOnArgs(func(v Term) Term { return v.ReplaceTerm(t, u) }) } func (f Fun) GetSubTerms() Lib.Set[Term] { - res := Lib.Singleton(Term(f)) - - for _, arg := range f.GetArgs().GetSlice() { - res = res.Union(arg.GetSubTerms()) - } - - return res + return listUnion(f.args, Term.GetSubTerms).Add(Term(f)) } func (f Fun) GetSymbols() Lib.Set[Id] { - res := Lib.Singleton(f.GetID()) - - for _, arg := range f.GetArgs().GetSlice() { - res = res.Union(arg.GetSymbols()) - } - - return res + return listUnion(f.args, Term.GetSymbols).Add(f.p) } func (f Fun) Less(u any) bool { @@ -262,22 +260,29 @@ func (f Fun) Less(u any) bool { // ----------------------------------------------------------------------------- // Bound variables -type Var struct { - name string +type Var int + +func (v Var) increase() Var { return Var(int(v) + 1) } +func (v Var) toString(n int) string { return printer.StrBound(n - int(v) - 1) } +func (v Var) ToString() string { return v.toString(0) } + +func (v Var) Index() int { return int(v) } + +func (v Var) GetName() string { + Glob.Anomaly("term.GetName()", "A bound variable is nameless") + return "" } -func (v Var) ToString() string { return printer.StrBound(v.name) } -func (v Var) GetName() string { return v.name } func (v Var) IsMeta() bool { return false } func (v Var) IsFun() bool { return false } -func (v Var) Copy() Term { return MakeVar(v.GetName()) } +func (v Var) Copy() Term { return v } func (Var) ToMeta() Meta { return MakeEmptyMeta() } func (Var) GetMetas() Lib.Set[Meta] { return Lib.EmptySet[Meta]() } func (Var) GetMetaList() Lib.List[Meta] { return Lib.NewList[Meta]() } func (v Var) Equals(t any) bool { if typed, ok := t.(Var); ok { - return v.name == typed.name + return v == typed } return false } @@ -290,14 +295,24 @@ func (v Var) GetSymbols() Lib.Set[Id] { return Lib.EmptySet[Id]() } -func (v Var) ReplaceSubTermBy(original_term, new_term Term) Term { - if v.Equals(original_term) { - return new_term.Copy() +func (v Var) Instantiate(x Var, t Term) Term { + if v.Equals(x) { + return t } return v } -func (v Var) SubstTy(TyGenVar, Ty) Term { return v } +func (v Var) Subst(Meta, Term) Term { return v } + +func (v Var) InstantiateTy(TyBound, Ty) Term { return v } +func (v Var) SubstTy(TyMeta, Ty) Term { return v } + +func (v Var) ReplaceTerm(t, u Term) Term { + if v.Equals(t) { + return u + } + return v +} func (v Var) Less(u any) bool { if t, is_term := u.(Term); is_term { @@ -305,7 +320,7 @@ func (v Var) Less(u any) bool { case Id, Fun: return true case Var: - return v.name < trm.name + return v < trm default: return false } @@ -317,18 +332,17 @@ func (v Var) Less(u any) bool { // Meta/Free variables type Meta struct { - index int - occurence int - name string - formula int - ty Ty + formula int + index int + name string + ty Ty } -func (m Meta) ToString() string { return printer.StrMeta(m.name, m.index) } -func (m Meta) GetFormula() int { return m.formula } +func (m Meta) GetFormula() int { return m.formula } +func (m Meta) toString(int) string { return printer.StrMeta(m.name, m.index) } +func (m Meta) ToString() string { return m.toString(0) } func (m Meta) GetName() string { return m.name } -func (m Meta) GetOccurence() int { return m.occurence } func (m Meta) GetIndex() int { return m.index } func (m Meta) IsMeta() bool { return true } func (m Meta) IsFun() bool { return false } @@ -340,7 +354,6 @@ func (m Meta) GetTy() Ty { return m.ty } func (m Meta) Equals(t any) bool { if typed, ok := t.(Meta); ok { return m.index == typed.index && - m.occurence == typed.occurence && m.name == typed.name && m.formula == typed.formula } @@ -348,17 +361,20 @@ func (m Meta) Equals(t any) bool { } func (m Meta) Copy() Term { - return Meta{m.index, m.GetOccurence(), m.GetName(), m.GetFormula(), m.GetTy()} + return Meta{m.formula, m.index, m.GetName(), m.GetTy()} } -func (m Meta) ReplaceSubTermBy(original_term, new_term Term) Term { - if m.Equals(original_term) { - return new_term.Copy() +func (m Meta) Subst(x Meta, t Term) Term { + if m.Equals(x) { + return t } return m } -func (m Meta) SubstTy(TyGenVar, Ty) Term { return m } +func (m Meta) Instantiate(Var, Term) Term { return m } + +func (m Meta) InstantiateTy(TyBound, Ty) Term { return m } +func (m Meta) SubstTy(TyMeta, Ty) Term { return m } func (m Meta) GetSubTerms() Lib.Set[Term] { return Lib.Singleton[Term](m) @@ -368,15 +384,22 @@ func (m Meta) GetSymbols() Lib.Set[Id] { return Lib.EmptySet[Id]() } +func (m Meta) ReplaceTerm(t, u Term) Term { + if m.Equals(t) { + return u + } + return m +} + func (m Meta) Less(u any) bool { if t, is_term := u.(Term); is_term { switch trm := t.(type) { case Id, Fun, Var: return true case Meta: - return m.occurence < trm.occurence || - (m.occurence == trm.occurence && m.name < trm.name) || - (m.occurence == trm.occurence && m.name == trm.name && m.formula < trm.formula) + return m.name < trm.name || + (m.name == trm.name && m.index < trm.index) || + (m.name == trm.name && m.index == trm.index && m.formula < trm.formula) default: return false } @@ -385,7 +408,7 @@ func (m Meta) Less(u any) bool { } func MakeEmptyMeta() Meta { - return Meta{-1, -1, "-1", -1, TIndividual()} + return Meta{-1, -1, "M-1", TIndividual()} } func MetaEquals(x, y Meta) bool { diff --git a/src/AST/ty-syntax.go b/src/AST/ty-syntax.go index 213a6128..7e10fa59 100644 --- a/src/AST/ty-syntax.go +++ b/src/AST/ty-syntax.go @@ -44,98 +44,119 @@ import ( "github.com/GoelandProver/Goeland/Lib" ) -type TyGenVar interface { - isGenVar() -} - type Ty interface { Lib.Stringable - Lib.Comparable + Lib.Ordered Lib.Copyable[Ty] - isTy() - SubstTy(TyGenVar, Ty) Ty -} -// Internal, shouldn't get out so no upper case -type tyVar struct { - repr string -} - -func (tyVar) isTy() {} -func (v tyVar) ToString() string { - return printer.StrBound(v.repr) -} -func (v tyVar) Equals(oth any) bool { - if ov, ok := oth.(tyVar); ok { - return v.repr == ov.repr - } - return false + isTy() + Instantiate(TyBound, Ty) Ty + SubstTy(TyMeta, Ty) Ty + toString(int) string } -func (v tyVar) Copy() Ty { return tyVar{v.repr} } -func (v tyVar) SubstTy(TyGenVar, Ty) Ty { return v } +type TyBound int -type TyBound struct { - name string +func (v TyBound) toString(i int) string { + return printer.StrBoundTy(i - int(v) - 1) } - func (TyBound) isTy() {} func (TyBound) isGenVar() {} -func (b TyBound) ToString() string { - return printer.StrBound(b.name) +func (v TyBound) ToString() string { + return v.toString(0) } func (b TyBound) Equals(oth any) bool { if bv, ok := oth.(TyBound); ok { - return b.name == bv.name + return b == bv } return false } -func (b TyBound) Copy() Ty { return TyBound{b.name} } -func (b TyBound) GetName() string { return b.name } +func (b TyBound) Copy() Ty { return b } +func (b TyBound) GetName() string { + Glob.Anomaly("term.GetName()", "A bound variable is nameless") + return "" +} -func (b TyBound) SubstTy(old TyGenVar, new Ty) Ty { - if b.Equals(old) { +func (v TyBound) Instantiate(old TyBound, new Ty) Ty { + if v.Equals(old) { return new } - return b + return v } +func (b TyBound) SubstTy(TyMeta, Ty) Ty { return b } + +func (v TyBound) Increase() TyBound { return TyBound(int(v) + 1) } + +func (v TyBound) Less(oth any) bool { + if ty, is_ty := oth.(Ty); is_ty { + switch t := ty.(type) { + case TyBound: + return v < t + default: + return true + } + } + return false +} + +func (v TyBound) Index() int { return int(v) } + type TyMeta struct { + formula int // for compatibility with term metas index int name string - formula int // for compatibility with term metas } -func (TyMeta) isTy() {} -func (TyMeta) isGenVar() {} -func (m TyMeta) ToString() string { +func (TyMeta) isTy() {} +func (m TyMeta) toString(int) string { return printer.StrMeta(m.name, m.index) } +func (m TyMeta) ToString() string { + return m.toString(0) +} func (m TyMeta) Equals(oth any) bool { if om, ok := oth.(TyMeta); ok { - return m.name == om.name && m.formula == om.formula + return m.name == om.name && m.index == om.index } return false } -func (m TyMeta) Copy() Ty { return TyMeta{m.index, m.name, m.formula} } +func (m TyMeta) Copy() Ty { return TyMeta{m.formula, m.index, m.name} } -func (m TyMeta) SubstTy(v TyGenVar, new Ty) Ty { +func (m TyMeta) Instantiate(TyBound, Ty) Ty { return m } +func (m TyMeta) SubstTy(v TyMeta, new Ty) Ty { if m.Equals(v) { return new } return m } -func (m TyMeta) ToTermMeta() Meta { return Meta{m.index, 0, m.name, m.formula, tType} } +func (m TyMeta) ToTermMeta() Meta { return Meta{m.formula, m.index, m.name, tType} } func TyMetaFromMeta(m Meta) TyMeta { return TyMeta{ + m.formula, m.index, m.name, - m.formula, } } +func (m TyMeta) Less(oth any) bool { + if ty, is_ty := oth.(Ty); is_ty { + switch t := ty.(type) { + case TyBound: + return false + case TyMeta: + return m.name < t.name || + (m.name == t.name && m.index < t.index) || + (m.name == t.name && m.index == t.index && m.formula < t.formula) + default: + return true + } + } + return false +} + // Type constructors, e.g., list, option, ... // Include constants, e.g., $i, $o, ... type TyConstr struct { @@ -145,16 +166,23 @@ type TyConstr struct { func (TyConstr) isTy() {} -func (c TyConstr) ToString() string { +func (c TyConstr) toString(n int) string { if c.args.Empty() { return printer.StrTy(c.symbol) } return fmt.Sprintf("%s%s", printer.StrTy(c.symbol), - printer.SurroundArgs(Lib.ListToString(c.args, printer.StrConn(SepArgs), "")), + printer.SurroundArgs( + c.args.ToString(func(t Ty) string { return t.toString(n) }, + printer.StrConn(SepArgs), ""), + ), ) } +func (c TyConstr) ToString() string { + return c.toString(0) +} + func (c TyConstr) Equals(oth any) bool { if oc, ok := oth.(TyConstr); ok { return c.symbol == oc.symbol && @@ -175,11 +203,31 @@ func (c TyConstr) Args() Lib.List[Ty] { return c.args } -func (c TyConstr) SubstTy(old TyGenVar, new Ty) Ty { - return TyConstr{ - c.symbol, - Lib.ListMap(c.args, func(t Ty) Ty { return t.SubstTy(old, new) }), +func (c TyConstr) applyOnArgs(f func(t Ty) Ty) TyConstr { + return TyConstr{c.symbol, Lib.ListMap(c.args, f)} +} + +func (c TyConstr) Instantiate(old TyBound, new Ty) Ty { + return c.applyOnArgs(func(t Ty) Ty { return t.Instantiate(old, new) }) +} + +func (c TyConstr) SubstTy(old TyMeta, new Ty) Ty { + return c.applyOnArgs(func(t Ty) Ty { return t.SubstTy(old, new) }) +} + +func (c TyConstr) Less(oth any) bool { + if ty, is_ty := oth.(Ty); is_ty { + switch t := ty.(type) { + case TyBound, TyMeta: + return false + case TyConstr: + return c.symbol < t.symbol || + (c.symbol == t.symbol && Lib.ListLess(c.args, t.args)) + default: + return true + } } + return false } type TyProd struct { @@ -188,13 +236,17 @@ type TyProd struct { func (TyProd) isTy() {} -func (p TyProd) ToString() string { +func (p TyProd) toString(n int) string { return p.args.ToString( - func(ty Ty) string { return printer.Str(printer.SurroundChild(ty.ToString())) }, + func(ty Ty) string { return printer.Str(printer.SurroundChild(ty.toString(n))) }, printer.StrConn(ConnProd), "", ) } +func (p TyProd) ToString() string { + return p.toString(0) +} + func (p TyProd) GetTys() Lib.List[Ty] { return p.args } @@ -210,10 +262,30 @@ func (p TyProd) Copy() Ty { return TyProd{Lib.ListCpy(p.args)} } -func (p TyProd) SubstTy(old TyGenVar, new Ty) Ty { - return TyProd{ - Lib.ListMap(p.args, func(t Ty) Ty { return t.SubstTy(old, new) }), +func (c TyProd) applyOnArgs(f func(t Ty) Ty) TyProd { + return TyProd{Lib.ListMap(c.args, f)} +} + +func (p TyProd) Instantiate(old TyBound, new Ty) Ty { + return p.applyOnArgs(func(t Ty) Ty { return t.Instantiate(old, new) }) +} + +func (p TyProd) SubstTy(old TyMeta, new Ty) Ty { + return p.applyOnArgs(func(t Ty) Ty { return t.SubstTy(old, new) }) +} + +func (p TyProd) Less(oth any) bool { + if ty, is_ty := oth.(Ty); is_ty { + switch t := ty.(type) { + case TyBound, TyMeta, TyConstr: + return false + case TyProd: + return Lib.ListLess(p.args, t.args) + default: + return true + } } + return false } type TyFunc struct { @@ -221,13 +293,19 @@ type TyFunc struct { } func (TyFunc) isTy() {} -func (f TyFunc) ToString() string { + +func (f TyFunc) toString(n int) string { return fmt.Sprintf("%s %s %s", - printer.Str(printer.SurroundChild(f.in.ToString())), + printer.Str(printer.SurroundChild(f.in.toString(n))), printer.StrConn(ConnMap), - printer.Str(printer.SurroundChild(f.out.ToString())), + printer.Str(printer.SurroundChild(f.out.toString(n))), ) } + +func (f TyFunc) ToString() string { + return f.toString(0) +} + func (f TyFunc) Equals(oth any) bool { if of, ok := oth.(TyFunc); ok { return f.in.Equals(of.in) && f.out.Equals(of.out) @@ -239,46 +317,94 @@ func (f TyFunc) Copy() Ty { return TyFunc{f.in.Copy(), f.out.Copy()} } -func (f TyFunc) SubstTy(old TyGenVar, new Ty) Ty { - return TyFunc{f.in.SubstTy(old, new), f.out.SubstTy(old, new)} +func (f TyFunc) applyOnArgs(g func(Ty) Ty) TyFunc { + return TyFunc{g(f.in), g(f.out)} +} + +func (f TyFunc) Instantiate(old TyBound, new Ty) Ty { + return f.applyOnArgs(func(t Ty) Ty { return t.Instantiate(old, new) }) +} + +func (f TyFunc) SubstTy(old TyMeta, new Ty) Ty { + return f.applyOnArgs(func(t Ty) Ty { return t.SubstTy(old, new) }) +} + +func (f TyFunc) Less(oth any) bool { + if ty, is_ty := oth.(Ty); is_ty { + switch t := ty.(type) { + case TyBound, TyMeta, TyConstr, TyProd: + return false + case TyFunc: + return f.in.Less(t.in) || + (f.in.Equals(t.in) && f.out.Less(t.out)) + default: + return true + } + } + return false } type TyPi struct { - vars Lib.List[string] - ty Ty + ty Ty } func (TyPi) isTy() {} -func (p TyPi) ToString() string { + +func (p TyPi) toString(n int) string { + vars := Lib.MkListV(n) + n += 1 + + for Glob.Is[TyPi](p.ty) { + p = Glob.To[TyPi](p.ty) + vars = vars.Push(n) + n += 1 + } + return fmt.Sprintf( "%s %s%s%s", printer.StrConn(ConnPi), printer.SurroundQuantified( - p.vars.ToString(PrinterIdentity, printer.StrConn(SepTyVars), ""), + vars.ToString(printer.StrBoundTy, printer.StrConn(SepTyVars), ""), ), printer.StrConn(SepVarsForm), - printer.Str(p.ty.ToString()), + printer.Str(p.ty.toString(n)), ) } + +func (p TyPi) ToString() string { + return p.toString(0) +} func (p TyPi) Equals(oth any) bool { if op, ok := oth.(TyPi); ok { - cmp := func(x, y string) bool { return x == y } - return p.vars.Equals(cmp, p.vars, op.vars) && - p.ty.Equals(op.ty) + return p.ty.Equals(op.ty) } return false } func (p TyPi) Copy() Ty { - return TyPi{p.vars.Copy(func(x string) string { return x }), p.ty.Copy()} + return TyPi{p.ty.Copy()} } -func (p TyPi) SubstTy(old TyGenVar, new Ty) Ty { - return TyPi{p.vars, p.ty.SubstTy(old, new)} +func (p TyPi) Instantiate(old TyBound, new Ty) Ty { + return TyPi{p.ty.Instantiate(old.Increase(), new)} } -func (p TyPi) VarsLen() int { - return p.vars.Len() +func (p TyPi) SubstTy(old TyMeta, new Ty) Ty { + return TyPi{p.ty.SubstTy(old, new)} +} + +func (p TyPi) Less(oth any) bool { + if ty, is_ty := oth.(Ty); is_ty { + switch t := ty.(type) { + case TyBound, TyMeta, TyConstr, TyProd, TyFunc: + return false + case TyPi: + return p.ty.Less(t.ty) + default: + return true + } + } + return false } func (p TyPi) Ty() Ty { @@ -287,20 +413,16 @@ func (p TyPi) Ty() Ty { // Makers -func MkTyVar(repr string) Ty { - return tyVar{repr} -} - -func MkTyBV(name string) Ty { - return TyBound{name} +func MkTyBV(id int) Ty { + return TyBound(id) } -func MkTyMeta(name string, formula int) Ty { +func MkTyMeta(formula int) Ty { lock_term.Lock() index := meta_id meta_id++ lock_term.Unlock() - meta := TyMeta{index, name, formula} + meta := TyMeta{formula, index, fmt.Sprintf("MT%d", index)} return meta } @@ -320,91 +442,8 @@ func MkTyFunc(in, out Ty) Ty { return TyFunc{in, out} } -func MkTyPi(vars Lib.List[string], ty Ty) Ty { - return TyPi{vars, ty} -} - -// Deprecated: use MkTyBV instead -func MakerTyBV(name string) Ty { - return MkTyBV(name) -} - -func InstantiateTy(ty Ty, instance Lib.List[Ty]) Ty { - fatal := func(expected int) { - Glob.Fatal( - "Ty.Instantiate", - fmt.Sprintf( - "On instantiation of %s: given instance %s does not have the right number of arguments (expected %d)", - ty.ToString(), - Lib.ListToString(instance, ", ", "(empty instance)"), - expected, - ), - ) - } - - switch rty := ty.(type) { - case TyConstr, TyFunc: - if !instance.Empty() { - fatal(0) - } - - return ty - case TyPi: - if instance.Len() != rty.vars.Len() { - fatal(rty.vars.Len()) - } - - instanceMap := make(map[string]Ty) - for i, ity := range instance.GetSlice() { - instanceMap[rty.vars.At(i)] = ity - } - return instantiateTyRec(rty.ty, ty, instanceMap) - } - Glob.Anomaly( - "Ty.Instantiate", - fmt.Sprintf("Tried to instantiate %s which is not a Pi-type", ty.ToString()), - ) - return nil -} - -// source type is here for logging -func instantiateTyRec(ty, source Ty, instance map[string]Ty) Ty { - aux := func(ty Ty) Ty { - return instantiateTyRec(ty, source, instance) - } - - switch rty := ty.(type) { - case tyVar: - if val, ok := instance[rty.repr]; ok { - return val - } - Glob.Anomaly( - "Ty.Instantiate", - fmt.Sprintf("Under type %s: type variable %s has no instance", source.ToString(), rty.repr), - ) - - case TyConstr: - return MkTyConstr( - rty.symbol, - Lib.ListMap(rty.args, aux), - ) - - case TyProd: - return MkTyProd(Lib.ListMap(rty.args, aux)) - - case TyFunc: - return MkTyFunc(aux(rty.in), aux(rty.out)) - } - - Glob.Anomaly( - "Ty.Instantiate", - fmt.Sprintf( - "In %s, trying to instantiate %s which is illegal", - source.ToString(), - ty.ToString(), - ), - ) - return nil +func MkTyPi(ty Ty) Ty { + return TyPi{ty} } func GetArgsTy(ty Ty) Lib.List[Ty] { @@ -419,6 +458,7 @@ func GetArgsTy(ty Ty) Lib.List[Ty] { return nty.args } } + Glob.Anomaly( "Ty.GetArgs", fmt.Sprintf( @@ -480,7 +520,7 @@ func TermToTy(trm Term) Ty { return TyMetaFromMeta(t) case Fun: return MkTyConstr( - t.GetID().name, + t.GetID().GetName(), Lib.ListMap(t.args, TermToTy), ) } @@ -513,3 +553,14 @@ func MkDefaultPredType(number_of_arguments int) Ty { func MkDefaultFunctionType(number_of_arguments int) Ty { return mkDefaultFunctionalType(number_of_arguments, TIndividual()) } + +func InstantiateTy(ty Ty, instance Lib.List[Ty]) Lib.Option[Ty] { + for _, t := range instance.GetSlice() { + if ty0, is_pi := ty.(TyPi); is_pi { + ty = ty0.ty.Instantiate(0, t) + } else { + return Lib.MkNone[Ty]() + } + } + return Lib.MkSome(ty) +} diff --git a/src/Core/FormListDS.go b/src/Core/FormListDS.go index d3dcb7ca..717e84f0 100644 --- a/src/Core/FormListDS.go +++ b/src/Core/FormListDS.go @@ -31,6 +31,10 @@ **/ package Core +// FIXME: what's the point of this file? It is misleading as it is simply a set and it +// checks the membership of a formula inside this set. +// This file implements the DataStructure interface for a list of formulas + import ( "github.com/GoelandProver/Goeland/AST" "github.com/GoelandProver/Goeland/Lib" @@ -45,8 +49,6 @@ func (f FormListDS) GetFL() Lib.List[AST.Form] { return Lib.ListCpy(f.fl) } -/* Data struct */ - /* Take a list of formula and return a FormList (Datastructure type) */ func (f FormListDS) MakeDataStruct(lf Lib.List[AST.Form], is_pos bool) Unif.DataStructure { return (new(FormListDS)).InsertFormulaListToDataStructure(lf) @@ -94,3 +96,7 @@ func (fl FormListDS) Unify(f AST.Form) (bool, []Unif.MixedSubstitutions) { } return false, []Unif.MixedSubstitutions{} } + +func (fl FormListDS) UnifyTerm(AST.Term) (bool, []Unif.MixedTermSubstitutions) { + return false, []Unif.MixedTermSubstitutions{} +} diff --git a/src/Core/Sko/inner-skolemization.go b/src/Core/Sko/inner-skolemization.go index b9794ac2..0b03131b 100644 --- a/src/Core/Sko/inner-skolemization.go +++ b/src/Core/Sko/inner-skolemization.go @@ -59,7 +59,6 @@ func MkInnerSkolemization() InnerSkolemization { func (sko InnerSkolemization) Skolemize( _, form AST.Form, - x AST.TypedVar, _ Lib.Set[AST.Meta], ) (Skolemization, AST.Form) { sko.mu.Lock() @@ -74,10 +73,7 @@ func (sko InnerSkolemization) Skolemize( Lib.ListMap(internalMetas, Glob.To[AST.Term]), ) - skolemizedForm, _ := form.ReplaceTermByTerm( - x.ToBoundVar(), - Glob.To[AST.Term](skolemFunc), - ) + skolemizedForm := form.Instantiate(0, skolemFunc) return sko, skolemizedForm } diff --git a/src/Core/Sko/interface.go b/src/Core/Sko/interface.go index a9b3ebfc..e3c26d21 100644 --- a/src/Core/Sko/interface.go +++ b/src/Core/Sko/interface.go @@ -52,7 +52,6 @@ type Skolemization interface { Skolemize( AST.Form, AST.Form, - AST.TypedVar, Lib.Set[AST.Meta], ) (Skolemization, AST.Form) } diff --git a/src/Core/Sko/outer-skolemization.go b/src/Core/Sko/outer-skolemization.go index 1d8a062a..95711301 100644 --- a/src/Core/Sko/outer-skolemization.go +++ b/src/Core/Sko/outer-skolemization.go @@ -59,7 +59,6 @@ func MkOuterSkolemization() OuterSkolemization { func (sko OuterSkolemization) Skolemize( _, form AST.Form, - x AST.TypedVar, fvs Lib.Set[AST.Meta], ) (Skolemization, AST.Form) { sko.mu.Lock() @@ -74,10 +73,7 @@ func (sko OuterSkolemization) Skolemize( Lib.ListMap(metas, Glob.To[AST.Term]), ) - skolemizedForm, _ := form.ReplaceTermByTerm( - x.ToBoundVar(), - Glob.To[AST.Term](skolemFunc), - ) + skolemizedForm := form.Instantiate(0, skolemFunc) return sko, skolemizedForm } diff --git a/src/Core/Sko/preinner-skolemization.go b/src/Core/Sko/preinner-skolemization.go index c343f711..6f524454 100644 --- a/src/Core/Sko/preinner-skolemization.go +++ b/src/Core/Sko/preinner-skolemization.go @@ -33,7 +33,6 @@ package Sko import ( - "fmt" "sync" "github.com/GoelandProver/Goeland/AST" @@ -48,7 +47,7 @@ import ( type PreInnerSkolemization struct { existingSymbols Lib.Set[AST.Id] - linkedSymbols Lib.List[Glob.Pair[AST.Form, AST.Id]] + linkedSymbols Lib.List[Glob.Pair[AST.Form, AST.Id]] // FIXME: use a map once a formula is hashable mu *sync.Mutex } @@ -62,21 +61,18 @@ func MkPreInnerSkolemization() PreInnerSkolemization { func (sko PreInnerSkolemization) Skolemize( delta, form AST.Form, - x AST.TypedVar, _ Lib.Set[AST.Meta], ) (Skolemization, AST.Form) { - realDelta := alphaConvert(delta, 0, make(map[string]AST.Var)) - var symbol AST.Id sko.mu.Lock() if val, ok := sko.linkedSymbols.Find( - func(p Glob.Pair[AST.Form, AST.Id]) bool { return p.Fst.Equals(realDelta) }, + func(p Glob.Pair[AST.Form, AST.Id]) bool { return p.Fst.Equals(delta) }, Glob.MakePair(Glob.To[AST.Form](AST.MakeBot()), AST.MakeId("")), ); ok { symbol = val.Snd } else { symbol = genFreshSymbol(&sko.existingSymbols) - sko.linkedSymbols.Append(Glob.MakePair(realDelta, symbol)) + sko.linkedSymbols.Append(Glob.MakePair(delta, symbol)) } sko.mu.Unlock() @@ -88,116 +84,7 @@ func (sko PreInnerSkolemization) Skolemize( Lib.ListMap(internalMetas, Glob.To[AST.Term]), ) - skolemizedForm, _ := form.ReplaceTermByTerm( - x.ToBoundVar(), - Glob.To[AST.Term](skolemFunc), - ) + skolemizedForm := form.Instantiate(0, skolemFunc) return sko, skolemizedForm } - -func fresh(k int) string { - return fmt.Sprintf("x@%d", k) -} - -func alphaConvert( - form AST.Form, - k int, - substitution map[string]AST.Var, -) AST.Form { - switch f := form.(type) { - case AST.Top, AST.Bot: - return form - case AST.Pred: - mappedTerms := Lib.ListMap(f.GetArgs(), - func(t AST.Term) AST.Term { - return alphaConvertTerm(t, substitution) - }) - return AST.MakePred( - f.GetID(), - f.GetTyArgs(), - mappedTerms, - ) - case AST.Not: - return AST.MakeNot( - alphaConvert(f.GetForm(), k, substitution), - ) - case AST.Imp: - return AST.MakeImp( - alphaConvert(f.GetF1(), k, substitution), - alphaConvert(f.GetF2(), k, substitution), - ) - case AST.Equ: - return AST.MakeEqu( - alphaConvert(f.GetF1(), k, substitution), - alphaConvert(f.GetF2(), k, substitution), - ) - case AST.And: - return AST.MakeAnd( - Lib.MkListV( - Glob.MapTo( - f.GetChildFormulas().GetSlice(), - func(_ int, f AST.Form) AST.Form { - return alphaConvert(f, k, substitution) - })...), - ) - case AST.Or: - return AST.MakeOr( - Lib.MkListV(Glob.MapTo( - f.GetChildFormulas().GetSlice(), - func(_ int, f AST.Form) AST.Form { - return alphaConvert(f, k, substitution) - })...), - ) - case AST.All: - k, substitution, vl := makeConvertedVarList(k, substitution, f.GetVarList()) - return AST.MakeAll(vl, alphaConvert(f.GetForm(), k, substitution)) - case AST.Ex: - k, substitution, vl := makeConvertedVarList(k, substitution, f.GetVarList()) - return AST.MakeEx(vl, alphaConvert(f.GetForm(), k, substitution)) - } - Glob.Anomaly( - "preinner", - fmt.Sprintf( - "On alpha-conversion of %s: form does not correspond to any known ones", - form.ToString(), - ), - ) - return form -} - -func makeConvertedVarList( - k int, - substitution map[string]AST.Var, - vl Lib.List[AST.TypedVar], -) (int, map[string]AST.Var, Lib.List[AST.TypedVar]) { - newVarList := Lib.MkList[AST.TypedVar](vl.Len()) - for i, v := range vl.GetSlice() { - nv := AST.MkTypedVar(fresh(k+i), v.GetTy()) - newVarList.Upd(i, nv) - substitution[v.GetName()] = nv.ToBoundVar() - } - return k + vl.Len(), substitution, newVarList -} - -func alphaConvertTerm(t AST.Term, substitution map[string]AST.Var) AST.Term { - switch nt := t.(type) { - case AST.Var: - if val, ok := substitution[nt.GetName()]; ok { - return val - } else { - return nt - } - case AST.Fun: - mappedTerms := Lib.ListMap(nt.GetArgs(), - func(trm AST.Term) AST.Term { - return alphaConvertTerm(trm, substitution) - }) - return AST.MakeFun( - nt.GetID(), - nt.GetTyArgs(), - mappedTerms, - ) - } - return t -} diff --git a/src/Core/form_and_terms.go b/src/Core/form_and_terms.go index 0a9e3234..371850ef 100644 --- a/src/Core/form_and_terms.go +++ b/src/Core/form_and_terms.go @@ -90,8 +90,13 @@ func (fat FormAndTerms) SubstituteBy( result := fat.Copy() for i := range metas.GetSlice() { - result.form = result.form.ReplaceMetaByTerm(metas.At(i), terms.At(i)) - result.Terms, _ = AST.ReplaceOccurrence(result.Terms, metas.At(i), terms.At(i)) + result.form = result.form.Subst(metas.At(i), terms.At(i)) + result.Terms = Lib.ListMap(result.Terms, func(t AST.Term) AST.Term { + if t.Equals(metas.At(i)) { + return terms.At(i) + } + return t + }) } return result diff --git a/src/Core/instanciation.go b/src/Core/instantiation.go similarity index 77% rename from src/Core/instanciation.go rename to src/Core/instantiation.go index 2ea05de8..47ee3614 100644 --- a/src/Core/instanciation.go +++ b/src/Core/instantiation.go @@ -32,8 +32,6 @@ package Core import ( - "strings" - "github.com/GoelandProver/Goeland/AST" "github.com/GoelandProver/Goeland/Glob" "github.com/GoelandProver/Goeland/Lib" @@ -55,10 +53,10 @@ func Instantiate(fnt FormAndTerms, index int) (FormAndTerms, Lib.Set[AST.Meta]) switch f := fnt.GetForm().(type) { case AST.Not: if ex, isEx := f.GetForm().(AST.Ex); isEx { - fnt, meta = RealInstantiate(ex.GetVarList(), index, is_exists, ex.GetForm(), terms) + fnt, meta = RealInstantiate(ex.Ty(), index, is_exists, ex.GetForm(), terms) } case AST.All: - fnt, meta = RealInstantiate(f.GetVarList(), index, is_all, f.GetForm(), terms) + fnt, meta = RealInstantiate(f.Ty(), index, is_all, f.GetForm(), terms) } switch m := meta.(type) { @@ -73,21 +71,20 @@ func Instantiate(fnt FormAndTerms, index int) (FormAndTerms, Lib.Set[AST.Meta]) } func RealInstantiate( - varList Lib.List[AST.TypedVar], + ty AST.Ty, index, status int, subForm AST.Form, terms Lib.List[AST.Term], ) (FormAndTerms, Lib.Option[AST.Meta]) { - v := varList.At(0) var m Lib.Option[AST.Meta] - if AST.IsTType(v.GetTy()) { - meta := AST.MkTyMeta(strings.ToUpper(v.GetName()), index) - subForm = subForm.SubstTy(v.ToTyBoundVar(), meta) + if AST.IsTType(ty) { + meta := AST.MkTyMeta(index) + subForm = subForm.InstantiateTy(0, meta) m = Lib.MkNone[AST.Meta]() } else { - meta := AST.MakeMeta(strings.ToUpper(v.GetName()), index, v.GetTy()) - subForm = subForm.SubstituteVarByMeta(v.ToBoundVar(), meta) + meta := AST.MakeMeta(index, ty) + subForm = subForm.Instantiate(0, meta) terms = terms.Copy(AST.Term.Copy) terms.Add( AST.TermEquals, @@ -96,17 +93,8 @@ func RealInstantiate( m = Lib.MkSome(meta) } - if varList.Len() > 1 { - if status == is_exists { - ex := AST.MakeEx(varList.Slice(1, varList.Len()), subForm) - subForm = AST.MakeNot(ex) - } else { - subForm = AST.MakeAll(varList.Slice(1, varList.Len()), subForm) - } - } else { - if status == is_exists { - subForm = AST.MakeNot(subForm) - } + if status == is_exists { + subForm = AST.MakeNot(subForm) } return MakeFormAndTerm(subForm, terms), m diff --git a/src/Core/skolemisation.go b/src/Core/skolemisation.go index 0949b8bc..2efa5630 100644 --- a/src/Core/skolemisation.go +++ b/src/Core/skolemisation.go @@ -98,8 +98,7 @@ func Skolemize(form AST.Form, branchMetas Lib.Set[AST.Meta]) AST.Form { return realSkolemize( form, f.GetForm(), - f.GetVarList().At(0), - f.GetVarList(), + f.Ty(), branchMetas, isNegAll, ) @@ -110,8 +109,7 @@ func Skolemize(form AST.Form, branchMetas Lib.Set[AST.Meta]) AST.Form { return realSkolemize( form, nf.GetForm(), - nf.GetVarList().At(0), - nf.GetVarList(), + nf.Ty(), branchMetas, isExists, ) @@ -124,40 +122,29 @@ func Skolemize(form AST.Form, branchMetas Lib.Set[AST.Meta]) AST.Form { func realSkolemize( initialForm, deltaForm AST.Form, - x AST.TypedVar, - allVars Lib.List[AST.TypedVar], + ty AST.Ty, metas Lib.Set[AST.Meta], typ int, ) AST.Form { var res AST.Form - if AST.IsTType(x.GetTy()) { + if AST.IsTType(ty) { ty_mutex.Lock() id := AST.MakeId(fmt.Sprintf("skoTy@%d", ty_index)) ty_index++ ty_mutex.Unlock() - res = deltaForm.SubstTy(x.ToTyBoundVar(), AST.MkTyConst(id.ToString())) + res = deltaForm.InstantiateTy(0, AST.MkTyConst(id.ToString())) } else { selectedSkolemization, res = selectedSkolemization.Skolemize( initialForm, deltaForm, - x, metas, ) } - switch typ { - case isNegAll: - if allVars.Len() > 1 { - res = AST.MakeAll(allVars.Slice(1, allVars.Len()), res) - } + if typ == isNegAll { res = AST.MakeNot(res) - case isExists: - if allVars.Len() > 1 { - res = AST.MakeEx(allVars.Slice(1, allVars.Len()), res) - } - default: - Glob.Anomaly("Skolemization", "impossible reconstruction case") } + return res } diff --git a/src/Core/substitutions_search.go b/src/Core/substitutions_search.go index 709ae16f..07b4d85d 100644 --- a/src/Core/substitutions_search.go +++ b/src/Core/substitutions_search.go @@ -276,7 +276,7 @@ func ApplySubstitutionsOnTerm(substs Lib.List[Unif.MixedSubstitution], t AST.Ter t = t.SubstTy(meta, ty) case Lib.Right[Unif.TySubstitution, Unif.Substitution]: meta, term := s.Val.Get() - t = t.ReplaceSubTermBy(meta, term) + t = t.Subst(meta, term) } } @@ -312,7 +312,7 @@ func ApplySubstitutionsOnFormula(s Lib.List[Unif.MixedSubstitution], f AST.Form) f = f.SubstTy(meta, ty) case Lib.Right[Unif.TySubstitution, Unif.Substitution]: meta, term := s.Val.Get() - f = f.ReplaceMetaByTerm(meta, term) + f = f.Subst(meta, term) } } @@ -320,7 +320,10 @@ func ApplySubstitutionsOnFormula(s Lib.List[Unif.MixedSubstitution], f AST.Form) } /* For each element of the substitution, apply it on the entire formula list */ -func ApplySubstitutionsOnFormulaList(s Lib.List[Unif.MixedSubstitution], lf Lib.List[AST.Form]) Lib.List[AST.Form] { +func ApplySubstitutionsOnFormulaList( + s Lib.List[Unif.MixedSubstitution], + lf Lib.List[AST.Form], +) Lib.List[AST.Form] { lf_res := Lib.NewList[AST.Form]() for _, f := range lf.GetSlice() { new_form := ApplySubstitutionsOnFormula(s, f) @@ -331,12 +334,18 @@ func ApplySubstitutionsOnFormulaList(s Lib.List[Unif.MixedSubstitution], lf Lib. } /* Apply substitutions on FormAndTerm */ -func ApplySubstitutionsOnFormAndTerms(s Lib.List[Unif.MixedSubstitution], fat FormAndTerms) FormAndTerms { +func ApplySubstitutionsOnFormAndTerms( + s Lib.List[Unif.MixedSubstitution], + fat FormAndTerms, +) FormAndTerms { return MakeFormAndTerm(ApplySubstitutionsOnFormula(s, fat.GetForm()), fat.GetTerms()) } /* For each element of the substitution, apply it on the entire formAndTerms list */ -func ApplySubstitutionsOnFormAndTermsList(s Lib.List[Unif.MixedSubstitution], lf FormAndTermsList) FormAndTermsList { +func ApplySubstitutionsOnFormAndTermsList( + s Lib.List[Unif.MixedSubstitution], + lf FormAndTermsList, +) FormAndTermsList { lf_res := MakeEmptyFormAndTermsList() for _, f := range lf { new_form := ApplySubstitutionsOnFormAndTerms(s, f) @@ -412,7 +421,8 @@ func AreEqualsModuloaLaphaConversion(s1, s2 Unif.Substitutions) bool { i := 0 for i < len(s1) && cpt == i { for _, s2_element := range s2 { - if (s1[i].Key().GetName() == s2_element.Key().GetName()) && (s1[i].Value().Equals(s2_element.Value())) { + if (s1[i].Key().GetName() == s2_element.Key().GetName()) && + (s1[i].Value().Equals(s2_element.Value())) { cpt++ } } diff --git a/src/Engine/pretyper.go b/src/Engine/pretyper.go index 16386a83..5fb043b4 100644 --- a/src/Engine/pretyper.go +++ b/src/Engine/pretyper.go @@ -88,7 +88,11 @@ func pretype(con Context, terms []Parser.PTerm) []Lib.Pair[Parser.PTerm, Parser. } if !typed { - debug_low_level(Lib.MkLazy(func() string { return "Term is not a defined term, assigning default type" })) + debug_low_level( + Lib.MkLazy( + func() string { return "Term is not a defined term, assigning default type" }, + ), + ) tys = append(tys, Lib.MkPair(term, defaultType)) } @@ -159,11 +163,23 @@ func parserTermToType(pterm Parser.PTerm) Parser.PType { return nil } -func pretypeVars(vars []Lib.Pair[string, Parser.PAtomicType]) Lib.List[AST.TypedVar] { - res := Lib.MkList[AST.TypedVar](len(vars)) +func pretypeVars(loc_ctx Context, vars []Lib.Pair[string, Parser.PAtomicType]) Lib.List[AST.Ty] { + res := Lib.MkList[AST.Ty](len(vars)) for i, v := range vars { - ty := elaborateType(v.Snd.(Parser.PType), v.Snd.(Parser.PType), false) - res.Upd(i, AST.MakerTypedVar(v.Fst, ty)) + vs := Lib.ListMap( + Lib.MkListV(vars[:i]...), + func(p Lib.Pair[string, Parser.PAtomicType]) Lib.Pair[string, Parser.PType] { + return Lib.MkPair(p.Fst, p.Snd.(Parser.PType)) + }, + ) + res.Upd( + i, + elaborateType( + append(loc_ctx, vs.GetSlice()...), + v.Snd.(Parser.PType), + v.Snd.(Parser.PType), + ), + ) } return res } diff --git a/src/Engine/syntax-translation.go b/src/Engine/syntax-translation.go index e1158d11..c2be13aa 100644 --- a/src/Engine/syntax-translation.go +++ b/src/Engine/syntax-translation.go @@ -58,7 +58,9 @@ func InitDebugger() { debug_low_level = Glob.CreateDebugger("elab-low") } -func ToInternalSyntax(parser_statements []Parser.PStatement) (statements []Core.Statement, is_typed bool) { +func ToInternalSyntax( + parser_statements []Parser.PStatement, +) (statements []Core.Statement, is_typed bool) { is_typed = false con := initialContext() for _, statement := range parser_statements { @@ -147,13 +149,13 @@ func elaborateRole(parsing_role Parser.PFormulaRole, stmt Parser.PStatement) Cor } func elaborateParsingForm(con Context, f Parser.PForm) (Context, AST.Form, bool) { - return elaborateForm(con, f, f) + return elaborateForm([]Lib.Pair[string, Parser.PType]{}, con, f, f) } // The [source_form] argument is here for error printing purposes. -func elaborateForm(con Context, f, source_form Parser.PForm) (Context, AST.Form, bool) { - aux := func(con Context, t Parser.PTerm) (Context, AST.Term, bool) { - return elaborateParsingTerm(con, t) +func elaborateForm(loc_ctx, con Context, f, source_form Parser.PForm) (Context, AST.Form, bool) { + aux := func(loc_ctx, con Context, t Parser.PTerm) (Context, AST.Term, bool) { + return elaborateParsingTerm(loc_ctx, con, t) } switch pform := f.(type) { @@ -173,7 +175,7 @@ func elaborateForm(con Context, f, source_form Parser.PForm) (Context, AST.Form, args := Lib.MkList[AST.Term](term_args.Len()) for i, trm := range term_args.GetSlice() { - new_con, arg, b := aux(con, trm) + new_con, arg, b := aux(loc_ctx, con, trm) con = new_con is_typed = is_typed || b args.Upd(i, arg) @@ -183,7 +185,7 @@ func elaborateForm(con Context, f, source_form Parser.PForm) (Context, AST.Form, if isDefined(pform.Symbol()) { tys := Lib.ListMap(Lib.MkListV(typed_arguments[typed_args.Len():]...), func(p Lib.Pair[Parser.PTerm, Parser.PType]) Parser.PType { return p.Snd }) - typed_args = elaborateDefinedFunctionals(con, pform.Symbol(), tys, args) + typed_args = elaborateDefinedFunctionals(loc_ctx, con, pform.Symbol(), tys, args) } else { is_typed = !typed_args.Empty() } @@ -193,7 +195,7 @@ func elaborateForm(con Context, f, source_form Parser.PForm) (Context, AST.Form, Lib.ListMap( typed_args, func(pty Parser.PType) AST.Ty { - return elaborateType(pty, pty, false) + return elaborateType(loc_ctx, pty, pty) }), args, ), is_typed @@ -201,28 +203,28 @@ func elaborateForm(con Context, f, source_form Parser.PForm) (Context, AST.Form, case Parser.PUnary: switch pform.PUnaryOp { case Parser.PUnaryNeg: - new_con, nf, b := elaborateForm(con, pform.PForm, source_form) + new_con, nf, b := elaborateForm(loc_ctx, con, pform.PForm, source_form) return new_con, AST.MakeNot(nf), b } case Parser.PBin: switch pform.Operator() { case Parser.PBinaryOr: - return maybeFlattenOr(con, pform, source_form) + return maybeFlattenOr(loc_ctx, con, pform, source_form) case Parser.PBinaryAnd: - return maybeFlattenAnd(con, pform, source_form) + return maybeFlattenAnd(loc_ctx, con, pform, source_form) case Parser.PBinaryImp: - con1, lft, b1 := elaborateForm(con, pform.Left(), source_form) - new_con, rgt, b2 := elaborateForm(con1, pform.Right(), source_form) + con1, lft, b1 := elaborateForm(loc_ctx, con, pform.Left(), source_form) + new_con, rgt, b2 := elaborateForm(loc_ctx, con1, pform.Right(), source_form) return new_con, AST.MakeImp(lft, rgt), b1 || b2 case Parser.PBinaryEqu: - con1, lft, b1 := elaborateForm(con, pform.Left(), source_form) - new_con, rgt, b2 := elaborateForm(con1, pform.Right(), source_form) + con1, lft, b1 := elaborateForm(loc_ctx, con, pform.Left(), source_form) + new_con, rgt, b2 := elaborateForm(loc_ctx, con1, pform.Right(), source_form) return new_con, AST.MakeEqu(lft, rgt), b1 || b2 } case Parser.PQuant: - vars := pretypeVars(pform.Vars()) + vars := pretypeVars(loc_ctx, pform.Vars()) switch pform.PQuantifier { case Parser.PQuantAll: actualVars := Lib.ListMap( @@ -231,14 +233,20 @@ func elaborateForm(con Context, f, source_form Parser.PForm) (Context, AST.Form, return Lib.MkPair(p.Fst, p.Snd.(Parser.PType)) }, ) - new_con, form, b := elaborateForm(append(con, actualVars.GetSlice()...), pform.PForm, source_form) + new_con, form, b := elaborateForm( + append(loc_ctx, actualVars.GetSlice()...), + append(con, actualVars.GetSlice()...), + pform.PForm, source_form, + ) if !vars.Empty() { - form = AST.MakeAll(vars, form) + for i := vars.Len() - 1; i >= 0; i-- { + form = AST.MakeAll(vars.At(i), form) + } } return new_con, form, b case Parser.PQuantEx: - if vars.Any(func(v AST.TypedVar) bool { return AST.IsTType(v.GetTy()) }) { + if vars.Any(func(v AST.Ty) bool { return AST.IsTType(v) }) { Glob.Anomaly( elab_label, "Found existentially quantified types when parsing "+source_form.ToString(), @@ -250,9 +258,12 @@ func elaborateForm(con Context, f, source_form Parser.PForm) (Context, AST.Form, return Lib.MkPair(p.Fst, p.Snd.(Parser.PType)) }, ) - new_con, form, b := elaborateForm(append(con, actualVars.GetSlice()...), pform.PForm, source_form) + new_con, form, b := elaborateForm(append(loc_ctx, actualVars.GetSlice()...), + append(con, actualVars.GetSlice()...), pform.PForm, source_form) if !vars.Empty() { - form = AST.MakeEx(vars, form) + for i := vars.Len() - 1; i >= 0; i-- { + form = AST.MakeEx(vars.At(i), form) + } } return new_con, form, b } @@ -264,32 +275,40 @@ func elaborateForm(con Context, f, source_form Parser.PForm) (Context, AST.Form, return con, nil, false } -func maybeFlattenOr(con Context, f Parser.PBin, source_form Parser.PForm) (Context, AST.Form, bool) { +func maybeFlattenOr( + loc_ctx, con Context, + f Parser.PBin, + source_form Parser.PForm, +) (Context, AST.Form, bool) { return maybeFlattenBin( - con, f, source_form, + loc_ctx, con, f, source_form, func(ls Lib.List[AST.Form]) AST.Form { return AST.MakeOr(ls) }, Parser.PBinaryOr, ) } -func maybeFlattenAnd(con Context, f Parser.PBin, source_form Parser.PForm) (Context, AST.Form, bool) { +func maybeFlattenAnd( + loc_ctx, con Context, + f Parser.PBin, + source_form Parser.PForm, +) (Context, AST.Form, bool) { return maybeFlattenBin( - con, f, source_form, + loc_ctx, con, f, source_form, func(ls Lib.List[AST.Form]) AST.Form { return AST.MakeAnd(ls) }, Parser.PBinaryAnd, ) } func maybeFlattenBin( - con Context, + loc_ctx, con Context, f Parser.PBin, source_form Parser.PForm, maker Lib.Func[Lib.List[AST.Form], AST.Form], op Parser.PBinOp, ) (Context, AST.Form, bool) { if !Glob.Flatten() { - con1, lft, b1 := elaborateForm(con, f.Left(), source_form) - new_con, rgt, b2 := elaborateForm(con1, f.Right(), source_form) + con1, lft, b1 := elaborateForm(loc_ctx, con, f.Left(), source_form) + new_con, rgt, b2 := elaborateForm(loc_ctx, con1, f.Right(), source_form) return new_con, maker(Lib.MkListV(lft, rgt)), b1 || b2 } @@ -297,7 +316,7 @@ func maybeFlattenBin( is_typed := false real_subforms := Lib.MkList[AST.Form](subforms.Len()) for i, subform := range subforms.GetSlice() { - new_con, real_subform, b := elaborateForm(con, subform, source_form) + new_con, real_subform, b := elaborateForm(loc_ctx, con, subform, source_form) con = new_con real_subforms.Upd(i, real_subform) is_typed = is_typed || b @@ -317,19 +336,37 @@ func flatten(f Parser.PForm, op Parser.PBinOp) Lib.List[Parser.PForm] { return Lib.MkListV(f) } -func elaborateParsingTerm(con Context, t Parser.PTerm) (Context, AST.Term, bool) { - return elaborateTerm(con, t, t) +func elaborateParsingTerm(loc_ctx, con Context, t Parser.PTerm) (Context, AST.Term, bool) { + return elaborateTerm(loc_ctx, con, t, t) +} + +func getFromLocalCtx(loc_ctx Context, name string) int { + i := -1 + for j, v := range loc_ctx { + if name == v.Fst { + i = j + } + } + + if i == -1 { + Glob.Fatal( + parsing_label, + fmt.Sprintf("Expected a closed formula but %s is a free variable", name), + ) + } + + return len(loc_ctx) - (i + 1) } // The argument [source_term] is here for error printing purposes. -func elaborateTerm(con Context, t, source_term Parser.PTerm) (Context, AST.Term, bool) { - aux := func(con Context, t Parser.PTerm) (Context, AST.Term, bool) { - return elaborateTerm(con, t, source_term) +func elaborateTerm(loc_ctx, con Context, t, source_term Parser.PTerm) (Context, AST.Term, bool) { + aux := func(loc_ctx, con Context, t Parser.PTerm) (Context, AST.Term, bool) { + return elaborateTerm(loc_ctx, con, t, source_term) } switch pterm := t.(type) { case Parser.PVar: - return con, AST.MakeVar(pterm.Name()), false + return con, AST.MakeVar(getFromLocalCtx(loc_ctx, pterm.Name())), false case Parser.PFun: typed_arguments := pretype(con, pterm.Args()) @@ -338,7 +375,7 @@ func elaborateTerm(con Context, t, source_term Parser.PTerm) (Context, AST.Term, args := Lib.MkList[AST.Term](term_args.Len()) for i, trm := range term_args.GetSlice() { - new_con, arg, b := aux(con, trm) + new_con, arg, b := aux(loc_ctx, con, trm) con = new_con is_typed = is_typed || b args.Upd(i, arg) @@ -348,7 +385,7 @@ func elaborateTerm(con Context, t, source_term Parser.PTerm) (Context, AST.Term, if isDefined(pterm.Symbol()) { tys := Lib.ListMap(Lib.MkListV(typed_arguments[typed_args.Len():]...), func(p Lib.Pair[Parser.PTerm, Parser.PType]) Parser.PType { return p.Snd }) - typed_args = elaborateDefinedFunctionals(con, pterm.Symbol(), tys, args) + typed_args = elaborateDefinedFunctionals(loc_ctx, con, pterm.Symbol(), tys, args) } else { is_typed = !typed_args.Empty() } @@ -358,7 +395,7 @@ func elaborateTerm(con Context, t, source_term Parser.PTerm) (Context, AST.Term, Lib.ListMap( typed_args, func(pty Parser.PType) AST.Ty { - return elaborateType(pty, pty, false) + return elaborateType(loc_ctx, pty, pty) }), args, ) @@ -369,7 +406,7 @@ func elaborateTerm(con Context, t, source_term Parser.PTerm) (Context, AST.Term, return fmt.Sprintf("%s has defined type %s", pterm.Symbol(), oty.Val.ToString()) })) con = append(con, Lib.MkPair(pterm.Symbol(), Parser.PType(oty.Val))) - ty := elaborateType(oty.Val, oty.Val, false) + ty := elaborateType(loc_ctx, oty.Val, oty.Val) Typing.AddToGlobalEnv(pterm.Symbol(), ty) } return con, fun, is_typed || !typed_args.Empty() @@ -385,22 +422,22 @@ func elaborateTerm(con Context, t, source_term Parser.PTerm) (Context, AST.Term, func elaborateParsingType(pty Lib.Pair[string, Parser.PType]) Core.TFFAtomTyping { return Core.TFFAtomTyping{ Literal: AST.MakeId(pty.Fst), - Ty: elaborateType(pty.Snd, pty.Snd, true), + Ty: elaborateType(Context{}, pty.Snd, pty.Snd), } } // The [source_type] argument is here for error printing. -func elaborateType(pty, source_type Parser.PType, from_top_level bool) AST.Ty { +func elaborateType(loc_ctx Context, pty, source_type Parser.PType) AST.Ty { + debug(Lib.MkLazy(func() string { + return fmt.Sprintf("Elaborating type: %s", pty.ToString()) + })) + aux := func(pty Parser.PType) AST.Ty { - return elaborateType(pty, source_type, from_top_level) + return elaborateType(loc_ctx, pty, source_type) } switch ty := pty.(type) { case Parser.PTypeVar: - if from_top_level { - return AST.MkTyVar(ty.Name()) - } else { - return AST.MakerTyBV(ty.Name()) - } + return AST.MkTyBV(getFromLocalCtx(loc_ctx, ty.Name())) case Parser.PTypeFun: args := Lib.MkListV(ty.Args()...) actualArgs := Lib.ListMap( @@ -436,8 +473,8 @@ func elaborateType(pty, source_type Parser.PType, from_top_level bool) AST.Ty { fail_if_forbidden(ty.Left()) fail_if_forbidden(ty.Right()) - new_left := elaborateType(ty.Left(), source_type, from_top_level) - new_right := elaborateType(ty.Right(), source_type, from_top_level) + new_left := elaborateType(loc_ctx, ty.Left(), source_type) + new_right := elaborateType(loc_ctx, ty.Right(), source_type) switch ty.Operator() { case Parser.PTypeProd: @@ -445,21 +482,17 @@ func elaborateType(pty, source_type Parser.PType, from_top_level bool) AST.Ty { right_list := flattenProd(new_right) return AST.MkTyProd(Lib.MkListV(append(left_list, right_list...)...)) case Parser.PTypeMap: - return AST.MkTyFunc( - elaborateType(ty.Left(), source_type, from_top_level), - elaborateType(ty.Right(), source_type, from_top_level), - ) + return AST.MkTyFunc(new_left, new_right) } case Parser.PTypeQuant: switch ty.Quant() { case Parser.PTypeAll: - var_names := Lib.MkList[string](len(ty.Vars())) - for i, v := range ty.Vars() { - var_names.Upd(i, v.Fst) + for _, v := range ty.Vars() { + loc_ctx = append(loc_ctx, Lib.MkPair[string, Parser.PType](v.Fst, Parser.MkTypeConst("$tType").(Parser.PType))) } - underlying_type := elaborateType(ty.Ty(), source_type, from_top_level) + underlying_type := elaborateType(loc_ctx, ty.Ty(), source_type) if Glob.Is[AST.TyPi](underlying_type) { Glob.Anomaly( @@ -468,7 +501,11 @@ func elaborateType(pty, source_type Parser.PType, from_top_level bool) AST.Ty { ) } - return AST.MkTyPi(var_names, underlying_type) + res := underlying_type + for i := 0; i < len(ty.Vars()); i += 1 { + res = AST.MkTyPi(res) + } + return res } } @@ -492,20 +529,29 @@ func flattenProd(ty AST.Ty) []AST.Ty { } func elaborateDefinedFunctionals( - con Context, + loc_ctx, con Context, name string, ty_arguments Lib.List[Parser.PType], arguments Lib.List[AST.Term], ) Lib.List[Parser.PType] { debug(Lib.MkLazy(func() string { - return fmt.Sprintf("Elaborating defined functional %s(%s)", name, Lib.ListToString(arguments, ", ", "")) + return fmt.Sprintf( + "Elaborating defined functional %s(%s)", + name, + Lib.ListToString(arguments, ", ", ""), + ) })) // Invariant: call from isDefined, defined_length should be defined as well if arguments.Len() != defined_length[name] { Glob.Fatal( elab_label, - fmt.Sprintf("%s expects %d arguments, got %d", name, defined_length[name], arguments.Len()), + fmt.Sprintf( + "%s expects %d arguments, got %d", + name, + defined_length[name], + arguments.Len(), + ), ) } @@ -514,28 +560,31 @@ func elaborateDefinedFunctionals( for i, arg := range arguments.GetSlice() { var ty Lib.Option[Parser.PType] ty_args := Lib.NewList[Parser.PTerm]() + name := "" switch term := arg.(type) { case AST.Fun: + name = term.GetName() ty = lookupInContext(con, term.GetName()) for _, ty := range term.GetTyArgs().GetSlice() { switch t := ty.(type) { case AST.TyConstr: ty_args.Append(Parser.MkFunConst(t.Symbol())) case AST.TyBound: - ty_args.Append(Parser.MkVar(t.GetName())) + ty_args.Append(Parser.MkVar(loc_ctx[len(loc_ctx)-(t.Index()+1)].Fst)) default: Glob.Anomaly(elab_label, "Found non-constant type parameter in defined type") } } case AST.Var: - ty = lookupInContext(con, term.GetName()) + name = loc_ctx[len(loc_ctx)-(term.Index()+1)].Fst + ty = Lib.MkSome(loc_ctx[len(loc_ctx)-(term.Index()+1)].Snd) default: Glob.Anomaly(elab_label, "Parsed argument is neither a function nor a variable") } switch rty := ty.(type) { case Lib.Some[Parser.PType]: - tys.Append(instantiateType(rty.Val, arg.GetName(), ty_args.GetSlice())) + tys.Append(instantiateType(rty.Val, name, ty_args.GetSlice())) case Lib.None[Parser.PType]: // This is not a defined, let's use the inferred type tys.Append(ty_arguments.At(i)) diff --git a/src/Engine/tptp-defined-types.go b/src/Engine/tptp-defined-types.go index 041f8c0d..0145cfb9 100644 --- a/src/Engine/tptp-defined-types.go +++ b/src/Engine/tptp-defined-types.go @@ -38,12 +38,20 @@ package Engine import ( "fmt" + "github.com/GoelandProver/Goeland/Lib" "github.com/GoelandProver/Goeland/Parser" ) type Context []Lib.Pair[string, Parser.PType] +func ctxToString(ctx Context) string { + out := Lib.MkListV(ctx...) + return out.ToString(func(p Lib.Pair[string, Parser.PType]) string { + return p.ToString(func(s string) string { return s }, Parser.PType.ToString, " , ") + }, " ; ", "") +} + var defined Lib.Set[Lib.String] var defined_length map[string]int var allowed_elab map[string]Lib.Option[Lib.List[Parser.PType]] // None: no restriction @@ -78,7 +86,9 @@ func initialContext() Context { tNumber := Parser.MkPTypeVar("number") binPoly := func(out Parser.PType) Parser.PType { return Parser.MkTypeAll( - []Lib.Pair[string, Parser.PAtomicType]{Lib.MkPair("number", tType.(Parser.PAtomicType))}, + []Lib.Pair[string, Parser.PAtomicType]{ + Lib.MkPair("number", tType.(Parser.PAtomicType)), + }, Parser.MkTypeMap( Parser.MkTypeProd(tNumber, tNumber), out, @@ -87,7 +97,9 @@ func initialContext() Context { } unPoly := func(out Parser.PType) Parser.PType { return Parser.MkTypeAll( - []Lib.Pair[string, Parser.PAtomicType]{Lib.MkPair("number", tType.(Parser.PAtomicType))}, + []Lib.Pair[string, Parser.PAtomicType]{ + Lib.MkPair("number", tType.(Parser.PAtomicType)), + }, Parser.MkTypeMap(tNumber, out), ) } diff --git a/src/Lib/list.go b/src/Lib/list.go index ec3f9076..1e178037 100644 --- a/src/Lib/list.go +++ b/src/Lib/list.go @@ -78,6 +78,11 @@ func (l List[T]) Push(values ...T) List[T] { return l } +func (l List[T]) Cons(x T) List[T] { + l.values = append([]T{x}, l.values...) + return l +} + func (l *List[T]) Upd(i int, v T) { l.values[i] = v } diff --git a/src/Lib/pair.go b/src/Lib/pair.go index 25f435d7..f7dac6e8 100644 --- a/src/Lib/pair.go +++ b/src/Lib/pair.go @@ -45,6 +45,10 @@ func (p Pair[T, U]) ToString(f Func[T, string], g Func[U, string], sep string) s return "(" + f(p.Fst) + sep + g(p.Snd) + ")" } +func PairToString[T, U Stringable](p Pair[T, U], sep string) string { + return p.ToString(T.ToString, U.ToString, sep) +} + // Managing lists of pairs func Pr1[T, U any](ls List[Pair[T, U]]) List[T] { return ListMap(ls, func(p Pair[T, U]) T { return p.Fst }) diff --git a/src/Mods/CertifUtils/epsilon-terms-management.go b/src/Mods/CertifUtils/epsilon-terms-management.go index 04f3ef3e..f600c4e5 100644 --- a/src/Mods/CertifUtils/epsilon-terms-management.go +++ b/src/Mods/CertifUtils/epsilon-terms-management.go @@ -181,9 +181,9 @@ func (e Epsilon) Substitute(dummy_tm AST.Term, form AST.Form) AST.Form { if !(e.ground.Contains(tm)) { switch repl := Lib.AssqOpt(tm, e.tms).(type) { case Lib.Some[AST.Term]: - form, _ = form.ReplaceTermByTerm(tm, repl.Val) + form = form.ReplaceTerm(tm, repl.Val) case Lib.None[AST.Term]: - form, _ = form.ReplaceTermByTerm(tm, dummy_tm) + form = form.ReplaceTerm(tm, dummy_tm) } } } diff --git a/src/Mods/dmt/rewritten.go b/src/Mods/dmt/rewritten.go index a68b16f3..8356e0e8 100644 --- a/src/Mods/dmt/rewritten.go +++ b/src/Mods/dmt/rewritten.go @@ -47,7 +47,7 @@ import ( func substitute(form AST.Form, subst Unif.Substitutions) AST.Form { for _, s := range subst { old_symbol, new_symbol := s.Get() - form = form.ReplaceMetaByTerm(old_symbol, new_symbol) + form = form.Subst(old_symbol, new_symbol) } return form } diff --git a/src/Mods/equality/bse/equality_problem.go b/src/Mods/equality/bse/equality_problem.go index e40d29da..5e8498fb 100644 --- a/src/Mods/equality/bse/equality_problem.go +++ b/src/Mods/equality/bse/equality_problem.go @@ -77,7 +77,14 @@ func (ep EqualityProblem) copy() EqualityProblem { return makeEqualityProblem(ep.GetE(), ep.GetS(), ep.GetT(), ep.getC()) } func (ep EqualityProblem) ToString() string { - return "<" + ep.GetE().ToString() + ", " + ep.GetS().ToString() + ", " + ep.GetT().ToString() + "> • " + ep.getC().toString() + return "<" + ep.GetE(). + ToString() + + ", " + ep.GetS(). + ToString() + + ", " + ep.GetT(). + ToString() + + "> • " + ep.getC(). + toString() } func (ep EqualityProblem) AxiomsToTPTPString() string { @@ -95,7 +102,10 @@ func (ep EqualityProblem) applySubstitution(s Unif.Substitutions) EqualityProble new_equalities := ep.GetE() if !ep.getC().isEmpty() { - Glob.PrintError("EQ-AS", fmt.Sprintf("Constraint not null in applySubstitution : %v", ep.getC().toString())) + Glob.PrintError( + "EQ-AS", + fmt.Sprintf("Constraint not null in applySubstitution : %v", ep.getC().toString()), + ) } for _, subst := range s { @@ -131,16 +141,23 @@ func makeEqualityProblemList(E Equalities, goal []eqStruct.TermPair) EqualityPro } func makeEqualityProblem(E Equalities, s AST.Term, t AST.Term, c ConstraintStruct) EqualityProblem { - return EqualityProblem{makeDataStructFromEqualities(E.copy()), makeEQMapFromEqualities(E.copy()), E.copy(), s.Copy(), t.Copy(), c.copy()} + return EqualityProblem{ + makeDataStructFromEqualities(E.copy()), + makeEQMapFromEqualities(E.copy()), + E.copy(), + s.Copy(), + t.Copy(), + c.copy(), + } } /* Take a list of equalities and build the corresponding code tree */ func makeDataStructFromEqualities(eq Equalities) Unif.DataStructure { - formList := Lib.NewList[AST.Form]() + unification_problem := Lib.NewList[AST.Term]() for _, e := range eq { - formList.Append(Unif.MakerTermForm(e.GetT1()), Unif.MakerTermForm(e.GetT2())) + unification_problem.Append(e.GetT1(), e.GetT2()) } - return Unif.NewNode().MakeDataStruct(Lib.ListCpy(formList), true) + return Unif.MakeTermUnifProblem(unification_problem) } /* Take a list of equalities and build the corresponding assocative map */ diff --git a/src/Mods/equality/bse/equality_problem_list.go b/src/Mods/equality/bse/equality_problem_list.go index 8bbe0787..69da99c2 100644 --- a/src/Mods/equality/bse/equality_problem_list.go +++ b/src/Mods/equality/bse/equality_problem_list.go @@ -116,7 +116,9 @@ func (epml EqualityProblemMultiList) ToTPTPString(isSat bool) string { problemName := os.Args[len(os.Args)-1] problemName = problemName[:len(problemName)-2] parts := strings.Split(problemName, "/") - problemName = strings.ToLower(strings.ReplaceAll(parts[len(parts)-1], "+", "plus") + "eq" + strconv.Itoa(eqCpt)) + problemName = strings.ToLower( + strings.ReplaceAll(parts[len(parts)-1], "+", "plus") + "eq" + strconv.Itoa(eqCpt), + ) if !isSat { problemName = problemName + "un" @@ -179,17 +181,29 @@ func makeEmptyEqualityProblemMultiList() EqualityProblemMultiList { /*** Functions ***/ /* Build an equalit problem multilist from a list of inequation */ -func buildEqualityProblemMultiListFromNEQ(neq Inequalities, eq Equalities) EqualityProblemMultiList { +func buildEqualityProblemMultiListFromNEQ( + neq Inequalities, + eq Equalities, +) EqualityProblemMultiList { res := makeEmptyEqualityProblemMultiList() for _, neq_pair := range neq { - x := makeEqualityProblem(eq.copy(), neq_pair.GetT1(), neq_pair.GetT2(), makeEmptyConstraintStruct()) + x := makeEqualityProblem( + eq.copy(), + neq_pair.GetT1(), + neq_pair.GetT2(), + makeEmptyConstraintStruct(), + ) res = append(res, append(makeEmptyEqualityProblemList(), x)) } return res } /* Build an equality problem list from a predicat and its negation */ -func buildEqualityProblemListFrom2Pred(p1 AST.Pred, p2 AST.Pred, eq Equalities) EqualityProblemList { +func buildEqualityProblemListFrom2Pred( + p1 AST.Pred, + p2 AST.Pred, + eq Equalities, +) EqualityProblemList { res := makeEmptyEqualityProblemList() for i := range p1.GetArgs().GetSlice() { res = append(res, makeEqualityProblem( @@ -203,7 +217,11 @@ func buildEqualityProblemListFrom2Pred(p1 AST.Pred, p2 AST.Pred, eq Equalities) } /* Build an equality problem multi list from a list of predicate. Take one predicate, search for its negation in the code tree, and if it found any, build the corresponding equality problem list */ -func buildEqualityProblemMultiListFromPredList(pred AST.Pred, tn Unif.DataStructure, equs Equalities) EqualityProblemMultiList { +func buildEqualityProblemMultiListFromPredList( + pred AST.Pred, + tn Unif.DataStructure, + equs Equalities, +) EqualityProblemMultiList { res := makeEmptyEqualityProblemMultiList() predId := pred.GetID() @@ -219,8 +237,8 @@ func buildEqualityProblemMultiListFromPredList(pred AST.Pred, tn Unif.DataStruct } } - for i, arg := range pred.GetArgs().GetSlice() { - metas = Lib.ListAdd(metas, AST.MakeMeta("METAEQ_"+arg.ToString(), -1, tys.At(i))) + for i, _ := range pred.GetArgs().GetSlice() { + metas = Lib.ListAdd(metas, AST.MakeMeta(-1, tys.At(i))) // fixme-now: !!! why tys.At(i) ???? } newTerm := AST.MakePred( @@ -232,7 +250,14 @@ func buildEqualityProblemMultiListFromPredList(pred AST.Pred, tn Unif.DataStruct if found { for _, s := range complementaryPredList { - res = append(res, buildEqualityProblemListFrom2Pred(pred.Copy().(AST.Pred), s.GetForm().(AST.Pred), equs.copy())) + res = append( + res, + buildEqualityProblemListFrom2Pred( + pred.Copy().(AST.Pred), + s.GetForm().(AST.Pred), + equs.copy(), + ), + ) } } @@ -240,7 +265,11 @@ func buildEqualityProblemMultiListFromPredList(pred AST.Pred, tn Unif.DataStruct } /* Take a list of form and build an equality problem list, corresponding to thoses related to a predicate and its negation */ -func buildEqualityProblemMultiListFromFormList(fl Lib.List[AST.Form], tn Unif.DataStructure, eq Equalities) EqualityProblemMultiList { +func buildEqualityProblemMultiListFromFormList( + fl Lib.List[AST.Form], + tn Unif.DataStructure, + eq Equalities, +) EqualityProblemMultiList { res := makeEmptyEqualityProblemMultiList() for _, p := range fl.GetSlice() { if pt, ok := p.(AST.Pred); ok { @@ -255,21 +284,30 @@ func buildEqualityProblemMultiListFromFormList(fl Lib.List[AST.Form], tn Unif.Da return res } -/** +/* +* * Take a form list * Retun a lis of independent problem list (from predicate and negation) + a boolean, true if there is equality in the formula list, false otherwise -**/ -func buildEqualityProblemMultiList(fl Lib.List[AST.Form], tp, tn Unif.DataStructure) (EqualityProblemMultiList, bool) { +* + */ +func buildEqualityProblemMultiList( + fl Lib.List[AST.Form], + tp, tn Unif.DataStructure, +) (EqualityProblemMultiList, bool) { res := makeEmptyEqualityProblemMultiList() eq := retrieveEqualities(tp.Copy()) if len(eq) == 0 { return res, false } - res = append(res, buildEqualityProblemMultiListFromNEQ(retrieveInequalities(tn.Copy()), eq.copy())...) + res = append( + res, + buildEqualityProblemMultiListFromNEQ(retrieveInequalities(tn.Copy()), eq.copy())...) debug( Lib.MkLazy(func() string { return fmt.Sprintf("Res after FromNEQ : %v", res.ToString()) }), ) - res = append(res, buildEqualityProblemMultiListFromFormList(Lib.ListCpy(fl), tn.Copy(), eq.copy())...) + res = append( + res, + buildEqualityProblemMultiListFromFormList(Lib.ListCpy(fl), tn.Copy(), eq.copy())...) debug( Lib.MkLazy(func() string { return fmt.Sprintf("Res after FromForm : %v", res.ToString()) }), ) diff --git a/src/Mods/equality/bse/equality_rules_apply.go b/src/Mods/equality/bse/equality_rules_apply.go index 40d6e8ae..4b17447a 100644 --- a/src/Mods/equality/bse/equality_rules_apply.go +++ b/src/Mods/equality/bse/equality_rules_apply.go @@ -48,7 +48,9 @@ import ( func applyRule(rs ruleStruct, ep EqualityProblem, parent chan answerEP, father_id uint64) { debug(Lib.MkLazy(func() string { return fmt.Sprintf("Child of %v", father_id) })) debug( - Lib.MkLazy(func() string { return fmt.Sprintf("EQ before applying rule %v", ep.ToString()) }), + Lib.MkLazy( + func() string { return fmt.Sprintf("EQ before applying rule %v", ep.ToString()) }, + ), ) debug( Lib.MkLazy(func() string { return fmt.Sprintf("Apply rule %v", rs.toString()) }), @@ -70,7 +72,14 @@ func applyLeftRule(rs ruleStruct, ep EqualityProblem, father_chan chan answerEP, debug( Lib.MkLazy(func() string { return "Apply left rule" }), ) - is_consistant_with_lpo, new_term, new_cl := applyEQRule(rs.getL(), rs.getR(), rs.getLPrime(), rs.getS(), rs.getT(), ep.getC()) + is_consistant_with_lpo, new_term, new_cl := applyEQRule( + rs.getL(), + rs.getR(), + rs.getLPrime(), + rs.getS(), + rs.getT(), + ep.getC(), + ) if is_consistant_with_lpo { debug( @@ -83,9 +92,17 @@ func applyLeftRule(rs ruleStruct, ep EqualityProblem, father_chan chan answerEP, new_eq_list[rs.getIndexEQList()] = eqStruct.MakeTermPair(rs.getS(), new_term.Copy()) } debug( - Lib.MkLazy(func() string { return fmt.Sprintf("New EQ list : %v", new_eq_list.ToString()) }), + Lib.MkLazy( + func() string { return fmt.Sprintf("New EQ list : %v", new_eq_list.ToString()) }, + ), + ) + tryEqualityReasoningProblem( + makeEqualityProblem(new_eq_list, ep.GetS(), ep.GetT(), new_cl), + father_chan, + rs.getIndexEQList(), + LEFT, + father_id, ) - tryEqualityReasoningProblem(makeEqualityProblem(new_eq_list, ep.GetS(), ep.GetT(), new_cl), father_chan, rs.getIndexEQList(), LEFT, father_id) } else { debug( Lib.MkLazy(func() string { return "Not consistant with LPO, send nil" }), @@ -96,19 +113,37 @@ func applyLeftRule(rs ruleStruct, ep EqualityProblem, father_chan chan answerEP, } /* Apply right rigid basic superposition rule */ -func applyRightRule(rs ruleStruct, ep EqualityProblem, father_chan chan answerEP, father_id uint64) { +func applyRightRule( + rs ruleStruct, + ep EqualityProblem, + father_chan chan answerEP, + father_id uint64, +) { debug( Lib.MkLazy(func() string { return "Apply right rule" }), ) - is_consistant_with_lpo, new_term, new_cl := applyEQRule(rs.getL(), rs.getR(), rs.getLPrime(), rs.getS(), rs.getT(), ep.getC()) + is_consistant_with_lpo, new_term, new_cl := applyEQRule( + rs.getL(), + rs.getR(), + rs.getLPrime(), + rs.getS(), + rs.getT(), + ep.getC(), + ) if is_consistant_with_lpo { debug( Lib.MkLazy(func() string { return fmt.Sprintf("New term : %v", new_term.ToString()) }), ) if rs.getIsSModified() { - tryEqualityReasoningProblem(makeEqualityProblem(ep.copy().GetE(), new_term.Copy(), rs.getT(), new_cl), father_chan, rs.getIndexEQList(), RIGHT, father_id) + tryEqualityReasoningProblem( + makeEqualityProblem(ep.copy().GetE(), new_term.Copy(), rs.getT(), new_cl), + father_chan, + rs.getIndexEQList(), + RIGHT, + father_id, + ) } else { tryEqualityReasoningProblem(makeEqualityProblem(ep.copy().GetE(), rs.getS(), new_term.Copy(), new_cl), father_chan, rs.getIndexEQList(), RIGHT, father_id) } @@ -128,7 +163,10 @@ func applyRightRule(rs ruleStruct, ep EqualityProblem, father_chan chan answerEP * s and t * sub_term_of s is a subterm of s unifible with l **/ -func applyEQRule(l, r, sub_term_of_s, s, t AST.Term, cs ConstraintStruct) (bool, AST.Term, ConstraintStruct) { +func applyEQRule( + l, r, sub_term_of_s, s, t AST.Term, + cs ConstraintStruct, +) (bool, AST.Term, ConstraintStruct) { debug( Lib.MkLazy(func() string { return "Apply eq rule" }), ) @@ -138,9 +176,11 @@ func applyEQRule(l, r, sub_term_of_s, s, t AST.Term, cs ConstraintStruct) (bool, "Replace %v by %v in %v", sub_term_of_s.ToString(), r.ToString(), s.ToString()) }), ) - new_s := s.Copy().ReplaceSubTermBy(sub_term_of_s, r) + new_s := s.ReplaceTerm(sub_term_of_s, r) debug( - Lib.MkLazy(func() string { return fmt.Sprintf("s = %v, new_s = %v", s.ToString(), new_s.ToString()) }), + Lib.MkLazy( + func() string { return fmt.Sprintf("s = %v, new_s = %v", s.ToString(), new_s.ToString()) }, + ), ) constraints_list := cs.copy() @@ -150,7 +190,9 @@ func applyEQRule(l, r, sub_term_of_s, s, t AST.Term, cs ConstraintStruct) (bool, if !constraints_list.appendIfConsistant(MakeConstraint(PREC, eqStruct.MakeTermPair(t, s))) { return false, nil, makeEmptyConstraintStruct() } - if !constraints_list.appendIfConsistant(MakeConstraint(EQ, eqStruct.MakeTermPair(l, sub_term_of_s))) { + if !constraints_list.appendIfConsistant( + MakeConstraint(EQ, eqStruct.MakeTermPair(l, sub_term_of_s)), + ) { return false, nil, makeEmptyConstraintStruct() } return true, new_s, constraints_list diff --git a/src/Mods/equality/bse/equality_rules_try_apply.go b/src/Mods/equality/bse/equality_rules_try_apply.go index 21fcd9c3..faa53892 100644 --- a/src/Mods/equality/bse/equality_rules_try_apply.go +++ b/src/Mods/equality/bse/equality_rules_try_apply.go @@ -255,7 +255,7 @@ func searchUnifBewteenListAndEq( /* Take a (sub)-term t, and retrieve all the term t' unifiable with t */ func checkUnifInTree(t AST.Term, tree Unif.DataStructure) (bool, Lib.List[AST.Term]) { result_list := Lib.NewList[AST.Term]() - res, ms := tree.Unify(Unif.MakerTermForm(t.Copy())) + res, ms := tree.UnifyTerm(t.Copy()) if !res { return false, result_list diff --git a/src/Mods/equality/bse/equality_types.go b/src/Mods/equality/bse/equality_types.go index 98e75a7a..a674803c 100644 --- a/src/Mods/equality/bse/equality_types.go +++ b/src/Mods/equality/bse/equality_types.go @@ -120,9 +120,9 @@ func (equs Equalities) removeHalf() Equalities { /* Retrieve equalities from a datastructure */ func retrieveEqualities(dt Unif.DataStructure) Equalities { res := Equalities{} - meta_ty := AST.MkTyMeta("META_TY_EQ", -1) - MetaEQ1 := AST.MakeMeta("METAEQ1", -1, meta_ty) - MetaEQ2 := AST.MakeMeta("METAEQ2", -1, meta_ty) + meta_ty := AST.MkTyMeta(-1) + MetaEQ1 := AST.MakeMeta(-1, meta_ty) + MetaEQ2 := AST.MakeMeta(-1, meta_ty) eq_pred := AST.MakePred(AST.Id_eq, Lib.NewList[AST.Ty](), Lib.NewList[AST.Term]()) eq_pred = AST.MakePred( @@ -150,9 +150,9 @@ func retrieveEqualities(dt Unif.DataStructure) Equalities { /* Retrieve inequalities from a datastructure */ func retrieveInequalities(dt Unif.DataStructure) Inequalities { res := Inequalities{} - meta_ty := AST.MkTyMeta("META_TY_NEQ", -1) - MetaNEQ1 := AST.MakeMeta("META_NEQ_1", -1, meta_ty) - MetaNEQ2 := AST.MakeMeta("META_NEQ_2", -1, meta_ty) + meta_ty := AST.MkTyMeta(-1) + MetaNEQ1 := AST.MakeMeta(-1, meta_ty) + MetaNEQ2 := AST.MakeMeta(-1, meta_ty) neq_pred := AST.MakePred(AST.Id_eq, Lib.NewList[AST.Ty](), Lib.NewList[AST.Term]()) neq_pred = AST.MakePred( diff --git a/src/Mods/lambdapi/output.go b/src/Mods/lambdapi/output.go index 5d2fbd20..4653a9ad 100644 --- a/src/Mods/lambdapi/output.go +++ b/src/Mods/lambdapi/output.go @@ -156,11 +156,10 @@ func LambdapiPrinterAction() AST.PrinterAction { return result_string }, func(i AST.Id) string { return i.GetName() }, - AST.PrinterIdentity, - func(metaName string, metaIndex int) string { return fmt.Sprintf("%s_%d", metaName, metaIndex) }, + func(metaName string, metaIndex int) string { return metaName }, sanitize_type, - func(typed_var Lib.Pair[string, AST.Ty]) string { - return fmt.Sprintf("(%s : %s)", typed_var.Fst, sanitize_type(typed_var.Snd.ToString())) + func(typed_var Lib.Pair[string, string]) string { + return fmt.Sprintf("(%s : %s)", typed_var.Fst, sanitize_type(typed_var.Snd)) }, func(id AST.Id, tys Lib.List[string], args Lib.List[string]) string { if strings.Contains(id.GetName(), "sko") { diff --git a/src/Mods/lambdapi/proof.go b/src/Mods/lambdapi/proof.go index 8cdbb936..3d741517 100644 --- a/src/Mods/lambdapi/proof.go +++ b/src/Mods/lambdapi/proof.go @@ -256,31 +256,18 @@ func getFormattedTerm(term AST.Term) string { } func getTypeOfFirstBoundVar(form AST.Form) AST.Ty { - getTySafe := func(var_list Lib.List[AST.TypedVar]) AST.Ty { - if var_list.Empty() { - debug(Lib.MkLazy(func() string { - return fmt.Sprintf( - "Formula %s has no bound variable, cannot get its type", - form.ToString(), - ) - })) - Glob.Anomaly("LambdaPi", "No bound variable.") - } - return var_list.At(0).GetTy() - } - switch f := form.(type) { case AST.Not: switch nf := f.GetForm().(type) { case AST.All: - return getTySafe(nf.GetVarList()) + return nf.Ty() case AST.Ex: - return getTySafe(nf.GetVarList()) + return nf.Ty() } case AST.All: - return getTySafe(f.GetVarList()) + return f.Ty() case AST.Ex: - return getTySafe(f.GetVarList()) + return f.Ty() } debug(Lib.MkLazy(func() string { @@ -295,13 +282,14 @@ func getTypeOfFirstBoundVar(form AST.Form) AST.Ty { // Gets the child formula as a λ (bound_var : ty), P func getFormattedChild(form AST.Form) string { - format := func(var_list Lib.List[AST.TypedVar], f AST.Form, maker func(Lib.List[AST.TypedVar], AST.Form) AST.Form) string { - f = maker(var_list.Slice(1, var_list.Len()), f) + format := func(ty AST.Ty, f AST.Form) string { return fmt.Sprintf( "λ (%s : %s), %s", - var_list.At(0).GetName(), - var_list.At(0).GetTy().ToString(), - f.ToString(), + AST.PrettyPrinter.StrBound( + 0, + ), // this function is the same for every printer. Maybe it shouldn't be bound to a specific printer. + ty.ToString(), + AST.FormToStringOffset(f), ) } @@ -309,34 +297,14 @@ func getFormattedChild(form AST.Form) string { case AST.Not: switch nf := f.GetForm().(type) { case AST.All: - return format(nf.GetVarList(), nf.GetForm(), func(vl Lib.List[AST.TypedVar], f AST.Form) AST.Form { - if !vl.Empty() { - f = AST.MakeAll(vl, f) - } - return f - }) + return format(nf.Ty(), nf.GetForm()) case AST.Ex: - return format(nf.GetVarList(), nf.GetForm(), func(vl Lib.List[AST.TypedVar], f AST.Form) AST.Form { - if !vl.Empty() { - f = AST.MakeEx(vl, f) - } - return f - }) + return format(nf.Ty(), nf.GetForm()) } case AST.All: - return format(f.GetVarList(), f.GetForm(), func(vl Lib.List[AST.TypedVar], f AST.Form) AST.Form { - if !vl.Empty() { - f = AST.MakeAll(vl, f) - } - return f - }) + return format(f.Ty(), f.GetForm()) case AST.Ex: - return format(f.GetVarList(), f.GetForm(), func(vl Lib.List[AST.TypedVar], f AST.Form) AST.Form { - if !vl.Empty() { - f = AST.MakeEx(vl, f) - } - return f - }) + return format(f.Ty(), f.GetForm()) } Glob.Anomaly("LambdaPi", "Not a quantifier formula") diff --git a/src/Mods/rocq/output.go b/src/Mods/rocq/output.go index bcb3aaff..a8f82440 100644 --- a/src/Mods/rocq/output.go +++ b/src/Mods/rocq/output.go @@ -121,11 +121,10 @@ func RocqPrinterAction() AST.PrinterAction { rocq_action := AST.MkPrinterAction( AST.PrinterIdentity, func(i AST.Id) string { return i.GetName() }, - AST.PrinterIdentity, - func(metaName string, metaIndex int) string { return fmt.Sprintf("%s_%d", metaName, metaIndex) }, + func(metaName string, metaIndex int) string { return metaName }, sanitize_type, - func(typed_var Lib.Pair[string, AST.Ty]) string { - return fmt.Sprintf("(%s : %s)", typed_var.Fst, sanitize_type(typed_var.Snd.ToString())) + func(typed_var Lib.Pair[string, string]) string { + return fmt.Sprintf("(%s : %s)", typed_var.Fst, sanitize_type(typed_var.Snd)) }, connectives.DefaultOnFunctionalArgs, ) diff --git a/src/Search/destructive.go b/src/Search/destructive.go index 963711aa..591a2d0f 100644 --- a/src/Search/destructive.go +++ b/src/Search/destructive.go @@ -62,7 +62,15 @@ type BasicSearchAlgorithm interface { ProofSearch(uint64, State, Communication, Core.SubstAndForm, int, int, []int, bool) DoEndManageBeta(uint64, State, Communication, []Communication, int, int, []int, []int) manageRewriteRules(uint64, State, Communication, Core.FormAndTermsList, int, int, []int) - ManageClosureRule(uint64, *State, Communication, Lib.List[Lib.List[Unif.MixedSubstitution]], Core.FormAndTerms, int, int) (bool, []Core.SubstAndForm) + ManageClosureRule( + uint64, + *State, + Communication, + Lib.List[Lib.List[Unif.MixedSubstitution]], + Core.FormAndTerms, + int, + int, + ) (bool, []Core.SubstAndForm) manageResult(c Communication) (Core.Unifier, []ProofStruct, bool) } @@ -76,7 +84,9 @@ func NewDestructiveSearch() BasicSearchAlgorithm { return ds } -func (ds *destructiveSearch) SetApplyRules(function func(uint64, State, Communication, Core.FormAndTermsList, int, int, []int)) { +func (ds *destructiveSearch) SetApplyRules( + function func(uint64, State, Communication, Core.FormAndTermsList, int, int, []int), +) { ds.doCorrectApplyRules = function } func (ds *destructiveSearch) Search(formula AST.Form, bound int) bool { @@ -119,20 +129,39 @@ func (ds *destructiveSearch) doOneStep(limit int, formula AST.Form) (bool, int) c := MakeCommunication(make(chan bool), make(chan Result)) if Glob.GetExchanges() { - WriteExchanges(Glob.GetGID(), state, []Core.SubstAndForm{}, Core.MakeEmptySubstAndForm(), "Search") + WriteExchanges( + Glob.GetGID(), + state, + []Core.SubstAndForm{}, + Core.MakeEmptySubstAndForm(), + "Search", + ) } nodeId := Glob.IncrCptNode() - go ds.ProofSearch(Glob.GetGID(), state, c, Core.MakeEmptySubstAndForm(), nodeId, nodeId, []int{}, false) + go ds.ProofSearch( + Glob.GetGID(), + state, + c, + Core.MakeEmptySubstAndForm(), + nodeId, + nodeId, + []int{}, + false, + ) Glob.IncrGoRoutine(1) debug(Lib.MkLazy(func() string { return "GO" })) debug( - Lib.MkLazy(func() string { return fmt.Sprintf("Nb of goroutines = %d", Glob.GetNbGoroutines()) }), + Lib.MkLazy( + func() string { return fmt.Sprintf("Nb of goroutines = %d", Glob.GetNbGoroutines()) }, + ), ) debug( - Lib.MkLazy(func() string { return fmt.Sprintf("%v goroutines still running", runtime.NumGoroutine()) }), + Lib.MkLazy( + func() string { return fmt.Sprintf("%v goroutines still running", runtime.NumGoroutine()) }, + ), ) unifier, finalProof, result := ds.manageResult(c) @@ -154,7 +183,11 @@ func (ds *destructiveSearch) doOneStep(limit int, formula AST.Form) (bool, int) } /* Choose a substitution (backtrack) */ -func (ds *destructiveSearch) tryBTSubstitution(spc *([]Core.SubstAndForm), mm Lib.Set[AST.Meta], children []Communication) Core.SubstAndForm { +func (ds *destructiveSearch) tryBTSubstitution( + spc *([]Core.SubstAndForm), + mm Lib.Set[AST.Meta], + children []Communication, +) Core.SubstAndForm { debug(Lib.MkLazy(func() string { return "Try another substitution." })) next_subst, new_spc := ds.chooseSubstitutionDestructive(Core.CopySubstAndFormList(*spc), mm) debug( @@ -170,7 +203,10 @@ func (ds *destructiveSearch) tryBTSubstitution(spc *([]Core.SubstAndForm), mm Li } /* Choose a substitution among all the subst send by children - takes thoses who contains no mm first */ -func (ds *destructiveSearch) chooseSubstitutionDestructive(subst_list []Core.SubstAndForm, mm Lib.Set[AST.Meta]) (Core.SubstAndForm, []Core.SubstAndForm) { +func (ds *destructiveSearch) chooseSubstitutionDestructive( + subst_list []Core.SubstAndForm, + mm Lib.Set[AST.Meta], +) (Core.SubstAndForm, []Core.SubstAndForm) { subst_found := subst_list[0] found := false i := 0 @@ -204,13 +240,21 @@ func (ds *destructiveSearch) chooseSubstitutionDestructive(subst_list []Core.Sub return subst_found, subst_list } -func (ds *destructiveSearch) searchContradictionAfterApplySusbt(father_id uint64, st State, cha Communication, node_id int, original_node_id int) bool { +func (ds *destructiveSearch) searchContradictionAfterApplySusbt( + father_id uint64, + st State, + cha Communication, + node_id int, + original_node_id int, +) bool { if Glob.GetAssisted() { return false } for _, f := range st.GetAtomic() { debug( - Lib.MkLazy(func() string { return fmt.Sprintf("##### Formula %v #####", f.ToString()) }), + Lib.MkLazy( + func() string { return fmt.Sprintf("##### Formula %v #####", f.ToString()) }, + ), ) // Check if exists a contradiction after applying the substitution if res, subst := ApplyClosureRules(f.GetForm(), &st); res { @@ -229,13 +273,22 @@ func (ds *destructiveSearch) searchContradictionAfterApplySusbt(father_id uint64 return false } -func (ds *destructiveSearch) searchContradiction(atomic AST.Form, father_id uint64, st State, cha Communication, node_id int, original_node_id int) bool { +func (ds *destructiveSearch) searchContradiction( + atomic AST.Form, + father_id uint64, + st State, + cha Communication, + node_id int, + original_node_id int, +) bool { // Search for a contradiction in LF if Glob.GetAssisted() { return false } debug( - Lib.MkLazy(func() string { return fmt.Sprintf("##### Formula %v #####", atomic.ToString()) }), + Lib.MkLazy( + func() string { return fmt.Sprintf("##### Formula %v #####", atomic.ToString()) }, + ), ) clos_res, subst := ApplyClosureRules(atomic, &st) fAt := Core.MakeFormAndTerm(atomic, Lib.MkList[AST.Term](0)) @@ -261,7 +314,16 @@ func (ds *destructiveSearch) searchContradiction(atomic AST.Form, father_id uint * s : substitution to apply to the current State * subst_found : Unif.Substitutions found by this process **/ -func (ds *destructiveSearch) ProofSearch(father_id uint64, st State, cha Communication, s Core.SubstAndForm, node_id int, original_node_id int, meta_to_reintroduce []int, post_dmt_step bool) { +func (ds *destructiveSearch) ProofSearch( + father_id uint64, + st State, + cha Communication, + s Core.SubstAndForm, + node_id int, + original_node_id int, + meta_to_reintroduce []int, + post_dmt_step bool, +) { debug( Lib.MkLazy(func() string { return "---------- New search step ----------" }), ) @@ -289,18 +351,37 @@ func (ds *destructiveSearch) ProofSearch(father_id uint64, st State, cha Communi // Select to check kill order select { case quit := <-cha.quit: - ds.manageQuitOrder(quit, cha, father_id, st, nil, st.GetSubstsFound(), node_id, original_node_id, nil, meta_to_reintroduce) + ds.manageQuitOrder( + quit, + cha, + father_id, + st, + nil, + st.GetSubstsFound(), + node_id, + original_node_id, + nil, + meta_to_reintroduce, + ) default: // Apply subst if needed if !s.IsEmpty() { debug( - Lib.MkLazy(func() string { return fmt.Sprintf("Apply Substitution : %v", s.ToString()) }), + Lib.MkLazy( + func() string { return fmt.Sprintf("Apply Substitution : %v", s.ToString()) }, + ), ) ApplySubstitution(&st, s) debug( Lib.MkLazy(func() string { return "Searching contradiction with new atomics" }), ) - if ds.searchContradictionAfterApplySusbt(father_id, st, cha, node_id, original_node_id) { + if ds.searchContradictionAfterApplySusbt( + father_id, + st, + cha, + node_id, + original_node_id, + ) { return } } @@ -312,13 +393,17 @@ func (ds *destructiveSearch) ProofSearch(father_id uint64, st State, cha Communi Lib.MkLazy(func() string { return fmt.Sprintf( "Current substitutions list: %v", - Unif.SubstsToString(Core.GetSubstListFromSubstAndFormList(st.GetSubstsFound())), + Unif.SubstsToString( + Core.GetSubstListFromSubstAndFormList(st.GetSubstsFound()), + ), ) }), ) } debug( - Lib.MkLazy(func() string { return fmt.Sprintf("Formulas to be added: %v", st.GetLF().ToString()) }), + Lib.MkLazy( + func() string { return fmt.Sprintf("Formulas to be added: %v", st.GetLF().ToString()) }, + ), ) // Dispatch newly generated formulas into the right category @@ -343,19 +428,34 @@ func (ds *destructiveSearch) ProofSearch(father_id uint64, st State, cha Communi // DMT --- Retrieve atomics for DMT debug( - Lib.MkLazy(func() string { return fmt.Sprintf("New atomics : %v", step_atomics.ToString()) }), + Lib.MkLazy( + func() string { return fmt.Sprintf("New atomics : %v", step_atomics.ToString()) }, + ), ) atomics_dmt, atomics_non_dmt := ds.getAtomicsForDMT(step_atomics, &st, s, post_dmt_step) debug( - Lib.MkLazy(func() string { return fmt.Sprintf("Atomics dmt : %v", atomics_dmt.ToString()) }), + Lib.MkLazy( + func() string { return fmt.Sprintf("Atomics dmt : %v", atomics_dmt.ToString()) }, + ), ) debug( - Lib.MkLazy(func() string { return fmt.Sprintf("Atomics non-dmt : %v", atomics_non_dmt.ToString()) }), + Lib.MkLazy( + func() string { return fmt.Sprintf("Atomics non-dmt : %v", atomics_non_dmt.ToString()) }, + ), ) // Equality - if EagerEq || (len(st.GetAlpha()) == 0 && len(st.GetDelta()) == 0 && len(st.GetBeta()) == 0) { - if TryEquality(atomics_dmt, st, step_atomics, father_id, cha, node_id, original_node_id) { + if EagerEq || + (len(st.GetAlpha()) == 0 && len(st.GetDelta()) == 0 && len(st.GetBeta()) == 0) { + if TryEquality( + atomics_dmt, + st, + step_atomics, + father_id, + cha, + node_id, + original_node_id, + ) { return } } @@ -364,24 +464,47 @@ func (ds *destructiveSearch) ProofSearch(father_id uint64, st State, cha Communi atomicsPlus := atomics_non_dmt.FilterLitPolarity(Core.Pos) atomicsMinus := atomics_non_dmt.FilterLitPolarity(Core.Neg) debug( - Lib.MkLazy(func() string { return fmt.Sprintf("Atomic plus : %v", atomicsPlus.ToString()) }), + Lib.MkLazy( + func() string { return fmt.Sprintf("Atomic plus : %v", atomicsPlus.ToString()) }, + ), ) debug( - Lib.MkLazy(func() string { return fmt.Sprintf("Atomic minus : %v", atomicsMinus.ToString()) }), + Lib.MkLazy( + func() string { return fmt.Sprintf("Atomic minus : %v", atomicsMinus.ToString()) }, + ), + ) + st.SetTreePos( + st.GetTreePos().MakeDataStruct(st.GetAtomic().Merge(atomicsPlus).ExtractForms(), true), + ) + st.SetTreeNeg( + st.GetTreeNeg(). + MakeDataStruct(st.GetAtomic().Merge(atomicsMinus).ExtractForms(), false), ) - st.SetTreePos(st.GetTreePos().MakeDataStruct(st.GetAtomic().Merge(atomicsPlus).ExtractForms(), true)) - st.SetTreeNeg(st.GetTreeNeg().MakeDataStruct(st.GetAtomic().Merge(atomicsMinus).ExtractForms(), false)) for _, f := range atomics_non_dmt { st.DispatchForm(f) } for _, f := range atomicsPlus { - if ds.searchContradiction(f.GetForm().Copy(), father_id, st, cha, node_id, original_node_id) { + if ds.searchContradiction( + f.GetForm().Copy(), + father_id, + st, + cha, + node_id, + original_node_id, + ) { return } } for _, f := range atomicsMinus { - if ds.searchContradiction(f.GetForm().Copy(), father_id, st, cha, node_id, original_node_id) { + if ds.searchContradiction( + f.GetForm().Copy(), + father_id, + st, + cha, + node_id, + original_node_id, + ) { return } } @@ -399,7 +522,15 @@ func (ds *destructiveSearch) ProofSearch(father_id uint64, st State, cha Communi ) // DoCorrectApplyRules is defined by default as ApplyRules, or to ApplyRulesAssisted if assisted flag is given. - go ds.doCorrectApplyRules(father_id, st, cha, atomics_dmt, node_id, original_node_id, meta_to_reintroduce) + go ds.doCorrectApplyRules( + father_id, + st, + cha, + atomics_dmt, + node_id, + original_node_id, + meta_to_reintroduce, + ) } } @@ -415,7 +546,12 @@ var TryEquality = func(atomics_for_dmt Core.FormAndTermsList, st State, new_atom * or the subst to apply is empty * = !(i is last and getBtOnFOrm and subst not null) **/ -func (ds *destructiveSearch) getAtomicsForDMT(new_atomics Core.FormAndTermsList, st *State, s Core.SubstAndForm, post_dmt_step bool) (Core.FormAndTermsList, Core.FormAndTermsList) { +func (ds *destructiveSearch) getAtomicsForDMT( + new_atomics Core.FormAndTermsList, + st *State, + s Core.SubstAndForm, + post_dmt_step bool, +) (Core.FormAndTermsList, Core.FormAndTermsList) { if post_dmt_step { return Core.MakeEmptyFormAndTermsList(), new_atomics } else { @@ -438,8 +574,25 @@ func (ds *destructiveSearch) waitChildren(args wcdArgs) { select { case quit := <-args.c.quit: - WriteExchanges(args.fatherId, args.st, args.givenSubsts, args.currentSubst, "WaitChildren - Die") - ds.manageQuitOrder(quit, args.c, args.fatherId, args.st, args.children, args.givenSubsts, args.nodeId, args.originalNodeId, args.childOrdering, args.toReintroduce) + WriteExchanges( + args.fatherId, + args.st, + args.givenSubsts, + args.currentSubst, + "WaitChildren - Die", + ) + ds.manageQuitOrder( + quit, + args.c, + args.fatherId, + args.st, + args.children, + args.givenSubsts, + args.nodeId, + args.originalNodeId, + args.childOrdering, + args.toReintroduce, + ) return default: debug( @@ -450,7 +603,12 @@ func (ds *destructiveSearch) waitChildren(args wcdArgs) { ) }), ) - status, substs, proofs, unifiers := ds.selectChildren(args.c, &args.children, args.currentSubst, args.childOrdering) + status, substs, proofs, unifiers := ds.selectChildren( + args.c, + &args.children, + args.currentSubst, + args.childOrdering, + ) debug( Lib.MkLazy(func() string { return fmt.Sprintf( @@ -472,20 +630,55 @@ func (ds *destructiveSearch) waitChildren(args wcdArgs) { case SUBST_FOR_CHILDREN: ds.passSubstToChildren(args, substs) case QUIT: - WriteExchanges(args.fatherId, args.st, args.givenSubsts, args.currentSubst, "WaitChildren - Die") + WriteExchanges( + args.fatherId, + args.st, + args.givenSubsts, + args.currentSubst, + "WaitChildren - Die", + ) debug(Lib.MkLazy(func() string { return "Closing order received" })) - ds.manageQuitOrder(true, args.c, args.fatherId, args.st, args.children, []Core.SubstAndForm{}, args.nodeId, args.originalNodeId, args.childOrdering, args.toReintroduce) + ds.manageQuitOrder( + true, + args.c, + args.fatherId, + args.st, + args.children, + []Core.SubstAndForm{}, + args.nodeId, + args.originalNodeId, + args.childOrdering, + args.toReintroduce, + ) case WAIT: - WriteExchanges(args.fatherId, args.st, args.givenSubsts, args.currentSubst, "WaitChildren - Wait father") + WriteExchanges( + args.fatherId, + args.st, + args.givenSubsts, + args.currentSubst, + "WaitChildren - Wait father", + ) debug(Lib.MkLazy(func() string { return "Closing order received, let's wait father" })) closeChildren(&args.children, true) - ds.waitFather(args.fatherId, args.st, args.c, args.givenSubsts, args.nodeId, args.originalNodeId, args.childOrdering, args.toReintroduce) + ds.waitFather( + args.fatherId, + args.st, + args.c, + args.givenSubsts, + args.nodeId, + args.originalNodeId, + args.childOrdering, + args.toReintroduce, + ) case OPENED: ds.manageOpenedChild(args) } if err != nil { - Glob.PrintError("WC", "Error when waiting for children. It should be an error when merging substitutions. What to do?") + Glob.PrintError( + "WC", + "Error when waiting for children. It should be an error when merging substitutions. What to do?", + ) } } } @@ -500,7 +693,16 @@ func (ds *destructiveSearch) waitChildren(args wcdArgs) { * children : list of children * given_substs : subst send by this node to its father **/ -func (ds *destructiveSearch) waitFather(father_id uint64, st State, c Communication, given_substs []Core.SubstAndForm, node_id int, original_node_id int, child_order []int, meta_to_reintroduce []int) { +func (ds *destructiveSearch) waitFather( + father_id uint64, + st State, + c Communication, + given_substs []Core.SubstAndForm, + node_id int, + original_node_id int, + child_order []int, + meta_to_reintroduce []int, +) { debug(Lib.MkLazy(func() string { return "Wait father" })) // CLear subst found @@ -508,8 +710,25 @@ func (ds *destructiveSearch) waitFather(father_id uint64, st State, c Communicat select { case quit := <-c.quit: - WriteExchanges(father_id, st, given_substs, Core.MakeEmptySubstAndForm(), "WaitFather - Die") - ds.manageQuitOrder(quit, c, father_id, st, []Communication{}, given_substs, node_id, original_node_id, child_order, meta_to_reintroduce) + WriteExchanges( + father_id, + st, + given_substs, + Core.MakeEmptySubstAndForm(), + "WaitFather - Die", + ) + ds.manageQuitOrder( + quit, + c, + father_id, + st, + []Communication{}, + given_substs, + node_id, + original_node_id, + child_order, + meta_to_reintroduce, + ) return case answer_father := <-c.result: @@ -518,27 +737,46 @@ func (ds *destructiveSearch) waitFather(father_id uint64, st State, c Communicat // Update to prune everything that shouldn't happen. WriteExchanges(father_id, st, given_substs, subst, "WaitFather") debug( - Lib.MkLazy(func() string { return fmt.Sprintf("Substition received : %v", subst.ToString()) }), + Lib.MkLazy( + func() string { return fmt.Sprintf("Substition received : %v", subst.ToString()) }, + ), ) // Check if the subst was already seen, returns eventually the subst with new formula(s) - if Core.GetSubstListFromSubstAndFormList(given_substs).Contains(answer_father.subst_for_children.GetSubst(), Lib.ListEquals[Unif.MixedSubstitution]) { + if Core.GetSubstListFromSubstAndFormList(given_substs). + Contains(answer_father.subst_for_children.GetSubst(), Lib.ListEquals[Unif.MixedSubstitution]) { debug( Lib.MkLazy(func() string { return "This substitution was sent by this child" }), ) for _, subst_sent := range given_substs { - if Lib.ListEquals(subst_sent.GetSubst(), answer_father.subst_for_children.GetSubst()) { + if Lib.ListEquals( + subst_sent.GetSubst(), + answer_father.subst_for_children.GetSubst(), + ) { subst = answer_father.getSubstForChildren().AddFormulas(subst_sent.GetForm()) } } unifier := st.GetGlobUnifier() unifier.PruneUncompatibleSubstitutions(subst.GetSubst()) if unifier.IsEmpty() { - unifier.AddSubstitutions(st.GetAppliedSubst().GetSubst(), st.GetAppliedSubst().GetSubst()) + unifier.AddSubstitutions( + st.GetAppliedSubst().GetSubst(), + st.GetAppliedSubst().GetSubst(), + ) } st.SetGlobUnifier(unifier) st.SetSubstsFound([]Core.SubstAndForm{subst}) - ds.sendSubToFather(c, true, true, father_id, st, given_substs, node_id, original_node_id, meta_to_reintroduce) + ds.sendSubToFather( + c, + true, + true, + father_id, + st, + given_substs, + node_id, + original_node_id, + meta_to_reintroduce, + ) } else { // A substitution is chosen. As free variables are kept inside the terms, we need to apply the substitution on the code tree @@ -641,7 +879,18 @@ func (ds *destructiveSearch) waitFather(father_id uint64, st State, c Communicat } /* Manage quit or wait father order. Return true if the process is supposed to die at the end */ -func (ds *destructiveSearch) manageQuitOrder(quit bool, c Communication, father_id uint64, st State, children []Communication, given_substs []Core.SubstAndForm, node_id int, original_node_id int, child_order []int, meta_to_reintroduce []int) { +func (ds *destructiveSearch) manageQuitOrder( + quit bool, + c Communication, + father_id uint64, + st State, + children []Communication, + given_substs []Core.SubstAndForm, + node_id int, + original_node_id int, + child_order []int, + meta_to_reintroduce []int, +) { if len(children) > 0 { closeChildren(&children, true) } @@ -676,7 +925,12 @@ Result : []Core.SubstAndForm : substitutions list */ -func (ds *destructiveSearch) selectChildren(father Communication, children *[]Communication, current_subst Core.SubstAndForm, child_order []int) (int, []Core.SubstAndForm, [][]ProofStruct, []Core.Unifier) { +func (ds *destructiveSearch) selectChildren( + father Communication, + children *[]Communication, + current_subst Core.SubstAndForm, + child_order []int, +) (int, []Core.SubstAndForm, [][]ProofStruct, []Core.Unifier) { proof_tab := make([][]ProofStruct, len(child_order)) @@ -688,7 +942,10 @@ func (ds *destructiveSearch) selectChildren(father Communication, children *[]Co // Manage quit order index_quit := len(*children) - cases[index_quit] = reflect.SelectCase{Dir: reflect.SelectRecv, Chan: reflect.ValueOf(father.quit)} + cases[index_quit] = reflect.SelectCase{ + Dir: reflect.SelectRecv, + Chan: reflect.ValueOf(father.quit), + } // Result struct result_int := ERROR @@ -888,7 +1145,9 @@ func (ds *destructiveSearch) selectChildren(father Communication, children *[]Co if current_subst_seen { // A child returns current subst and the other nothing debug( - Lib.MkLazy(func() string { return "One on more children returns the current subst" }), + Lib.MkLazy( + func() string { return "One on more children returns the current subst" }, + ), ) result_int = SUBST_FOR_PARENT result_subst = append(result_subst, new_current_subst) @@ -944,11 +1203,44 @@ func (ds *destructiveSearch) selectChildren(father Communication, children *[]Co return result_int, result_subst, proof_tab, unifiers } -func (ds *destructiveSearch) DoEndManageBeta(fatherId uint64, state State, c Communication, channels []Communication, currentNodeId int, originalNodeId int, childIds []int, metaToReintroduce []int) { - ds.waitChildren(MakeWcdArgs(fatherId, state, c, channels, []Core.SubstAndForm{}, Core.MakeEmptySubstAndForm(), []Core.SubstAndForm{}, []Core.IntSubstAndFormAndTerms{}, currentNodeId, originalNodeId, false, childIds, metaToReintroduce)) +func (ds *destructiveSearch) DoEndManageBeta( + fatherId uint64, + state State, + c Communication, + channels []Communication, + currentNodeId int, + originalNodeId int, + childIds []int, + metaToReintroduce []int, +) { + ds.waitChildren( + MakeWcdArgs( + fatherId, + state, + c, + channels, + []Core.SubstAndForm{}, + Core.MakeEmptySubstAndForm(), + []Core.SubstAndForm{}, + []Core.IntSubstAndFormAndTerms{}, + currentNodeId, + originalNodeId, + false, + childIds, + metaToReintroduce, + ), + ) } -func (ds *destructiveSearch) manageRewriteRules(fatherId uint64, state State, c Communication, newAtomics Core.FormAndTermsList, currentNodeId int, originalNodeId int, metaToReintroduce []int) { +func (ds *destructiveSearch) manageRewriteRules( + fatherId uint64, + state State, + c Communication, + newAtomics Core.FormAndTermsList, + currentNodeId int, + originalNodeId int, + metaToReintroduce []int, +) { debug(Lib.MkLazy(func() string { return "Try rewrite rule" })) debug( Lib.MkLazy(func() string { @@ -968,13 +1260,25 @@ func (ds *destructiveSearch) manageRewriteRules(fatherId uint64, state State, c remainingAtomics = remainingAtomics[1:].Copy() debug(Lib.MkLazy(func() string { return fmt.Sprintf("Choose : %v", f.ToString()) })) debug( - Lib.MkLazy(func() string { return fmt.Sprintf("Remaining atomics %v", remainingAtomics.ToString()) }), + Lib.MkLazy( + func() string { return fmt.Sprintf("Remaining atomics %v", remainingAtomics.ToString()) }, + ), ) // If f is in atomic, that means we couldn't rewrite it, so it's useless to check if !state.GetAtomic().Contains(f) && Glob.IsLoaded("dmt") { if rewritten, err := dmt.Rewrite(f.GetForm()); err == nil { - shouldReturn := ds.tryRewrite(rewritten, f, &state, remainingAtomics, fatherId, c, currentNodeId, originalNodeId, metaToReintroduce) + shouldReturn := ds.tryRewrite( + rewritten, + f, + &state, + remainingAtomics, + fatherId, + c, + currentNodeId, + originalNodeId, + metaToReintroduce, + ) if shouldReturn { return } @@ -985,11 +1289,30 @@ func (ds *destructiveSearch) manageRewriteRules(fatherId uint64, state State, c } //If no rewriting has been found, perform an "empty" step with unused axioms - ds.ProofSearch(fatherId, state, c, Core.MakeEmptySubstAndForm(), currentNodeId, originalNodeId, []int{}, true) + ds.ProofSearch( + fatherId, + state, + c, + Core.MakeEmptySubstAndForm(), + currentNodeId, + originalNodeId, + []int{}, + true, + ) } // FIXME: check if this function does not make the DMT version lose completeness: is the original formula that's rewritten still in the branch or not? -func (ds *destructiveSearch) tryRewrite(rewritten []Core.IntSubstAndForm, f Core.FormAndTerms, state *State, remainingAtomics Core.FormAndTermsList, fatherId uint64, c Communication, currentNodeId int, originalNodeId int, metaToReintroduce []int) bool { +func (ds *destructiveSearch) tryRewrite( + rewritten []Core.IntSubstAndForm, + f Core.FormAndTerms, + state *State, + remainingAtomics Core.FormAndTermsList, + fatherId uint64, + c Communication, + currentNodeId int, + originalNodeId int, + metaToReintroduce []int, +) bool { debug( Lib.MkLazy(func() string { return fmt.Sprintf( @@ -1004,7 +1327,13 @@ func (ds *destructiveSearch) tryRewrite(rewritten []Core.IntSubstAndForm, f Core for _, isaf_f := range isaf.GetSaf().GetForm().GetSlice() { newFNTs = append(newFNTs, Core.MakeFormAndTerm(isaf_f, f.GetTerms())) } - newRewritten = append(newRewritten, Core.MakeIntSubstAndFormAndTerms(isaf.GetId_rewrite(), Core.MakeSubstAndFormAndTerms(isaf.GetSaf().GetSubst(), newFNTs))) + newRewritten = append( + newRewritten, + Core.MakeIntSubstAndFormAndTerms( + isaf.GetId_rewrite(), + Core.MakeSubstAndFormAndTerms(isaf.GetSaf().GetSubst(), newFNTs), + ), + ) } // Keep all the possibility of rewriting and choose the first one @@ -1020,12 +1349,21 @@ func (ds *destructiveSearch) tryRewrite(rewritten []Core.IntSubstAndForm, f Core // all atomics but not the chosen one state.SetLF(append(remainingAtomics.Copy(), choosenRewrittenForm.Copy())) - state.SetBTOnFormulas(true) // I need to know that I can bt on form and my child needs to know it to to don't loop + state.SetBTOnFormulas( + true, + ) // I need to know that I can bt on form and my child needs to know it to to don't loop // Proof state.SetCurrentProofFormula(f) childNode := Glob.IncrCptNode() - state.SetCurrentProofResultFormulas([]IntFormAndTermsList{MakeIntFormAndTermsList(childNode, Core.MakeSingleElementFormAndTermList(choosenRewrittenForm.Copy()))}) + state.SetCurrentProofResultFormulas( + []IntFormAndTermsList{ + MakeIntFormAndTermsList( + childNode, + Core.MakeSingleElementFormAndTermList(choosenRewrittenForm.Copy()), + ), + }, + ) state.SetCurrentProofRule("Rewrite") state.SetCurrentProofRuleName("Rewrite") state.SetCurrentProofIdDMT(choosenRewritten.GetId_rewrite()) @@ -1038,10 +1376,35 @@ func (ds *destructiveSearch) tryRewrite(rewritten []Core.IntSubstAndForm, f Core otherState.SetBTOnFormulas(false) channelChild := Communication{make(chan bool), make(chan Result)} - go ds.ProofSearch(Glob.GetGID(), otherState, channelChild, choosenRewritten.GetSaf().ToSubstAndForm(), childNode, childNode, []int{}, false) + go ds.ProofSearch( + Glob.GetGID(), + otherState, + channelChild, + choosenRewritten.GetSaf().ToSubstAndForm(), + childNode, + childNode, + []int{}, + false, + ) debug(Lib.MkLazy(func() string { return "GO !" })) Glob.IncrGoRoutine(1) - ds.waitChildren(MakeWcdArgs(fatherId, *state, c, []Communication{channelChild}, []Core.SubstAndForm{}, choosenRewritten.GetSaf().ToSubstAndForm(), []Core.SubstAndForm{}, newRewritten, currentNodeId, originalNodeId, false, []int{childNode}, metaToReintroduce)) + ds.waitChildren( + MakeWcdArgs( + fatherId, + *state, + c, + []Communication{channelChild}, + []Core.SubstAndForm{}, + choosenRewritten.GetSaf().ToSubstAndForm(), + []Core.SubstAndForm{}, + newRewritten, + currentNodeId, + originalNodeId, + false, + []int{childNode}, + metaToReintroduce, + ), + ) return true } else { // No rewriting possible @@ -1082,11 +1445,15 @@ func (ds *destructiveSearch) ManageClosureRule( switch { case substs.Empty(): debug( - Lib.MkLazy(func() string { return "Branch closed by ¬⊤ or ⊥ or a litteral and its opposite!" }), + Lib.MkLazy( + func() string { return "Branch closed by ¬⊤ or ⊥ or a litteral and its opposite!" }, + ), ) if Glob.GetAssisted() { - fmt.Printf("Branch can be closed by ¬⊤, ⊥ or a litteral and its opposite!\nApplying it automatically...\n") + fmt.Printf( + "Branch can be closed by ¬⊤, ⊥ or a litteral and its opposite!\nApplying it automatically...\n", + ) } st.SetSubstsFound([]Core.SubstAndForm{st.GetAppliedSubst()}) @@ -1104,7 +1471,17 @@ func (ds *destructiveSearch) ManageClosureRule( // No new subst needed in the Glob unifier if !Glob.GetAssisted() { - ds.sendSubToFather(c, true, false, Glob.GetGID(), *st, []Core.SubstAndForm{}, node_id, original_node_id, []int{}) + ds.sendSubToFather( + c, + true, + false, + Glob.GetGID(), + *st, + []Core.SubstAndForm{}, + node_id, + original_node_id, + []int{}, + ) } case !substs_without_mm.Empty(): @@ -1117,7 +1494,9 @@ func (ds *destructiveSearch) ManageClosureRule( ) if Glob.GetAssisted() && !substs_without_mm.At(0).Empty() { - fmt.Printf("The branch can be closed by using a substitution which has no impact elsewhere!\nApplying it automatically : ") + fmt.Printf( + "The branch can be closed by using a substitution which has no impact elsewhere!\nApplying it automatically : ", + ) fmt.Printf("%v !\n", Unif.SubstsToString(substs_without_mm)) } @@ -1141,7 +1520,17 @@ func (ds *destructiveSearch) ManageClosureRule( } st.SetGlobUnifier(unifier) if !Glob.GetAssisted() { - ds.sendSubToFather(c, true, false, Glob.GetGID(), *st, []Core.SubstAndForm{}, node_id, original_node_id, []int{}) + ds.sendSubToFather( + c, + true, + false, + Glob.GetGID(), + *st, + []Core.SubstAndForm{}, + node_id, + original_node_id, + []int{}, + ) } case !substs_with_mm.Empty(): @@ -1171,7 +1560,10 @@ func (ds *destructiveSearch) ManageClosureRule( ) // Create substAndForm with the current form and the subst found - subst_and_form_for_father := Core.MakeSubstAndForm(subst_for_father, Lib.MkListV(f.GetForm())) + subst_and_form_for_father := Core.MakeSubstAndForm( + subst_for_father, + Lib.MkListV(f.GetForm()), + ) debug( Lib.MkLazy(func() string { @@ -1182,16 +1574,25 @@ func (ds *destructiveSearch) ManageClosureRule( ) // Merge with applied subst (if any) - err, subst_and_form_for_father := Core.MergeSubstAndForm(subst_and_form_for_father.Copy(), st.GetAppliedSubst()) + err, subst_and_form_for_father := Core.MergeSubstAndForm( + subst_and_form_for_father.Copy(), + st.GetAppliedSubst(), + ) if err != nil { - Glob.PrintError("MCR", "Contradiction found between applied subst and child subst. What to do?") + Glob.PrintError( + "MCR", + "Contradiction found between applied subst and child subst. What to do?", + ) } else { st.SetSubstsFound(Core.AppendIfNotContainsSubstAndForm(st.GetSubstsFound(), subst_and_form_for_father)) } - meta_to_reintroduce = Glob.UnionIntList(meta_to_reintroduce, retrieveMetaFromSubst(subst_for_father)) + meta_to_reintroduce = Glob.UnionIntList( + meta_to_reintroduce, + retrieveMetaFromSubst(subst_for_father), + ) } if Glob.GetAssisted() { @@ -1230,7 +1631,15 @@ func (ds *destructiveSearch) ManageClosureRule( } /* Apply rules with priority (closure < rewrite < alpha < delta < closure with mm < beta < gamma) */ -func (ds *destructiveSearch) applyRules(fatherId uint64, state State, c Communication, atomicDMT Core.FormAndTermsList, currentNodeId int, originalNodeId int, metaToReintroduce []int) { +func (ds *destructiveSearch) applyRules( + fatherId uint64, + state State, + c Communication, + atomicDMT Core.FormAndTermsList, + currentNodeId int, + originalNodeId int, + metaToReintroduce []int, +) { debug(Lib.MkLazy(func() string { return "ApplyRule" })) debug( Lib.MkLazy(func() string { @@ -1248,7 +1657,15 @@ func (ds *destructiveSearch) applyRules(fatherId uint64, state State, c Communic state.GetTreeNeg().Print() switch { case len(atomicDMT) > 0 && Glob.IsLoaded("dmt") && len(state.GetSubstsFound()) == 0: - ds.manageRewriteRules(fatherId, state, c, atomicDMT, currentNodeId, originalNodeId, metaToReintroduce) + ds.manageRewriteRules( + fatherId, + state, + c, + atomicDMT, + currentNodeId, + originalNodeId, + metaToReintroduce, + ) case len(state.GetAlpha()) > 0: ds.manageAlphaRules(fatherId, state, c, originalNodeId) @@ -1263,18 +1680,42 @@ func (ds *destructiveSearch) applyRules(fatherId uint64, state State, c Communic ds.manageGammaRules(fatherId, state, c, originalNodeId) case len(state.GetMetaGen()) > 0 && state.CanReintroduce(): - ds.manageReintroductionRules(fatherId, state, c, originalNodeId, metaToReintroduce, atomicDMT, currentNodeId, true) + ds.manageReintroductionRules( + fatherId, + state, + c, + originalNodeId, + metaToReintroduce, + atomicDMT, + currentNodeId, + true, + ) default: WriteExchanges(fatherId, state, nil, Core.MakeEmptySubstAndForm(), "ApplyRules - SAT") state.SetCurrentProofRule("Sat") state.SetProof(append(state.GetProof(), state.GetCurrentProof())) debug(Lib.MkLazy(func() string { return "Nothing found, return sat" })) - ds.sendSubToFather(c, false, false, fatherId, state, []Core.SubstAndForm{}, currentNodeId, originalNodeId, []int{}) + ds.sendSubToFather( + c, + false, + false, + fatherId, + state, + []Core.SubstAndForm{}, + currentNodeId, + originalNodeId, + []int{}, + ) } } -func (ds *destructiveSearch) manageAlphaRules(fatherId uint64, state State, c Communication, originalNodeId int) { +func (ds *destructiveSearch) manageAlphaRules( + fatherId uint64, + state State, + c Communication, + originalNodeId int, +) { debug(Lib.MkLazy(func() string { return "Alpha rule" })) hdf := state.GetAlpha()[0] debug(Lib.MkLazy(func() string { return fmt.Sprintf("Rule applied on : %s", hdf.ToString()) })) @@ -1285,13 +1726,29 @@ func (ds *destructiveSearch) manageAlphaRules(fatherId uint64, state State, c Co // Proof state.SetCurrentProofFormula(hdf) childId := Glob.IncrCptNode() - state.SetCurrentProofResultFormulas([]IntFormAndTermsList{MakeIntFormAndTermsList(childId, resultForms)}) + state.SetCurrentProofResultFormulas( + []IntFormAndTermsList{MakeIntFormAndTermsList(childId, resultForms)}, + ) state.SetProof(append(state.GetProof(), state.GetCurrentProof())) - ds.ProofSearch(fatherId, state, c, Core.MakeEmptySubstAndForm(), childId, originalNodeId, []int{}, false) + ds.ProofSearch( + fatherId, + state, + c, + Core.MakeEmptySubstAndForm(), + childId, + originalNodeId, + []int{}, + false, + ) } -func (ds *destructiveSearch) manageDeltaRules(fatherId uint64, state State, c Communication, originalNodeId int) { +func (ds *destructiveSearch) manageDeltaRules( + fatherId uint64, + state State, + c Communication, + originalNodeId int, +) { debug(Lib.MkLazy(func() string { return "Delta rule" })) hdf := state.GetDelta()[0] debug(Lib.MkLazy(func() string { return fmt.Sprintf("Rule applied on : %s", hdf.ToString()) })) @@ -1302,13 +1759,31 @@ func (ds *destructiveSearch) manageDeltaRules(fatherId uint64, state State, c Co // Proof state.SetCurrentProofFormula(hdf) childId := Glob.IncrCptNode() - state.SetCurrentProofResultFormulas([]IntFormAndTermsList{MakeIntFormAndTermsList(childId, resultForms)}) + state.SetCurrentProofResultFormulas( + []IntFormAndTermsList{MakeIntFormAndTermsList(childId, resultForms)}, + ) state.SetProof(append(state.GetProof(), state.GetCurrentProof())) - ds.ProofSearch(fatherId, state, c, Core.MakeEmptySubstAndForm(), childId, originalNodeId, []int{}, false) + ds.ProofSearch( + fatherId, + state, + c, + Core.MakeEmptySubstAndForm(), + childId, + originalNodeId, + []int{}, + false, + ) } -func (ds *destructiveSearch) manageBetaRules(fatherId uint64, state State, c Communication, currentNodeId int, originalNodeId int, metaToReintroduce []int) { +func (ds *destructiveSearch) manageBetaRules( + fatherId uint64, + state State, + c Communication, + currentNodeId int, + originalNodeId int, + metaToReintroduce []int, +) { debug(Lib.MkLazy(func() string { return "Beta rule" })) hdf := state.GetBeta()[0] debug(Lib.MkLazy(func() string { return fmt.Sprintf("Rule applied on : %s", hdf.ToString()) })) @@ -1335,7 +1810,16 @@ func (ds *destructiveSearch) manageBetaRules(fatherId uint64, state State, c Com if Glob.IsDestructive() { channelChild := Communication{make(chan bool), make(chan Result)} channels = append(channels, channelChild) - go ds.ProofSearch(Glob.GetGID(), otherState, channelChild, Core.MakeEmptySubstAndForm(), fl.GetI(), fl.GetI(), []int{}, false) + go ds.ProofSearch( + Glob.GetGID(), + otherState, + channelChild, + Core.MakeEmptySubstAndForm(), + fl.GetI(), + fl.GetI(), + []int{}, + false, + ) } else { go ds.ProofSearch(Glob.GetGID(), otherState, c, Core.MakeEmptySubstAndForm(), fl.GetI(), fl.GetI(), []int{}, false) } @@ -1345,10 +1829,24 @@ func (ds *destructiveSearch) manageBetaRules(fatherId uint64, state State, c Com } - ds.DoEndManageBeta(fatherId, state, c, channels, currentNodeId, originalNodeId, childIds, metaToReintroduce) + ds.DoEndManageBeta( + fatherId, + state, + c, + channels, + currentNodeId, + originalNodeId, + childIds, + metaToReintroduce, + ) } -func (ds *destructiveSearch) manageGammaRules(fatherId uint64, state State, c Communication, originalNodeId int) { +func (ds *destructiveSearch) manageGammaRules( + fatherId uint64, + state State, + c Communication, + originalNodeId int, +) { debug(Lib.MkLazy(func() string { return "Gamma rule" })) hdf := state.GetGamma()[0] debug(Lib.MkLazy(func() string { return fmt.Sprintf("Rule applied on : %s", hdf.ToString()) })) @@ -1372,13 +1870,33 @@ func (ds *destructiveSearch) manageGammaRules(fatherId uint64, state State, c Co // Proof state.SetCurrentProofFormula(hdf) childId := Glob.IncrCptNode() - state.SetCurrentProofResultFormulas([]IntFormAndTermsList{MakeIntFormAndTermsList(childId, newFnts)}) + state.SetCurrentProofResultFormulas( + []IntFormAndTermsList{MakeIntFormAndTermsList(childId, newFnts)}, + ) state.SetProof(append(state.GetProof(), state.GetCurrentProof())) - ds.ProofSearch(fatherId, state, c, Core.MakeEmptySubstAndForm(), childId, originalNodeId, []int{}, false) + ds.ProofSearch( + fatherId, + state, + c, + Core.MakeEmptySubstAndForm(), + childId, + originalNodeId, + []int{}, + false, + ) } -func (ds *destructiveSearch) manageReintroductionRules(fatherId uint64, state State, c Communication, originalNodeId int, metaToReintroduce []int, newAtomics Core.FormAndTermsList, currentNodeId int, reintroduceAnyway bool) { +func (ds *destructiveSearch) manageReintroductionRules( + fatherId uint64, + state State, + c Communication, + originalNodeId int, + metaToReintroduce []int, + newAtomics Core.FormAndTermsList, + currentNodeId int, + reintroduceAnyway bool, +) { currentMTR := -1 @@ -1393,7 +1911,9 @@ func (ds *destructiveSearch) manageReintroductionRules(fatherId uint64, state St newMetaGen := state.GetMetaGen() reslf := Core.ReintroduceMeta(&newMetaGen, currentMTR, state.GetN()) debug( - Lib.MkLazy(func() string { return fmt.Sprintf("Reintroduce the formula : %s", reslf.ToString()) }), + Lib.MkLazy( + func() string { return fmt.Sprintf("Reintroduce the formula : %s", reslf.ToString()) }, + ), ) state.SetLF(Core.MakeSingleElementFormAndTermList(reslf)) @@ -1405,17 +1925,32 @@ func (ds *destructiveSearch) manageReintroductionRules(fatherId uint64, state St state.SetCurrentProofRule("Reintroduction") state.SetCurrentProofRuleName("Reintroduction") state.SetCurrentProofFormula(reslf) - state.SetCurrentProofResultFormulas([]IntFormAndTermsList{MakeIntFormAndTermsList(childId, Core.MakeSingleElementFormAndTermList(reslf))}) + state.SetCurrentProofResultFormulas( + []IntFormAndTermsList{ + MakeIntFormAndTermsList(childId, Core.MakeSingleElementFormAndTermList(reslf)), + }, + ) state.SetProof(append(state.GetProof(), state.GetCurrentProof())) - ds.ProofSearch(fatherId, state, c, Core.MakeEmptySubstAndForm(), childId, originalNodeId, metaToReintroduce, false) + ds.ProofSearch( + fatherId, + state, + c, + Core.MakeEmptySubstAndForm(), + childId, + originalNodeId, + metaToReintroduce, + false, + ) } func (ds *destructiveSearch) manageResult(c Communication) (Core.Unifier, []ProofStruct, bool) { result := <-c.getResult() debug( - Lib.MkLazy(func() string { return fmt.Sprintf("Proof : %v", ProofStructListToString(result.getProof())) }), + Lib.MkLazy( + func() string { return fmt.Sprintf("Proof : %v", ProofStructListToString(result.getProof())) }, + ), ) if result.needsAnswer() { diff --git a/src/Search/incremental/rules.go b/src/Search/incremental/rules.go index 2c84899a..698b9ebd 100644 --- a/src/Search/incremental/rules.go +++ b/src/Search/incremental/rules.go @@ -389,7 +389,10 @@ func (gne *GammaNotExists) apply() []RuleList { resultRules := RuleList{} debug(Lib.MkLazy(func() string { return "Applying " + fmt.Sprint(gne.FullString) })) - instanciatedForm, metas := Core.Instantiate(Core.MakeFormAndTerm(gne.GetForm(), gne.GetTerms()), 42) + instanciatedForm, metas := Core.Instantiate( + Core.MakeFormAndTerm(gne.GetForm(), gne.GetTerms()), + 42, + ) newTerms := gne.GetTerms().Copy(AST.Term.Copy) newTerms.Add(AST.TermEquals, AST.MetaListToTermList(metas.Elements()).GetSlice()...) resultRules = append(resultRules, makeCorrectRule(instanciatedForm.GetForm(), newTerms)) @@ -412,15 +415,6 @@ func (gne *GammaNotExists) getGeneratedMetas() Lib.List[AST.Meta] { return gne.generatedMetas } -func (gne *GammaNotExists) getVarList() Lib.List[AST.TypedVar] { - if not, isNot := gne.formula.(AST.Not); isNot { - if exists, isExists := not.GetForm().(AST.Ex); isExists { - return exists.GetVarList() - } - } - return Lib.NewList[AST.TypedVar]() -} - type GammaForall struct { AnyRule generatedMetas Lib.List[AST.Meta] @@ -430,7 +424,10 @@ func (gf *GammaForall) apply() []RuleList { resultRules := RuleList{} debug(Lib.MkLazy(func() string { return "Applying " + fmt.Sprint(gf.FullString) })) - instanciatedForm, metas := Core.Instantiate(Core.MakeFormAndTerm(gf.GetForm(), gf.GetTerms()), 42) + instanciatedForm, metas := Core.Instantiate( + Core.MakeFormAndTerm(gf.GetForm(), gf.GetTerms()), + 42, + ) newTerms := gf.GetTerms().Copy(AST.Term.Copy) newTerms.Add(AST.TermEquals, AST.MetaListToTermList(metas.Elements()).GetSlice()...) resultRules = append(resultRules, makeCorrectRule(instanciatedForm.GetForm(), newTerms)) @@ -453,13 +450,6 @@ func (gf *GammaForall) getGeneratedMetas() Lib.List[AST.Meta] { return gf.generatedMetas } -func (gf *GammaForall) getVarList() Lib.List[AST.TypedVar] { - if forall, isForall := gf.formula.(AST.All); isForall { - return forall.GetVarList() - } - return Lib.NewList[AST.TypedVar]() -} - type DeltaNotForall struct { AnyRule } diff --git a/src/Search/nonDestructiveSearch.go b/src/Search/nonDestructiveSearch.go index 55c0b275..c8297c7d 100644 --- a/src/Search/nonDestructiveSearch.go +++ b/src/Search/nonDestructiveSearch.go @@ -44,6 +44,8 @@ import ( "github.com/GoelandProver/Goeland/Unif" ) +// FIXME + type nonDestructiveSearch struct { } @@ -65,20 +67,45 @@ func getMetas(substs Lib.List[Unif.MixedSubstitution]) Lib.List[AST.Meta] { return metas } -func (nds *nonDestructiveSearch) setApplyRules(function func(uint64, State, Communication, Core.FormAndTermsList, int, int, []int)) { - Glob.PrintError("NDS", "Non-destructive search not compatible with the assisted plugin for now.") +func (nds *nonDestructiveSearch) setApplyRules( + function func(uint64, State, Communication, Core.FormAndTermsList, int, int, []int), +) { + Glob.PrintError( + "NDS", + "Non-destructive search not compatible with the assisted plugin for now.", + ) } -func (nds *nonDestructiveSearch) doEndManageBeta(fatherId uint64, state State, c Communication, channels []Communication, currentNodeId int, originalNodeId int, childIds []int, metaToReintroduce []int) { +func (nds *nonDestructiveSearch) doEndManageBeta( + fatherId uint64, + state State, + c Communication, + channels []Communication, + currentNodeId int, + originalNodeId int, + childIds []int, + metaToReintroduce []int, +) { debug(Lib.MkLazy(func() string { return "Die" })) } -func (nds *nonDestructiveSearch) manageRewriteRules(fatherId uint64, state State, c Communication, newAtomics Core.FormAndTermsList, currentNodeId int, originalNodeId int, metaToReintroduce []int) { +func (nds *nonDestructiveSearch) manageRewriteRules( + fatherId uint64, + state State, + c Communication, + newAtomics Core.FormAndTermsList, + currentNodeId int, + originalNodeId int, + metaToReintroduce []int, +) { Glob.PrintError("NDS", "Non-destructive search not compatible with the DMT plugin for now.") } /* Choose substitution - whitout meta in lastAppliedSubst */ -func (nds *nonDestructiveSearch) chooseSubstitutionWithoutMetaLastApplyNonDestructive(sl []Core.SubstAndForm, ml Lib.List[AST.Meta]) (Core.SubstAndForm, []Core.SubstAndForm) { +func (nds *nonDestructiveSearch) chooseSubstitutionWithoutMetaLastApplyNonDestructive( + sl []Core.SubstAndForm, + ml Lib.List[AST.Meta], +) (Core.SubstAndForm, []Core.SubstAndForm) { for i, v := range sl { if !AST.IsIncludeInsideOF(getMetas(v.GetSubst()), ml) { return v, Core.RemoveSubstFromSubstAndFormList(i, sl) @@ -88,7 +115,10 @@ func (nds *nonDestructiveSearch) chooseSubstitutionWithoutMetaLastApplyNonDestru } /* Choose substitution - whith meta in lastAppliedSubst */ -func (nds *nonDestructiveSearch) chooseSubstitutionWithtMetaLastApplyNonDestructive(sl []Core.SubstAndForm, last_applied_subst Core.SubstAndForm) (Core.SubstAndForm, []Core.SubstAndForm) { +func (nds *nonDestructiveSearch) chooseSubstitutionWithtMetaLastApplyNonDestructive( + sl []Core.SubstAndForm, + last_applied_subst Core.SubstAndForm, +) (Core.SubstAndForm, []Core.SubstAndForm) { for i, v := range sl { if !Lib.ListEquals(v.GetSubst(), last_applied_subst.GetSubst()) { return v, Core.RemoveSubstFromSubstAndFormList(i, sl) @@ -98,8 +128,14 @@ func (nds *nonDestructiveSearch) chooseSubstitutionWithtMetaLastApplyNonDestruct } /* Choose the best substitution among subst_found_at_this_step and subst_found */ -func (nds *nonDestructiveSearch) chooseSubstitutionNonDestructive(substs_found_this_step []Core.SubstAndForm, st *State) Core.SubstAndForm { - res, sl := nds.chooseSubstitutionWithoutMetaLastApplyNonDestructive(substs_found_this_step, getMetas(st.GetLastAppliedSubst().GetSubst())) +func (nds *nonDestructiveSearch) chooseSubstitutionNonDestructive( + substs_found_this_step []Core.SubstAndForm, + st *State, +) Core.SubstAndForm { + res, sl := nds.chooseSubstitutionWithoutMetaLastApplyNonDestructive( + substs_found_this_step, + getMetas(st.GetLastAppliedSubst().GetSubst()), + ) if !res.IsEmpty() { // subst without meta in last applied meta found in substs_found_at_this_step st.SetSubstsFound(append(sl, st.GetSubstsFound()...)) return res @@ -132,29 +168,24 @@ func (nds *nonDestructiveSearch) chooseSubstitutionNonDestructive(substs_found_t } /* Take a substitution, returns the id of the formula which introduce the metavariable */ -func (nds *nonDestructiveSearch) catchFormulaToInstantiate(subst_found Lib.List[Unif.MixedSubstitution]) int { - meta_to_reintroduce := -1 - for _, subst := range subst_found.GetSlice() { - switch s := subst.Substitution().(type) { - case Lib.Some[Unif.Substitution]: - meta, term := s.Val.Get() - if meta.GetFormula() < meta_to_reintroduce || meta_to_reintroduce == -1 { - meta_to_reintroduce = meta.GetFormula() - } - if term.IsMeta() { - if term.ToMeta().GetFormula() < meta_to_reintroduce || meta_to_reintroduce == -1 { - meta_to_reintroduce = term.ToMeta().GetFormula() - } - } - } - } - return meta_to_reintroduce +func (nds *nonDestructiveSearch) catchFormulaToInstantiate( + subst_found Lib.List[Unif.MixedSubstitution], +) int { + return -1 } -/** Instantiate a formula with a substitution +/* +* Instantiate a formula with a substitution * Got the substitution (X, a) and reintroduce ForAll x P(x) -> need to reintroduce P(a). Remplace immediatly the new generated metavariable by a. -**/ -func (nds *nonDestructiveSearch) instantiate(fatherId uint64, state *State, c Communication, index int, s Core.SubstAndForm) { +* + */ +func (nds *nonDestructiveSearch) instantiate( + fatherId uint64, + state *State, + c Communication, + index int, + s Core.SubstAndForm, +) { debug( Lib.MkLazy(func() string { return fmt.Sprintf( @@ -167,7 +198,9 @@ func (nds *nonDestructiveSearch) instantiate(fatherId uint64, state *State, c Co reslf := Core.ReintroduceMeta(&newMetaGenerator, index, state.GetN()) state.SetMetaGen(newMetaGenerator) debug( - Lib.MkLazy(func() string { return fmt.Sprintf("Instantiate the formula : %s", reslf.ToString()) }), + Lib.MkLazy( + func() string { return fmt.Sprintf("Instantiate the formula : %s", reslf.ToString()) }, + ), ) // Apply gamma rule @@ -201,7 +234,8 @@ func (nds *nonDestructiveSearch) instantiate(fatherId uint64, state *State, c Co // Trouver celle de la formula de base for _, f := range s.GetForm().GetSlice() { for _, term_formula := range f.GetMetas().Elements().GetSlice() { - if !found && term_formula.IsMeta() && term_formula.GetName() == new_meta.GetName() { + if !found && term_formula.IsMeta() && + term_formula.GetName() == new_meta.GetName() { association_subst.Set(new_meta, term_formula) found = true } @@ -237,7 +271,10 @@ func (nds *nonDestructiveSearch) instantiate(fatherId uint64, state *State, c Co for _, subst := range association_subst { mixed_assoc_subst.Append(Unif.MkMixedFromSubst(subst)) } - new_subst, same_key := Unif.MergeMixedSubstitutions(mixed_assoc_subst, state.GetAppliedSubst().GetSubst()) + new_subst, same_key := Unif.MergeMixedSubstitutions( + mixed_assoc_subst, + state.GetAppliedSubst().GetSubst(), + ) if same_key { Glob.PrintInfo("PS", "Same key in S2 and S1") } @@ -265,7 +302,9 @@ func (nds *nonDestructiveSearch) instantiate(fatherId uint64, state *State, c Co debug( Lib.MkLazy(func() string { return fmt.Sprintf( - "Real substitution applied : %s", Lib.ListToString(new_subst, ", ", "(empty subst)")) + "Real substitution applied : %s", + Lib.ListToString(new_subst, ", ", "(empty subst)"), + ) }), ) @@ -287,7 +326,12 @@ func (nds *nonDestructiveSearch) instantiate(fatherId uint64, state *State, c Co * Choose the best subtitution to instantiate : avoid the same than last used, and the one which contains meta already used in last applied **/ -func (nds *nonDestructiveSearch) manageSubstFoundNonDestructive(father_id uint64, st *State, c Communication, substs_found_at_this_step []Core.SubstAndFormAndTerms) (int, Core.SubstAndForm) { +func (nds *nonDestructiveSearch) manageSubstFoundNonDestructive( + father_id uint64, + st *State, + c Communication, + substs_found_at_this_step []Core.SubstAndFormAndTerms, +) (int, Core.SubstAndForm) { form_to_instantiate := -1 choosen_subst := Core.MakeEmptySubstAndForm() new_choosen_subst := Core.MakeEmptySubstAndForm() @@ -322,7 +366,9 @@ func (nds *nonDestructiveSearch) manageSubstFoundNonDestructive(father_id uint64 ) })) debug( - Lib.MkLazy(func() string { return fmt.Sprintf("AreRulesApplicable : %v", st.AreRulesApplicable()) }), + Lib.MkLazy( + func() string { return fmt.Sprintf("AreRulesApplicable : %v", st.AreRulesApplicable()) }, + ), ) choosen_subst = new_choosen_subst @@ -330,7 +376,9 @@ func (nds *nonDestructiveSearch) manageSubstFoundNonDestructive(father_id uint64 // Catch all the meta which can be instantiate form_to_instantiate = nds.catchFormulaToInstantiate(choosen_subst.GetSubst()) debug( - Lib.MkLazy(func() string { return fmt.Sprintf("Form_to_instantiate : %v", form_to_instantiate) }), + Lib.MkLazy( + func() string { return fmt.Sprintf("Form_to_instantiate : %v", form_to_instantiate) }, + ), ) return form_to_instantiate, choosen_subst @@ -411,9 +459,18 @@ func (ds *nonDestructiveSearch) manageResult(c Communication) (Core.Unifier, []P time.Sleep(1 * time.Millisecond) debug( - Lib.MkLazy(func() string { return fmt.Sprintf("open is : %v from %v", open, res.getId()) }), + Lib.MkLazy( + func() string { return fmt.Sprintf("open is : %v from %v", open, res.getId()) }, + ), + ) + Glob.PrintInfo( + "MAIN", + fmt.Sprintf( + "%v goroutines still running - %v goroutines generated", + runtime.NumGoroutine(), + Glob.GetNbGoroutines(), + ), ) - Glob.PrintInfo("MAIN", fmt.Sprintf("%v goroutines still running - %v goroutines generated", runtime.NumGoroutine(), Glob.GetNbGoroutines())) } return Core.MakeUnifier(), []ProofStruct{}, !open diff --git a/src/Search/proof-adapter.go b/src/Search/proof-adapter.go index 9acd4aa8..cc12201d 100644 --- a/src/Search/proof-adapter.go +++ b/src/Search/proof-adapter.go @@ -157,21 +157,7 @@ func (proof TableauxProof) TermGenerated() Lib.Option[Lib.Either[AST.Ty, AST.Ter source_form := proof[0].Formula.GetForm() target_form := proof[0].Result_formulas[0].GetForms().At(0) - - replaced_variable, is_quantified := getReplacedVariable(source_form) - - if !is_quantified { - return Lib.MkNone[Lib.Either[AST.Ty, AST.Term]]() - } - debug(Lib.MkLazy(func() string { - return fmt.Sprintf( - "Trying to get occurrence of %s in %s", - replaced_variable.ToString(), - source_form.ToString(), - ) - })) - - occurrence_opt := getOneOccurrence(source_form, replaced_variable) + occurrence_opt := getOneOccurrence(source_form) return Lib.OptBind( occurrence_opt, @@ -179,7 +165,7 @@ func (proof TableauxProof) TermGenerated() Lib.Option[Lib.Either[AST.Ty, AST.Ter debug(Lib.MkLazy(func() string { return fmt.Sprintf( "Target: %s, occurrence: [%s]", - getCleanForm(target_form).ToString(), + target_form.ToString(), Lib.ListToString(occurrence, ", ", ""), ) })) @@ -224,66 +210,52 @@ func getAtomic(f AST.Form) AST.Form { return nil } -func getReplacedVariable(form AST.Form) (AST.TypedVar, bool) { - get_first := func(vars Lib.List[AST.TypedVar]) (AST.TypedVar, bool) { - if vars.Empty() { - return AST.TypedVar{}, false - } - return vars.At(0), true - } - - switch f := form.(type) { - case AST.All: - return get_first(f.GetVarList()) - case AST.Ex: - return get_first(f.GetVarList()) - case AST.Not: - switch nf := f.GetForm().(type) { - case AST.All: - return get_first(nf.GetVarList()) - case AST.Ex: - return get_first(nf.GetVarList()) - } - } - - return AST.TypedVar{}, false -} - -// A variable might be quantified but never appear in a formula -func getOneOccurrence(form AST.Form, v AST.TypedVar) Lib.Option[Lib.List[Lib.Int]] { - return getOneOccInCleanForm(getCleanForm(form), v, Lib.NewList[Lib.Int]()) +func getOneOccurrence(form AST.Form) Lib.Option[Lib.List[Lib.Int]] { + return getOneOccInCleanForm(getCleanForm(form), 0, Lib.NewList[Lib.Int]()) } func getTermAtOcc(form AST.Form, occurrence Lib.List[Lib.Int]) Lib.Either[AST.Ty, AST.Term] { - return getTermAtOccInCleanForm(getCleanForm(form), occurrence) + return getTermAtOccInCleanForm(form, occurrence) } func getCleanForm(form AST.Form) AST.Form { switch f := form.(type) { case AST.Not: - return AST.MakeNot(getCleanForm_rec(f.GetForm())) + return AST.MakeNot(getCleanForm_aux(f.GetForm())) } - return getCleanForm_rec(form) + return getCleanForm_aux(form) } -func getCleanForm_rec(form AST.Form) AST.Form { - switch f := form.(type) { +func getCleanForm_aux(form AST.Form) AST.Form { + switch form := form.(type) { case AST.All: - return getCleanForm(f.GetForm()) + return form.GetForm() case AST.Ex: - return getCleanForm(f.GetForm()) + return form.GetForm() } return form } func getOneOccInCleanForm( form AST.Form, - v AST.TypedVar, + v int, occurrence Lib.List[Lib.Int], ) Lib.Option[Lib.List[Lib.Int]] { switch f := form.(type) { case AST.Pred: return getFunctionalOcc(f.GetTyArgs(), f.GetArgs(), v, occurrence) + case AST.All: + return getOneOccInCleanForm( + f.GetForm(), + v+1, + appCopy(Lib.MkInt(0), occurrence), + ) + case AST.Ex: + return getOneOccInCleanForm( + f.GetForm(), + v+1, + appCopy(Lib.MkInt(0), occurrence), + ) default: for i, child := range form.GetChildFormulas().GetSlice() { @@ -318,12 +290,12 @@ func getTermAtOccInCleanForm( func getFunctionalOcc( tys Lib.List[AST.Ty], terms Lib.List[AST.Term], - v AST.TypedVar, + v int, occurrence Lib.List[Lib.Int], ) Lib.Option[Lib.List[Lib.Int]] { for i, ty := range tys.GetSlice() { local_occ := appCopy(Lib.MkInt(i), occurrence) - occ := getOneOccInTy(ty, v.ToTyBoundVar(), local_occ) + occ := getOneOccInTy(ty, v, local_occ) if _, ok := occ.(Lib.Some[Lib.List[Lib.Int]]); ok { return occ @@ -374,12 +346,12 @@ func appCopy[A Lib.Copyable[A]](x A, ls Lib.List[A]) Lib.List[A] { func getOneOccInTy( ty AST.Ty, - v AST.TyBound, + v int, occurrence Lib.List[Lib.Int], ) Lib.Option[Lib.List[Lib.Int]] { switch t := ty.(type) { case AST.TyBound: - if t.Equals(v) { + if t.Equals(AST.MkTyBV(v)) { return Lib.MkSome(occurrence) } return Lib.MkNone[Lib.List[Lib.Int]]() @@ -423,12 +395,12 @@ func getTermInTy(ty AST.Ty, occurrence Lib.List[Lib.Int]) AST.Ty { func getOneOccInTrm( trm AST.Term, - v AST.TypedVar, + v int, occurrence Lib.List[Lib.Int], ) Lib.Option[Lib.List[Lib.Int]] { switch t := trm.(type) { case AST.Var: - if t.Equals(v.ToBoundVar()) { + if t.Equals(AST.MakeVar(v)) { return Lib.MkSome(occurrence) } return Lib.MkNone[Lib.List[Lib.Int]]() diff --git a/src/Search/rules.go b/src/Search/rules.go index 7cdb0877..31f39702 100644 --- a/src/Search/rules.go +++ b/src/Search/rules.go @@ -59,7 +59,10 @@ var strToPrintMap map[string]string = map[string]string{ "EXISTS": "∃", } -func ApplyClosureRules(form AST.Form, state *State) (bool, Lib.List[Lib.List[Unif.MixedSubstitution]]) { +func ApplyClosureRules( + form AST.Form, + state *State, +) (bool, Lib.List[Lib.List[Unif.MixedSubstitution]]) { result := false substitutions := Lib.NewList[Lib.List[Unif.MixedSubstitution]]() debug(Lib.MkLazy(func() string { return "Start ACR" })) @@ -175,15 +178,21 @@ func searchInequalities(form AST.Form) (bool, Unif.Substitutions) { arg_2 := predNeq.GetArgs().At(1) debug( - Lib.MkLazy(func() string { return fmt.Sprintf("Arg 1 : %v", arg_1.ToString()) }), + Lib.MkLazy( + func() string { return fmt.Sprintf("Arg 1 : %v", arg_1.ToString()) }, + ), ) debug( - Lib.MkLazy(func() string { return fmt.Sprintf("Arg 2 : %v", arg_2.ToString()) }), + Lib.MkLazy( + func() string { return fmt.Sprintf("Arg 2 : %v", arg_2.ToString()) }, + ), ) subst = Unif.AddUnification(arg_1, arg_2, subst) debug( - Lib.MkLazy(func() string { return fmt.Sprintf("Subst : %v", subst.ToString()) }), + Lib.MkLazy( + func() string { return fmt.Sprintf("Subst : %v", subst.ToString()) }, + ), ) if !subst.Equals(Unif.Failure()) { @@ -309,7 +318,9 @@ func applyAlphaNotImpRule( setStateRules(state, "ALPHA", "NOT", "IMPLY") result = result.AppendIfNotContains(Core.MakeFormAndTerm(formWithoutNot.GetF1(), terms)) - result = result.AppendIfNotContains(Core.MakeFormAndTerm(AST.MakeNot(formWithoutNot.GetF2()), terms)) + result = result.AppendIfNotContains( + Core.MakeFormAndTerm(AST.MakeNot(formWithoutNot.GetF2()), terms), + ) return result } @@ -437,8 +448,16 @@ func applyBetaImpRule( ) []Core.FormAndTermsList { setStateRules(state, "BETA", "IMPLY") - result = append(result, Core.MakeSingleElementFormAndTermList(Core.MakeFormAndTerm(AST.MakeNot(formTyped.GetF1()), terms))) - result = append(result, Core.MakeSingleElementFormAndTermList(Core.MakeFormAndTerm(formTyped.GetF2(), terms))) + result = append( + result, + Core.MakeSingleElementFormAndTermList( + Core.MakeFormAndTerm(AST.MakeNot(formTyped.GetF1()), terms), + ), + ) + result = append( + result, + Core.MakeSingleElementFormAndTermList(Core.MakeFormAndTerm(formTyped.GetF2(), terms)), + ) return result } @@ -498,7 +517,11 @@ func ApplyDeltaRules(fnt Core.FormAndTerms, state *State) Core.FormAndTermsList * a formula * the new metavariables **/ -func ApplyGammaRules(fnt Core.FormAndTerms, index int, state *State) (Core.FormAndTermsList, Lib.Set[AST.Meta]) { +func ApplyGammaRules( + fnt Core.FormAndTerms, + index int, + state *State, +) (Core.FormAndTermsList, Lib.Set[AST.Meta]) { switch fnt.GetForm().(type) { case AST.Not: setStateRules(state, "GAMMA", "NOT", "EXISTS") diff --git a/src/Typing/env-and-context.go b/src/Typing/env-and-context.go index 9b7caa83..5569220e 100644 --- a/src/Typing/env-and-context.go +++ b/src/Typing/env-and-context.go @@ -40,67 +40,51 @@ package Typing import ( "sync" - "fmt" "github.com/GoelandProver/Goeland/AST" "github.com/GoelandProver/Goeland/Lib" ) -// We define an ordered type of pairs of (string, Ty) in order to use sets. -type definedType struct { - name string - ty AST.Ty +// A context is a list of types, where the nth type is the type of the nth bound variable +// (where n is the number of quantifiers to cross to find back the quantifier that binds +// the variable --- à la De Bruijn) +type Ctx struct { + Lib.List[AST.Ty] } -func (dty definedType) Less(oth any) bool { - if other, ok := oth.(definedType); ok { - return dty.name < other.name - } - return false -} - -func (dty definedType) Equals(oth any) bool { - if other, ok := oth.(definedType); ok { - return dty.name == other.name && dty.ty.Equals(other.ty) - } - return false -} - -// A context is a set of defined types -type Con struct { - defs Lib.Set[definedType] +func emptyCtx() Ctx { + return Ctx{Lib.NewList[AST.Ty]()} } -func emptyCon() Con { - return Con{Lib.EmptySet[definedType]()} +func (ctx Ctx) Copy() Ctx { + return Ctx{ctx.Clone()} } -func (con Con) Copy() Con { - return Con{con.defs.Copy()} +func reindexTy(ty AST.Ty) AST.Ty { + switch ty := ty.(type) { + case AST.TyBound: + return ty.Increase() + case AST.TyConstr: + return AST.MkTyConstr( + ty.Symbol(), + Lib.ListMap(ty.Args(), reindexTy), + ) + default: + return ty + } } -func (con Con) add(name string, ty AST.Ty) Con { - return Con{con.defs.Add(definedType{name, ty})} +func (ctx Ctx) reindex() Ctx { + return Ctx{Lib.ListMap(ctx.List, reindexTy)} } -func (con Con) contains(name string, ty AST.Ty) bool { - return con.defs.Contains(definedType{name, ty}) +func (ctx Ctx) add(ty AST.Ty) Ctx { + return Ctx{ctx.reindex().Cons(reindexTy(ty))} } -func (con Con) addTypedVars(typed_vars Lib.List[AST.TypedVar]) Con { - for _, tv := range typed_vars.GetSlice() { - con = con.add(tv.GetName(), tv.GetTy()) - } - return con -} - -func (con Con) toString() string { - to_string := func(def definedType) string { - return fmt.Sprintf("%s: %s", def.name, def.ty.ToString()) - } - return con.defs.Elements().ToString(to_string, ", ", "{}") +func (ctx Ctx) toString() string { + return Lib.ListToString(ctx.List, ", ", "{}") } -// We could use [Con] to do environments, but as we need to query by name it's faster to use a map. type Env struct { con map[string]AST.Ty mut sync.Mutex @@ -108,7 +92,7 @@ type Env struct { func (env *Env) toString() string { env.mut.Lock() - result := "Environment:" + result := "Typing environment:" for k, v := range env.con { result += "\n- " + k + ": " + v.ToString() } @@ -153,7 +137,7 @@ func QueryEnvInstance(name string, instance Lib.List[AST.Ty]) Lib.Option[AST.Ty] return Lib.OptBind( unsafeQuery(name), func(ty AST.Ty) Lib.Option[AST.Ty] { - return Lib.MkSome(AST.InstantiateTy(ty, instance)) + return AST.InstantiateTy(ty, instance) }, ) }, diff --git a/src/Typing/init.go b/src/Typing/init.go index ccbccbc0..402dc313 100644 --- a/src/Typing/init.go +++ b/src/Typing/init.go @@ -45,13 +45,11 @@ import ( ) var global_env Env -var ari_var string var debug Glob.Debugger var debug_low_level Glob.Debugger func Init() { global_env = Env{make(map[string]AST.Ty), sync.Mutex{}} - ari_var = "number" initTPTPNativeTypes() } @@ -69,8 +67,7 @@ func initTPTPNativeTypes() { AddToGlobalEnv( AST.Id_eq.GetName(), AST.MkTyPi( - Lib.MkListV("α"), - AST.MkTyFunc(AST.MkTyProd(Lib.MkListV(AST.MkTyVar("α"), AST.MkTyVar("α"))), AST.TProp()), + AST.MkTyFunc(AST.MkTyProd(Lib.MkListV(AST.MkTyBV(0), AST.MkTyBV(0))), AST.TProp()), ), ) @@ -93,12 +90,11 @@ func initTPTPNativeTypes() { // 3 - $quotient AddToGlobalEnv("$quotient", - AST.MkTyPi( - Lib.MkListV(ari_var, "rat_or_real"), + AST.MkTyPi(AST.MkTyPi( AST.MkTyFunc( - AST.MkTyProd(Lib.MkListV(AST.MkTyVar(ari_var), AST.MkTyVar(ari_var))), - AST.MkTyVar("rat_or_real")), - )) + AST.MkTyProd(Lib.MkListV(AST.MkTyBV(0), AST.MkTyBV(0))), + AST.MkTyBV(1)), + ))) // 4 - Unary input arguments recordUnaryInArgs("$uminus") @@ -124,8 +120,10 @@ func recordBinaryProp(name string) { AddToGlobalEnv( name, AST.MkTyPi( - Lib.MkListV(ari_var), - AST.MkTyFunc(AST.MkTyProd(Lib.MkListV(AST.MkTyVar(ari_var), AST.MkTyVar(ari_var))), AST.TProp()), + AST.MkTyFunc( + AST.MkTyProd(Lib.MkListV(AST.MkTyBV(0), AST.MkTyBV(0))), + AST.TProp(), + ), ), ) } @@ -134,8 +132,10 @@ func recordBinaryInArgs(name string) { AddToGlobalEnv( name, AST.MkTyPi( - Lib.MkListV(ari_var), - AST.MkTyFunc(AST.MkTyProd(Lib.MkListV(AST.MkTyVar(ari_var), AST.MkTyVar(ari_var))), AST.MkTyVar(ari_var)), + AST.MkTyFunc( + AST.MkTyProd(Lib.MkListV(AST.MkTyBV(0), AST.MkTyBV(0))), + AST.MkTyBV(0), + ), ), ) } @@ -144,8 +144,7 @@ func recordUnaryInArgs(name string) { AddToGlobalEnv( name, AST.MkTyPi( - Lib.MkListV(ari_var), - AST.MkTyFunc(AST.MkTyVar(ari_var), AST.MkTyVar(ari_var)), + AST.MkTyFunc(AST.MkTyBV(0), AST.MkTyBV(0)), ), ) } @@ -154,8 +153,7 @@ func recordUnaryProp(name string) { AddToGlobalEnv( name, AST.MkTyPi( - Lib.MkListV(ari_var), - AST.MkTyFunc(AST.MkTyVar(ari_var), AST.TProp()), + AST.MkTyFunc(AST.MkTyBV(0), AST.TProp()), ), ) } @@ -164,8 +162,7 @@ func recordConversion(name string, out AST.Ty) { AddToGlobalEnv( name, AST.MkTyPi( - Lib.MkListV(ari_var), - AST.MkTyFunc(AST.MkTyVar(ari_var), out), + AST.MkTyFunc(AST.MkTyBV(0), out), ), ) } diff --git a/src/Typing/rules.go b/src/Typing/rules.go index 1b2332ef..15b40ad3 100644 --- a/src/Typing/rules.go +++ b/src/Typing/rules.go @@ -39,6 +39,7 @@ package Typing import ( "fmt" + "github.com/GoelandProver/Goeland/AST" "github.com/GoelandProver/Goeland/Glob" "github.com/GoelandProver/Goeland/Lib" @@ -47,14 +48,18 @@ import ( var label = "typing" func TypeCheck(form AST.Form) bool { - debug(Lib.MkLazy(func() string { return fmt.Sprintf("Launching type checking on %s", form.ToString()) })) + debug( + Lib.MkLazy( + func() string { return fmt.Sprintf("Launching type checking on %s", form.ToString()) }, + ), + ) - return typecheckForm(emptyCon(), form) + return typecheckForm(emptyCtx(), form) } -func typecheckForm(con Con, form AST.Form) bool { +func typecheckForm(ctx Ctx, form AST.Form) bool { debug(Lib.MkLazy(func() string { - return fmt.Sprintf("Trying to type-check: %s |- %s : o", con.toString(), form.ToString()) + return fmt.Sprintf("Trying to type-check: %s |- %s : o", ctx.toString(), form.ToString()) })) switch f := form.(type) { @@ -62,7 +67,7 @@ func typecheckForm(con Con, form AST.Form) bool { return true case AST.Pred: return checkFunctional( - con, + ctx, f.GetID().GetName(), f.GetTyArgs(), f.GetArgs(), @@ -71,7 +76,7 @@ func typecheckForm(con Con, form AST.Form) bool { case AST.Not, AST.And, AST.Or, AST.Imp, AST.Equ: return typecheckRec( - con, + ctx, f.GetChildFormulas(), Lib.NewList[Lib.Pair[AST.Term, AST.Ty]](), Lib.NewList[AST.Ty](), @@ -79,7 +84,7 @@ func typecheckForm(con Con, form AST.Form) bool { case AST.All: return typecheckRec( - con.addTypedVars(f.GetVarList()), + ctx.add(f.Ty()), Lib.MkListV(f.GetForm()), Lib.NewList[Lib.Pair[AST.Term, AST.Ty]](), Lib.NewList[AST.Ty](), @@ -87,7 +92,7 @@ func typecheckForm(con Con, form AST.Form) bool { case AST.Ex: return typecheckRec( - con.addTypedVars(f.GetVarList()), + ctx.add(f.Ty()), Lib.MkListV(f.GetForm()), Lib.NewList[Lib.Pair[AST.Term, AST.Ty]](), Lib.NewList[AST.Ty](), @@ -101,35 +106,39 @@ func typecheckForm(con Con, form AST.Form) bool { return false } -func typecheckTerm(con Con, term AST.Term, ty AST.Ty) bool { +func typecheckTerm(ctx Ctx, term AST.Term, ty AST.Ty) bool { debug(Lib.MkLazy(func() string { - return fmt.Sprintf("Trying to type-check: %s |- %s : %s", con.toString(), term.ToString(), ty.ToString()) + return fmt.Sprintf( + "Trying to type-check: %s |- %s : %s", + ctx.toString(), + term.ToString(), + ty.ToString(), + ) })) switch t := term.(type) { case AST.Var: - if !con.contains(t.GetName(), ty) { + if t.Index() >= ctx.Len() { Glob.Fatal( label, fmt.Sprintf( - "Variable %s is either not in the context or should not have type %s\nContext: %s", - t.GetName(), - ty.ToString(), - con.toString(), + "Variable index too high for the context: expected at most %d, got %d", + ctx.Len()-1, + t.Index(), )) return false } return typecheckRec( - con, + ctx, Lib.NewList[AST.Form](), Lib.NewList[Lib.Pair[AST.Term, AST.Ty]](), - Lib.MkListV(ty), + Lib.MkListV(ctx.At(t.Index())), ) case AST.Fun: return checkFunctional( - con, + ctx, t.GetID().GetName(), t.GetTyArgs(), t.GetArgs(), @@ -139,27 +148,28 @@ func typecheckTerm(con Con, term AST.Term, ty AST.Ty) bool { Glob.Anomaly( label, - fmt.Sprintf("Only bound variables and functions should be typechecked, but found %s", term.ToString()), + fmt.Sprintf( + "Only bound variables and functions should be typechecked, but found %s", + term.ToString(), + ), ) return false } -func typecheckType(con Con, ty AST.Ty) bool { +func typecheckType(ctx Ctx, ty AST.Ty) bool { debug(Lib.MkLazy(func() string { return fmt.Sprintf("Trying to type-check: %s |- %s : %s", - con.toString(), ty.ToString(), AST.TType().ToString()) + ctx.toString(), ty.ToString(), AST.TType().ToString()) })) - switch nty := ty.(type) { case AST.TyBound: - if !con.contains(nty.GetName(), AST.TType()) { - Glob.PrintInfo("Context", con.toString()) + if nty.Index() >= ctx.Len() || !ctx.At(nty.Index()).Equals(AST.TType()) { Glob.Fatal( label, fmt.Sprintf( - "Variable %s is either not in the context or is not a type variable\nContext: %s", - nty.ToString(), - con.toString(), + "Variable %d is either not in the context or is not a type variable\nContext: %s", + nty.Index(), + ctx.toString(), )) return false } @@ -190,7 +200,7 @@ func typecheckType(con Con, ty AST.Ty) bool { } return typecheckRec( - con, + ctx, Lib.NewList[AST.Form](), Lib.NewList[Lib.Pair[AST.Term, AST.Ty]](), nty.Args(), @@ -212,19 +222,22 @@ func typecheckType(con Con, ty AST.Ty) bool { } func checkFunctional( - con Con, + ctx Ctx, name string, tys Lib.List[AST.Ty], args Lib.List[AST.Term], debug_str Lib.Lazy[string], ) bool { + debug(Lib.MkLazy(func() string { + return "Cheking a functional type (predicate or function)..." + })) + oty := QueryEnvInstance(name, tys) switch ty := oty.(type) { case Lib.Some[AST.Ty]: debug_low_level(Lib.MkLazy(func() string { return fmt.Sprintf("%s has a functional scheme instantiated to %s", debug_str.Run(), ty.Val.ToString()) })) - instantiated_ty := AST.GetArgsTy(ty.Val) debug_low_level(Lib.MkLazy(func() string { return fmt.Sprintf("Arguments will be typechecked against: [%s]", @@ -239,7 +252,7 @@ func checkFunctional( ) tys.Append(AST.GetOutTy(ty.Val)) - return typecheckRec(con, Lib.NewList[AST.Form](), terms_checker, tys) + return typecheckRec(ctx, Lib.NewList[AST.Form](), terms_checker, tys) case Lib.None[AST.Ty]: Glob.Fatal( @@ -247,11 +260,13 @@ func checkFunctional( fmt.Sprintf("Type of %s not found in the global environment", debug_str.Run()), ) } + + Glob.Anomaly(label, "Reached an impossible case") return false } func typecheckRec( - con Con, + ctx Ctx, forms Lib.List[AST.Form], typed_terms Lib.List[Lib.Pair[AST.Term, AST.Ty]], tys Lib.List[AST.Ty], @@ -267,21 +282,21 @@ func typecheckRec( for _, form := range forms.GetSlice() { loop_form := form calls = append(calls, func(outchan chan bool) { - outchan <- typecheckForm(con, loop_form) + outchan <- typecheckForm(ctx, loop_form) }) } for _, typed_term := range typed_terms.GetSlice() { loop_term := typed_term calls = append(calls, func(outchan chan bool) { - outchan <- typecheckTerm(con, loop_term.Fst, loop_term.Snd) + outchan <- typecheckTerm(ctx, loop_term.Fst, loop_term.Snd) }) } for _, ty := range tys.GetSlice() { loop_ty := ty calls = append(calls, func(outchan chan bool) { - outchan <- typecheckType(con, loop_ty) + outchan <- typecheckType(ctx, loop_ty) }) } diff --git a/src/Unif/matching_substitutions.go b/src/Unif/matching_substitutions.go index 7b2bfadf..db54fab9 100644 --- a/src/Unif/matching_substitutions.go +++ b/src/Unif/matching_substitutions.go @@ -284,7 +284,7 @@ func (s MixMatchSubstitutions) toMatching() MatchingSubstitutions { } Glob.Anomaly("unification", "reached an unreachable case") - return MakeMatchingSubstitutions(AST.MakerTop(), MakeEmptySubstitution()) + return MakeMatchingSubstitutions(AST.MakeTop(), MakeEmptySubstitution()) } func (s MixMatchSubstitutions) toMixed() MixedSubstitutions { @@ -300,7 +300,7 @@ func (s MixedTermSubstitutions) Term() AST.Term { return s.term } func (s MixedTermSubstitutions) ToString() string { substs_list := Lib.MkListV(s.substs...) - return s.term.ToString() + " {" + Lib.ListToString(substs_list, Lib.WithEmpty("")) + "}" + return s.term.ToString() + " {" + Lib.ListToString(substs_list, ", ", "") + "}" } func (s MixMatchSubstitutions) toMixedTerm() MixedTermSubstitutions { diff --git a/src/Unif/parsing.go b/src/Unif/parsing.go index 5e8d080d..79854ec4 100644 --- a/src/Unif/parsing.go +++ b/src/Unif/parsing.go @@ -39,7 +39,7 @@ import ( ) func transformPred(p AST.Pred) AST.Term { - return transformTerm(AST.MakerFun(p.GetID(), p.GetTyArgs(), p.GetArgs())) + return transformTerm(AST.MakeFun(p.GetID(), p.GetTyArgs(), p.GetArgs())) } func transformTerm(t AST.Term) AST.Term { @@ -49,7 +49,7 @@ func transformTerm(t AST.Term) AST.Term { case AST.Fun: args := Lib.ListMap(term.GetTyArgs(), AST.TyToTerm) args.Append(Lib.ListMap(term.GetArgs(), transformTerm).GetSlice()...) - return AST.MakerFun( + return AST.MakeFun( term.GetID(), Lib.NewList[AST.Ty](), args, From 591af8271fa73f9b05d56d6f45eace7ec84ac0d8 Mon Sep 17 00:00:00 2001 From: Johann Rosain Date: Thu, 26 Mar 2026 19:44:43 +0100 Subject: [PATCH 30/30] upd: test-suite output update with nameless variables --- devtools/test-suite/proofs/example_sctptp.out | 30 ++++++++--------- devtools/test-suite/proofs/example_tptp.out | 30 ++++++++--------- .../test-suite/proofs/tf1_basic_thm-2.out | 32 +++++++++---------- devtools/test-suite/proofs/tf1_basic_thm.out | 18 +++++------ 4 files changed, 55 insertions(+), 55 deletions(-) diff --git a/devtools/test-suite/proofs/example_sctptp.out b/devtools/test-suite/proofs/example_sctptp.out index 36dbe26e..97b80280 100644 --- a/devtools/test-suite/proofs/example_sctptp.out +++ b/devtools/test-suite/proofs/example_sctptp.out @@ -1,29 +1,29 @@ -fof(c_example_sctptp_p, conjecture, (! [X]: p(X)) <=> ~(? [Y]: ~p(Y))). +fof(c_example_sctptp_p, conjecture, (! [X0]: p(X0)) <=> ~(? [X0]: ~p(X0))). -fof(f8, plain, [~((! [X]: p(X)) <=> ~(? [Y]: ~p(Y))), ~(! [X]: p(X)), ~(? [Y]: ~p(Y)), ~(~(? [Y]: ~p(Y)) => (! [X]: p(X))), ~p(Sko_0), ~~p(Sko_0), p(Sko_0)] --> [], inference(leftHyp, [status(thm), 6], [])). +fof(f8, plain, [~((! [X0]: p(X0)) <=> ~(? [X0]: ~p(X0))), ~(! [X0]: p(X0)), ~(? [X0]: ~p(X0)), ~(~(? [X0]: ~p(X0)) => (! [X0]: p(X0))), ~p(Sko_0), ~~p(Sko_0), p(Sko_0)] --> [], inference(leftHyp, [status(thm), 6], [])). -fof(f7, plain, [~((! [X]: p(X)) <=> ~(? [Y]: ~p(Y))), ~(! [X]: p(X)), ~(? [Y]: ~p(Y)), ~(~(? [Y]: ~p(Y)) => (! [X]: p(X))), ~p(Sko_0), ~~p(Sko_0)] --> [], inference(leftNotNot, [status(thm), 5], [f8])). +fof(f7, plain, [~((! [X0]: p(X0)) <=> ~(? [X0]: ~p(X0))), ~(! [X0]: p(X0)), ~(? [X0]: ~p(X0)), ~(~(? [X0]: ~p(X0)) => (! [X0]: p(X0))), ~p(Sko_0), ~~p(Sko_0)] --> [], inference(leftNotNot, [status(thm), 5], [f8])). -fof(f6, plain, [~((! [X]: p(X)) <=> ~(? [Y]: ~p(Y))), ~(! [X]: p(X)), ~(? [Y]: ~p(Y)), ~(~(? [Y]: ~p(Y)) => (! [X]: p(X))), ~p(Sko_0)] --> [], inference(leftNotEx, [status(thm), 2, $fot(Sko_0)], [f7])). +fof(f6, plain, [~((! [X0]: p(X0)) <=> ~(? [X0]: ~p(X0))), ~(! [X0]: p(X0)), ~(? [X0]: ~p(X0)), ~(~(? [X0]: ~p(X0)) => (! [X0]: p(X0))), ~p(Sko_0)] --> [], inference(leftNotEx, [status(thm), 2, $fot(Sko_0)], [f7])). -fof(f4, plain, [~((! [X]: p(X)) <=> ~(? [Y]: ~p(Y))), ~(! [X]: p(X)), ~(? [Y]: ~p(Y)), ~(~(? [Y]: ~p(Y)) => (! [X]: p(X)))] --> [], inference(leftNotAll, [status(thm), 1, 'Sko_0'], [f6])). +fof(f4, plain, [~((! [X0]: p(X0)) <=> ~(? [X0]: ~p(X0))), ~(! [X0]: p(X0)), ~(? [X0]: ~p(X0)), ~(~(? [X0]: ~p(X0)) => (! [X0]: p(X0)))] --> [], inference(leftNotAll, [status(thm), 1, 'Sko_0'], [f6])). -fof(f11, plain, [~((! [X]: p(X)) <=> ~(? [Y]: ~p(Y))), ! [X]: p(X), ~~(? [Y]: ~p(Y)), ~((! [X]: p(X)) => ~(? [Y]: ~p(Y))), ? [Y]: ~p(Y), ~p(Sko_1), p(Sko_1)] --> [], inference(leftHyp, [status(thm), 6], [])). +fof(f11, plain, [~((! [X0]: p(X0)) <=> ~(? [X0]: ~p(X0))), ! [X0]: p(X0), ~~(? [X0]: ~p(X0)), ~((! [X0]: p(X0)) => ~(? [X0]: ~p(X0))), ? [X0]: ~p(X0), ~p(Sko_1), p(Sko_1)] --> [], inference(leftHyp, [status(thm), 6], [])). -fof(f10, plain, [~((! [X]: p(X)) <=> ~(? [Y]: ~p(Y))), ! [X]: p(X), ~~(? [Y]: ~p(Y)), ~((! [X]: p(X)) => ~(? [Y]: ~p(Y))), ? [Y]: ~p(Y), ~p(Sko_1)] --> [], inference(leftForall, [status(thm), 1, $fot(Sko_1)], [f11])). +fof(f10, plain, [~((! [X0]: p(X0)) <=> ~(? [X0]: ~p(X0))), ! [X0]: p(X0), ~~(? [X0]: ~p(X0)), ~((! [X0]: p(X0)) => ~(? [X0]: ~p(X0))), ? [X0]: ~p(X0), ~p(Sko_1)] --> [], inference(leftForall, [status(thm), 1, $fot(Sko_1)], [f11])). -fof(f9, plain, [~((! [X]: p(X)) <=> ~(? [Y]: ~p(Y))), ! [X]: p(X), ~~(? [Y]: ~p(Y)), ~((! [X]: p(X)) => ~(? [Y]: ~p(Y))), ? [Y]: ~p(Y)] --> [], inference(leftExists, [status(thm), 4, 'Sko_1'], [f10])). +fof(f9, plain, [~((! [X0]: p(X0)) <=> ~(? [X0]: ~p(X0))), ! [X0]: p(X0), ~~(? [X0]: ~p(X0)), ~((! [X0]: p(X0)) => ~(? [X0]: ~p(X0))), ? [X0]: ~p(X0)] --> [], inference(leftExists, [status(thm), 4, 'Sko_1'], [f10])). -fof(f5, plain, [~((! [X]: p(X)) <=> ~(? [Y]: ~p(Y))), ! [X]: p(X), ~~(? [Y]: ~p(Y)), ~((! [X]: p(X)) => ~(? [Y]: ~p(Y)))] --> [], inference(leftNotNot, [status(thm), 2], [f9])). +fof(f5, plain, [~((! [X0]: p(X0)) <=> ~(? [X0]: ~p(X0))), ! [X0]: p(X0), ~~(? [X0]: ~p(X0)), ~((! [X0]: p(X0)) => ~(? [X0]: ~p(X0)))] --> [], inference(leftNotNot, [status(thm), 2], [f9])). -fof(f3ext2, plain, [~((! [X]: p(X)) <=> ~(? [Y]: ~p(Y))), ~(~(? [Y]: ~p(Y)) => (! [X]: p(X)))] --> [], inference(leftNotImplies, [status(thm), 1], [f4])). +fof(f3ext2, plain, [~((! [X0]: p(X0)) <=> ~(? [X0]: ~p(X0))), ~(~(? [X0]: ~p(X0)) => (! [X0]: p(X0)))] --> [], inference(leftNotImplies, [status(thm), 1], [f4])). -fof(f3ext1, plain, [~((! [X]: p(X)) <=> ~(? [Y]: ~p(Y))), ~((! [X]: p(X)) => ~(? [Y]: ~p(Y)))] --> [], inference(leftNotImplies, [status(thm), 1], [f5])). +fof(f3ext1, plain, [~((! [X0]: p(X0)) <=> ~(? [X0]: ~p(X0))), ~((! [X0]: p(X0)) => ~(? [X0]: ~p(X0)))] --> [], inference(leftNotImplies, [status(thm), 1], [f5])). -fof(f3, plain, [~((! [X]: p(X)) <=> ~(? [Y]: ~p(Y)))] --> [], inference(leftNotIff, [status(thm), 0], [f3ext1, f3ext2])). +fof(f3, plain, [~((! [X0]: p(X0)) <=> ~(? [X0]: ~p(X0)))] --> [], inference(leftNotIff, [status(thm), 0], [f3ext1, f3ext2])). -fof(f2, plain, [(! [X]: p(X)) <=> ~(? [Y]: ~p(Y))] --> [(! [X]: p(X)) <=> ~(? [Y]: ~p(Y))], inference(hyp, [status(thm), 0], [])). +fof(f2, plain, [(! [X0]: p(X0)) <=> ~(? [X0]: ~p(X0))] --> [(! [X0]: p(X0)) <=> ~(? [X0]: ~p(X0))], inference(hyp, [status(thm), 0], [])). -fof(f1, plain, [] --> [(! [X]: p(X)) <=> ~(? [Y]: ~p(Y)), ~((! [X]: p(X)) <=> ~(? [Y]: ~p(Y)))], inference(rightNot, [status(thm), 1], [f2])). +fof(f1, plain, [] --> [(! [X0]: p(X0)) <=> ~(? [X0]: ~p(X0)), ~((! [X0]: p(X0)) <=> ~(? [X0]: ~p(X0)))], inference(rightNot, [status(thm), 1], [f2])). -fof(f0, plain, [] --> [(! [X]: p(X)) <=> ~(? [Y]: ~p(Y))], inference(cut, [status(thm), 1], [f1, f3])). +fof(f0, plain, [] --> [(! [X0]: p(X0)) <=> ~(? [X0]: ~p(X0))], inference(cut, [status(thm), 1], [f1, f3])). diff --git a/devtools/test-suite/proofs/example_tptp.out b/devtools/test-suite/proofs/example_tptp.out index a5a9dfbf..e3fc8517 100644 --- a/devtools/test-suite/proofs/example_tptp.out +++ b/devtools/test-suite/proofs/example_tptp.out @@ -1,29 +1,29 @@ -fof(c_example_tptp_p, conjecture, (! [X]: p(X)) <=> ~(? [Y]: ~p(Y))). +fof(c_example_tptp_p, conjecture, (! [X0]: p(X0)) <=> ~(? [X0]: ~p(X0))). -fof(f8, plain, [~((! [X]: p(X)) <=> ~(? [Y]: ~p(Y))), ~(! [X]: p(X)), ~(? [Y]: ~p(Y)), ~(~(? [Y]: ~p(Y)) => (! [X]: p(X))), ~p(sko_0), ~~p(sko_0), p(sko_0)] --> [], inference(leftHyp, [status(thm), 6], [])). +fof(f8, plain, [~((! [X0]: p(X0)) <=> ~(? [X0]: ~p(X0))), ~(! [X0]: p(X0)), ~(? [X0]: ~p(X0)), ~(~(? [X0]: ~p(X0)) => (! [X0]: p(X0))), ~p(sko_0), ~~p(sko_0), p(sko_0)] --> [], inference(leftHyp, [status(thm), 6], [])). -fof(f7, plain, [~((! [X]: p(X)) <=> ~(? [Y]: ~p(Y))), ~(! [X]: p(X)), ~(? [Y]: ~p(Y)), ~(~(? [Y]: ~p(Y)) => (! [X]: p(X))), ~p(sko_0), ~~p(sko_0)] --> [], inference(leftNotNot, [status(thm), 5], [f8])). +fof(f7, plain, [~((! [X0]: p(X0)) <=> ~(? [X0]: ~p(X0))), ~(! [X0]: p(X0)), ~(? [X0]: ~p(X0)), ~(~(? [X0]: ~p(X0)) => (! [X0]: p(X0))), ~p(sko_0), ~~p(sko_0)] --> [], inference(leftNotNot, [status(thm), 5], [f8])). -fof(f6, plain, [~((! [X]: p(X)) <=> ~(? [Y]: ~p(Y))), ~(! [X]: p(X)), ~(? [Y]: ~p(Y)), ~(~(? [Y]: ~p(Y)) => (! [X]: p(X))), ~p(sko_0)] --> [], inference(leftNotEx, [status(thm), 2, $fot(sko_0)], [f7])). +fof(f6, plain, [~((! [X0]: p(X0)) <=> ~(? [X0]: ~p(X0))), ~(! [X0]: p(X0)), ~(? [X0]: ~p(X0)), ~(~(? [X0]: ~p(X0)) => (! [X0]: p(X0))), ~p(sko_0)] --> [], inference(leftNotEx, [status(thm), 2, $fot(sko_0)], [f7])). -fof(f4, plain, [~((! [X]: p(X)) <=> ~(? [Y]: ~p(Y))), ~(! [X]: p(X)), ~(? [Y]: ~p(Y)), ~(~(? [Y]: ~p(Y)) => (! [X]: p(X)))] --> [], inference(leftNotAll, [status(thm), 1, 'sko_0'], [f6])). +fof(f4, plain, [~((! [X0]: p(X0)) <=> ~(? [X0]: ~p(X0))), ~(! [X0]: p(X0)), ~(? [X0]: ~p(X0)), ~(~(? [X0]: ~p(X0)) => (! [X0]: p(X0)))] --> [], inference(leftNotAll, [status(thm), 1, 'sko_0'], [f6])). -fof(f11, plain, [~((! [X]: p(X)) <=> ~(? [Y]: ~p(Y))), ! [X]: p(X), ~~(? [Y]: ~p(Y)), ~((! [X]: p(X)) => ~(? [Y]: ~p(Y))), ? [Y]: ~p(Y), ~p(sko_1), p(sko_1)] --> [], inference(leftHyp, [status(thm), 6], [])). +fof(f11, plain, [~((! [X0]: p(X0)) <=> ~(? [X0]: ~p(X0))), ! [X0]: p(X0), ~~(? [X0]: ~p(X0)), ~((! [X0]: p(X0)) => ~(? [X0]: ~p(X0))), ? [X0]: ~p(X0), ~p(sko_1), p(sko_1)] --> [], inference(leftHyp, [status(thm), 6], [])). -fof(f10, plain, [~((! [X]: p(X)) <=> ~(? [Y]: ~p(Y))), ! [X]: p(X), ~~(? [Y]: ~p(Y)), ~((! [X]: p(X)) => ~(? [Y]: ~p(Y))), ? [Y]: ~p(Y), ~p(sko_1)] --> [], inference(leftForall, [status(thm), 1, $fot(sko_1)], [f11])). +fof(f10, plain, [~((! [X0]: p(X0)) <=> ~(? [X0]: ~p(X0))), ! [X0]: p(X0), ~~(? [X0]: ~p(X0)), ~((! [X0]: p(X0)) => ~(? [X0]: ~p(X0))), ? [X0]: ~p(X0), ~p(sko_1)] --> [], inference(leftForall, [status(thm), 1, $fot(sko_1)], [f11])). -fof(f9, plain, [~((! [X]: p(X)) <=> ~(? [Y]: ~p(Y))), ! [X]: p(X), ~~(? [Y]: ~p(Y)), ~((! [X]: p(X)) => ~(? [Y]: ~p(Y))), ? [Y]: ~p(Y)] --> [], inference(leftExists, [status(thm), 4, 'sko_1'], [f10])). +fof(f9, plain, [~((! [X0]: p(X0)) <=> ~(? [X0]: ~p(X0))), ! [X0]: p(X0), ~~(? [X0]: ~p(X0)), ~((! [X0]: p(X0)) => ~(? [X0]: ~p(X0))), ? [X0]: ~p(X0)] --> [], inference(leftExists, [status(thm), 4, 'sko_1'], [f10])). -fof(f5, plain, [~((! [X]: p(X)) <=> ~(? [Y]: ~p(Y))), ! [X]: p(X), ~~(? [Y]: ~p(Y)), ~((! [X]: p(X)) => ~(? [Y]: ~p(Y)))] --> [], inference(leftNotNot, [status(thm), 2], [f9])). +fof(f5, plain, [~((! [X0]: p(X0)) <=> ~(? [X0]: ~p(X0))), ! [X0]: p(X0), ~~(? [X0]: ~p(X0)), ~((! [X0]: p(X0)) => ~(? [X0]: ~p(X0)))] --> [], inference(leftNotNot, [status(thm), 2], [f9])). -fof(f3ext2, plain, [~((! [X]: p(X)) <=> ~(? [Y]: ~p(Y))), ~(~(? [Y]: ~p(Y)) => (! [X]: p(X)))] --> [], inference(leftNotImplies, [status(thm), 1], [f4])). +fof(f3ext2, plain, [~((! [X0]: p(X0)) <=> ~(? [X0]: ~p(X0))), ~(~(? [X0]: ~p(X0)) => (! [X0]: p(X0)))] --> [], inference(leftNotImplies, [status(thm), 1], [f4])). -fof(f3ext1, plain, [~((! [X]: p(X)) <=> ~(? [Y]: ~p(Y))), ~((! [X]: p(X)) => ~(? [Y]: ~p(Y)))] --> [], inference(leftNotImplies, [status(thm), 1], [f5])). +fof(f3ext1, plain, [~((! [X0]: p(X0)) <=> ~(? [X0]: ~p(X0))), ~((! [X0]: p(X0)) => ~(? [X0]: ~p(X0)))] --> [], inference(leftNotImplies, [status(thm), 1], [f5])). -fof(f3, plain, [~((! [X]: p(X)) <=> ~(? [Y]: ~p(Y)))] --> [], inference(leftNotIff, [status(thm), 0], [f3ext1, f3ext2])). +fof(f3, plain, [~((! [X0]: p(X0)) <=> ~(? [X0]: ~p(X0)))] --> [], inference(leftNotIff, [status(thm), 0], [f3ext1, f3ext2])). -fof(f2, plain, [(! [X]: p(X)) <=> ~(? [Y]: ~p(Y))] --> [(! [X]: p(X)) <=> ~(? [Y]: ~p(Y))], inference(hyp, [status(thm), 0], [])). +fof(f2, plain, [(! [X0]: p(X0)) <=> ~(? [X0]: ~p(X0))] --> [(! [X0]: p(X0)) <=> ~(? [X0]: ~p(X0))], inference(hyp, [status(thm), 0], [])). -fof(f1, plain, [] --> [(! [X]: p(X)) <=> ~(? [Y]: ~p(Y)), ~((! [X]: p(X)) <=> ~(? [Y]: ~p(Y)))], inference(rightNot, [status(thm), 1], [f2])). +fof(f1, plain, [] --> [(! [X0]: p(X0)) <=> ~(? [X0]: ~p(X0)), ~((! [X0]: p(X0)) <=> ~(? [X0]: ~p(X0)))], inference(rightNot, [status(thm), 1], [f2])). -fof(f0, plain, [] --> [(! [X]: p(X)) <=> ~(? [Y]: ~p(Y))], inference(cut, [status(thm), 1], [f1, f3])). +fof(f0, plain, [] --> [(! [X0]: p(X0)) <=> ~(? [X0]: ~p(X0))], inference(cut, [status(thm), 1], [f1, f3])). diff --git a/devtools/test-suite/proofs/tf1_basic_thm-2.out b/devtools/test-suite/proofs/tf1_basic_thm-2.out index 16a0fdbb..dcb113b1 100644 --- a/devtools/test-suite/proofs/tf1_basic_thm-2.out +++ b/devtools/test-suite/proofs/tf1_basic_thm-2.out @@ -1,28 +1,28 @@ -[0] ALPHA_AND : (! [A]: head(A ; nil(A ; )) = none(A ; )) & (! [A, X, XS]: head(A ; cons(A ; X, XS)) = some(A ; X)) & ~(! [A, X, Y, Z]: head(A ; cons(A ; X, cons(A ; Y, cons(A ; Z, nil(A ; ))))) = some(A ; X)) - -> [1] ! [A]: head(A ; nil(A ; )) = none(A ; ), ! [A, X, XS]: head(A ; cons(A ; X, XS)) = some(A ; X), ~(! [A, X, Y, Z]: head(A ; cons(A ; X, cons(A ; Y, cons(A ; Z, nil(A ; ))))) = some(A ; X)) +[0] ALPHA_AND : (! [T0]: head(T0 ; nil(T0 ; )) = none(T0 ; )) & (! [T0, X1, X2]: head(T0 ; cons(T0 ; X1, X2)) = some(T0 ; X1)) & ~(! [T0, X1, X2, X3]: head(T0 ; cons(T0 ; X1, cons(T0 ; X2, cons(T0 ; X3, nil(T0 ; ))))) = some(T0 ; X1)) + -> [1] ! [T0]: head(T0 ; nil(T0 ; )) = none(T0 ; ), ! [T0, X1, X2]: head(T0 ; cons(T0 ; X1, X2)) = some(T0 ; X1), ~(! [T0, X1, X2, X3]: head(T0 ; cons(T0 ; X1, cons(T0 ; X2, cons(T0 ; X3, nil(T0 ; ))))) = some(T0 ; X1)) -[1] DELTA_NOT_FORALL : ~(! [A, X, Y, Z]: head(A ; cons(A ; X, cons(A ; Y, cons(A ; Z, nil(A ; ))))) = some(A ; X)) - -> [2] ~(! [X, Y, Z]: head(skoTy@0 ; cons(skoTy@0 ; X, cons(skoTy@0 ; Y, cons(skoTy@0 ; Z, nil(skoTy@0 ; ))))) = some(skoTy@0 ; X)) +[1] DELTA_NOT_FORALL : ~(! [T0, X1, X2, X3]: head(T0 ; cons(T0 ; X1, cons(T0 ; X2, cons(T0 ; X3, nil(T0 ; ))))) = some(T0 ; X1)) + -> [2] ~(! [X0, X1, X2]: head(skoTy@0 ; cons(skoTy@0 ; X0, cons(skoTy@0 ; X1, cons(skoTy@0 ; X2, nil(skoTy@0 ; ))))) = some(skoTy@0 ; X0)) -[2] DELTA_NOT_FORALL : ~(! [X, Y, Z]: head(skoTy@0 ; cons(skoTy@0 ; X, cons(skoTy@0 ; Y, cons(skoTy@0 ; Z, nil(skoTy@0 ; ))))) = some(skoTy@0 ; X)) - -> [3] ~(! [Y, Z]: head(skoTy@0 ; cons(skoTy@0 ; skolem@0, cons(skoTy@0 ; Y, cons(skoTy@0 ; Z, nil(skoTy@0 ; ))))) = some(skoTy@0 ; skolem@0)) +[2] DELTA_NOT_FORALL : ~(! [X0, X1, X2]: head(skoTy@0 ; cons(skoTy@0 ; X0, cons(skoTy@0 ; X1, cons(skoTy@0 ; X2, nil(skoTy@0 ; ))))) = some(skoTy@0 ; X0)) + -> [3] ~(! [X0, X1]: head(skoTy@0 ; cons(skoTy@0 ; skolem@0, cons(skoTy@0 ; X0, cons(skoTy@0 ; X1, nil(skoTy@0 ; ))))) = some(skoTy@0 ; skolem@0)) -[3] DELTA_NOT_FORALL : ~(! [Y, Z]: head(skoTy@0 ; cons(skoTy@0 ; skolem@0, cons(skoTy@0 ; Y, cons(skoTy@0 ; Z, nil(skoTy@0 ; ))))) = some(skoTy@0 ; skolem@0)) - -> [4] ~(! [Z]: head(skoTy@0 ; cons(skoTy@0 ; skolem@0, cons(skoTy@0 ; skolem@1, cons(skoTy@0 ; Z, nil(skoTy@0 ; ))))) = some(skoTy@0 ; skolem@0)) +[3] DELTA_NOT_FORALL : ~(! [X0, X1]: head(skoTy@0 ; cons(skoTy@0 ; skolem@0, cons(skoTy@0 ; X0, cons(skoTy@0 ; X1, nil(skoTy@0 ; ))))) = some(skoTy@0 ; skolem@0)) + -> [4] ~(! [X0]: head(skoTy@0 ; cons(skoTy@0 ; skolem@0, cons(skoTy@0 ; skolem@1, cons(skoTy@0 ; X0, nil(skoTy@0 ; ))))) = some(skoTy@0 ; skolem@0)) -[4] DELTA_NOT_FORALL : ~(! [Z]: head(skoTy@0 ; cons(skoTy@0 ; skolem@0, cons(skoTy@0 ; skolem@1, cons(skoTy@0 ; Z, nil(skoTy@0 ; ))))) = some(skoTy@0 ; skolem@0)) +[4] DELTA_NOT_FORALL : ~(! [X0]: head(skoTy@0 ; cons(skoTy@0 ; skolem@0, cons(skoTy@0 ; skolem@1, cons(skoTy@0 ; X0, nil(skoTy@0 ; ))))) = some(skoTy@0 ; skolem@0)) -> [5] ~(head(skoTy@0 ; cons(skoTy@0 ; skolem@0, cons(skoTy@0 ; skolem@1, cons(skoTy@0 ; skolem@2, nil(skoTy@0 ; ))))) = some(skoTy@0 ; skolem@0)) -[5] GAMMA_FORALL : ! [A]: head(A ; nil(A ; )) = none(A ; ) - -> [6] head(A ; nil(A ; )) = none(A ; ) +[5] GAMMA_FORALL : ! [T0]: head(T0 ; nil(T0 ; )) = none(T0 ; ) + -> [6] head(MT3 ; nil(MT3 ; )) = none(MT3 ; ) -[6] GAMMA_FORALL : ! [A, X, XS]: head(A ; cons(A ; X, XS)) = some(A ; X) - -> [7] ! [X, XS]: head(skoTy@0 ; cons(skoTy@0 ; X, XS)) = some(skoTy@0 ; X) +[6] GAMMA_FORALL : ! [T0, X1, X2]: head(T0 ; cons(T0 ; X1, X2)) = some(T0 ; X1) + -> [7] ! [X0, X1]: head(skoTy@0 ; cons(skoTy@0 ; X0, X1)) = some(skoTy@0 ; X0) -[7] GAMMA_FORALL : ! [X, XS]: head(skoTy@0 ; cons(skoTy@0 ; X, XS)) = some(skoTy@0 ; X) - -> [8] ! [XS]: head(skoTy@0 ; cons(skoTy@0 ; skolem@0, XS)) = some(skoTy@0 ; skolem@0) +[7] GAMMA_FORALL : ! [X0, X1]: head(skoTy@0 ; cons(skoTy@0 ; X0, X1)) = some(skoTy@0 ; X0) + -> [8] ! [X0]: head(skoTy@0 ; cons(skoTy@0 ; skolem@0, X0)) = some(skoTy@0 ; skolem@0) -[8] GAMMA_FORALL : ! [XS]: head(skoTy@0 ; cons(skoTy@0 ; skolem@0, XS)) = some(skoTy@0 ; skolem@0) +[8] GAMMA_FORALL : ! [X0]: head(skoTy@0 ; cons(skoTy@0 ; skolem@0, X0)) = some(skoTy@0 ; skolem@0) -> [9] head(skoTy@0 ; cons(skoTy@0 ; skolem@0, cons(skoTy@0 ; skolem@1, cons(skoTy@0 ; skolem@2, nil(skoTy@0 ; ))))) = some(skoTy@0 ; skolem@0) [9] CLOSURE : head(skoTy@0 ; cons(skoTy@0 ; skolem@0, cons(skoTy@0 ; skolem@1, cons(skoTy@0 ; skolem@2, nil(skoTy@0 ; ))))) = some(skoTy@0 ; skolem@0) diff --git a/devtools/test-suite/proofs/tf1_basic_thm.out b/devtools/test-suite/proofs/tf1_basic_thm.out index 9a0b34af..c751eb79 100644 --- a/devtools/test-suite/proofs/tf1_basic_thm.out +++ b/devtools/test-suite/proofs/tf1_basic_thm.out @@ -1,16 +1,16 @@ -[0] ALPHA_AND : (! [A]: head(A ; nil(A ; )) = none(A ; )) & (! [A, X, XS]: head(A ; cons(A ; X, XS)) = some(A ; X)) & ~(head($int ; cons($int ; 1, cons($int ; 2, cons($int ; 3, nil($int ; ))))) = some($int ; 1)) - -> [1] ! [A]: head(A ; nil(A ; )) = none(A ; ), ! [A, X, XS]: head(A ; cons(A ; X, XS)) = some(A ; X), ~(head($int ; cons($int ; 1, cons($int ; 2, cons($int ; 3, nil($int ; ))))) = some($int ; 1)) +[0] ALPHA_AND : (! [T0]: head(T0 ; nil(T0 ; )) = none(T0 ; )) & (! [T0, X1, X2]: head(T0 ; cons(T0 ; X1, X2)) = some(T0 ; X1)) & ~(head($int ; cons($int ; 1, cons($int ; 2, cons($int ; 3, nil($int ; ))))) = some($int ; 1)) + -> [1] ! [T0]: head(T0 ; nil(T0 ; )) = none(T0 ; ), ! [T0, X1, X2]: head(T0 ; cons(T0 ; X1, X2)) = some(T0 ; X1), ~(head($int ; cons($int ; 1, cons($int ; 2, cons($int ; 3, nil($int ; ))))) = some($int ; 1)) -[1] GAMMA_FORALL : ! [A]: head(A ; nil(A ; )) = none(A ; ) - -> [2] head(A ; nil(A ; )) = none(A ; ) +[1] GAMMA_FORALL : ! [T0]: head(T0 ; nil(T0 ; )) = none(T0 ; ) + -> [2] head(MT3 ; nil(MT3 ; )) = none(MT3 ; ) -[2] GAMMA_FORALL : ! [A, X, XS]: head(A ; cons(A ; X, XS)) = some(A ; X) - -> [3] ! [X, XS]: head($int ; cons($int ; X, XS)) = some($int ; X) +[2] GAMMA_FORALL : ! [T0, X1, X2]: head(T0 ; cons(T0 ; X1, X2)) = some(T0 ; X1) + -> [3] ! [X0, X1]: head($int ; cons($int ; X0, X1)) = some($int ; X0) -[3] GAMMA_FORALL : ! [X, XS]: head($int ; cons($int ; X, XS)) = some($int ; X) - -> [4] ! [XS]: head($int ; cons($int ; 1, XS)) = some($int ; 1) +[3] GAMMA_FORALL : ! [X0, X1]: head($int ; cons($int ; X0, X1)) = some($int ; X0) + -> [4] ! [X0]: head($int ; cons($int ; 1, X0)) = some($int ; 1) -[4] GAMMA_FORALL : ! [XS]: head($int ; cons($int ; 1, XS)) = some($int ; 1) +[4] GAMMA_FORALL : ! [X0]: head($int ; cons($int ; 1, X0)) = some($int ; 1) -> [5] head($int ; cons($int ; 1, cons($int ; 2, cons($int ; 3, nil($int ; ))))) = some($int ; 1) [5] CLOSURE : head($int ; cons($int ; 1, cons($int ; 2, cons($int ; 3, nil($int ; ))))) = some($int ; 1)