Conversation
Add test for polymorphic function in DDM Add tests for verifier errors (polymorphism, no decreaes, etc) Remove reundant scope with scopeSelf
Add support for more complex triggers in s-expr Remove uses of Visibility
MikaelMayer
left a comment
There was a problem hiding this comment.
This PR adds comprehensive support for recursive functions in Strata Core with a well-designed implementation. The changes are structured logically across the DDM layer (adding @[scopeSelf] metadata), the Lambda dialect (axiom generation), and the Core language (grammar, translation, SMT encoding). The test coverage is excellent, including positive tests, error cases, and a complex example (BinaryTreeSize). The documentation clearly explains the new @[scopeSelf] attribute and its purpose.
The implementation correctly handles the key challenges: bringing the function name into scope for recursive calls, generating per-constructor axioms for SMT reasoning, and properly rejecting unsupported cases (polymorphic recursion, missing decreases clauses). The ITE evaluation change to always reduce both branches is a sensible improvement that enables better partial evaluation.
I have a few minor suggestions for clarity and potential improvements, but overall this is high-quality work that's ready to merge after addressing the comments.
Issue #, if available:
Description of changes: This PR adds support for recursive functions in Strata Core, including their definition in concrete syntax, partial evaluation, and an axiom-based SMT encoding.
Main changes:
@[scopeSelf]that acts like@[scope]but also adds the function's name to its body's scope. This is structured and handled very similarly to@[declareDatatype], which involves a similar recursive structure. Main changes are inAST.lean,Format.lean,Core.lean.Funcindicating whether a function is recursive and giving an optionaldecreasesclause. This information is used inEnv.leanto calculate the index of the decreasing argument. Here we also rule out recursive functions that are not yet supported: polymorphic functions, functions with more sophisticated termination measures, and functions without an explicitdecreasingclause.RecursiveAxioms.leancontains the generation of axioms asLExprfor a recursive function. Generating the axiom is fairly simple, since we just create term e.g.forall h t, length (List.cons h t) = length (List.cons h t)and then partially evaluate the right-hand side. Since recursive functions are marked asinlineIfConstron their decreasing parameter, this produces the simplified form.Other changes
SMT/DDMTransform/Translatefor trigger patterns complex enough to handle constructors applied to arguments (e.g.List.cons h t).thenandelsebranches and changes the small-step semantics to match.Tests
RecursiveAxiomTests.leantests the generation of recursive axioms as Lambda terms.SMTEncoderDatatypeTests.leanthat demonstrates the SMT encoding of the recursive function axioms.RecursiveFunctionDDMTest.leantests the DDM parsing for recursive function.RecursiveFunctionErrorTest.leandemonstrates not-yet-supported recursive functions.RecursiveFunctionTests.leancontain a variety of programs with recursive functions, some of which contain VCs which can be solved purely by partial evaluation and others which require SMT-based reasoning.BinaryTreeSize.leangives a more complex example that demonstrates inductive reasoning over types and functions.What is not supported (yet): polymorphic and mutually recursive functions, termination checking.
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.