Skip to content

Conversation

@MikaelMayer
Copy link
Contributor

@MikaelMayer MikaelMayer commented Jan 27, 2026

Add support for function declarations within statement blocks

This PR adds the ability to declare functions as a statement Stmt.funDecl in Strata Core, enabling local function definitions within procedures.

Changes

  • Implemented statement-level operations (variable analysis, substitution, type erasure) for funcDecl
  • Added type checking that converts between PureFunc and Function representations, handling type monomorphization
  • Implemented evaluation that makes function context updatable locally by adding declared functions to the factory
  • Extended all program transformations to handle funcDecl

Testing

Added tests demonstrating funcDecl functionality: declaring helper functions within statement blocks and using them in subsequent statements, including symbolic variable capture from enclosing scope.

@MikaelMayer MikaelMayer changed the title Add support for function declarations within statement blocks Add support for function declarations statements Jan 27, 2026
@MikaelMayer MikaelMayer changed the title Add support for function declarations statements Add support for function declaration statements Jan 27, 2026
@MikaelMayer MikaelMayer force-pushed the add-func-decl-to-statements branch from 6016b5a to b8ec252 Compare January 28, 2026 18:21
…or Func

- Added ToFormat for generic Func with proper constraints
- Added [ToFormat T.IDMeta] to Factory.lean section variables
- Removed unnecessary ToFormat instances from test files and Program.lean
- Removed custom Env.format function (now uses default ToFormat)
- Function bodies now display properly instead of showing <body>
- Resolved conflict in Factory.lean (Factory_wf moved to FactoryWF.lean in main)
- Applied rotate_left fix to FactoryWF.lean
@MikaelMayer MikaelMayer marked this pull request as ready for review January 29, 2026 20:27
@MikaelMayer MikaelMayer requested a review from a team as a code owner January 29, 2026 20:27
MikaelMayer and others added 6 commits January 29, 2026 14:35
- Modified testFuncDeclSymbolic to show functions capture variables by reference
- Function declared with n=10, then n mutated to 20, function uses n=20 at call time
- Proof obligation correctly shows result should be 25 (5+20), not 15 (5+10)
- Reverted Env.lean to main (custom scope formatting not needed)
…claration time

- Functions now capture variable values at declaration time, not by reference
- Free variables in function body are substituted with their current values from environment
- Test demonstrates: n=10 at declaration, n=20 after mutation, function uses n=10
- Proof obligation correctly shows result is 15 (5+10), not 25 (5+20)
Copy link
Contributor

@joscoh joscoh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall looks good, had a few questions about polymorphism. Also, do the small step semantics for Statements (StmtSemanticsSmallStep.lean) need to be updated?

-/
structure LFuncWF {T : LExprParams} (f : LFunc T) extends FuncWF f where
-- Free variables of body must be arguments.
body_freevars:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why doesn't this hold for general Func? Is it because there is no generic notion of "variable in an expression"?


-- LFuncWF.concreteEval_argmatch is not decidable.
-- FuncWF.concreteEval_argmatch and LFuncWF.concreteEval_argmatch are not decidable.-- FuncWF.body_freevars is commented out as it's expression-type specific
-- FuncWF.concreteEval_argmatch is not decidable.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Repeated comment. Also, Why would FuncWF.body_freevars be commented out?

typeArgs := decl.typeArgs,
isConstr := decl.isConstr,
inputs := decl.inputs.map (fun (id, ty) => (id, Lambda.LTy.toMonoTypeUnsafe ty)),
output := Lambda.LTy.toMonoTypeUnsafe decl.output,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the unsafe cause any problems with polymorphism?

axioms := decl.axioms
}
let (func', Env) ← Function.typeCheck C Env func |>.mapError DiagnosticModel.fromFormat
-- Convert back by wrapping monotypes in trivial polytypes
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, what happens to polymorphic functions?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to see a test with a polymorphic function decl, followed by using one (or even better, multiple) concrete instantiations of this function. For example, something like:

function toInt (x: a) : int { 1 }
assert (toInt(3) == toInt(true));

Just to make sure there are no type variables captured.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants