Skip to content

F# emit for the remaining service/codegen frame surface (2.2.7)#400

Merged
jeremydmiller merged 1 commit into
mainfrom
feat-fsharp-frame-surface
May 29, 2026
Merged

F# emit for the remaining service/codegen frame surface (2.2.7)#400
jeremydmiller merged 1 commit into
mainfrom
feat-fsharp-frame-surface

Conversation

@jeremydmiller
Copy link
Copy Markdown
Member

Closes #399.

Wiring the first Wolverine EF Core static-codegen slice through the F# emit path hit LazyServiceLocationFrame with no GenerateFSharpCode (mid-render NotSupportedException). A sweep for GenerateCode overrides lacking an F# counterpart found the rest of the frame surface, all added here:

Frame F# emit
LazyServiceLocationFrame let x = ServiceProviderServiceExtensions.GetRequiredService<T>(provider) — the frame the EF Core render needed
AppendActivityEventFrame if not (isNull Activity.Current) then Activity.Current.AddEvent(...) |> ignore (no ?. in F#)
ReturnValueTask trailing ValueTask<T>(result) expression (no return keyword)
NowFetchFrame let now = System.DateTime.UtcNow
CreateArrayFrame F# array literal `[
MemberAccessFrame let x = parent.Member

TemplateFrame is intentionally left throwing — its body is an arbitrary C# template string supplied by the subclass, so a generic F# re-emit is unsafe; F# support there is a subclass responsibility.

Coverage

Each frame gets a dedicated sample type in FSharpCodegenSample (contracts in FSharpCodegenTarget), so the checked-in compile-gate regenerates Generated.fs and compiles it on net9.0 and net10.0. Gate is green.

Bumps JasperFxVersion to 2.2.7.

🤖 Generated with Claude Code

Add GenerateFSharpCode to the JasperFx frames that still threw
NotSupportedException on the F# path, completing the frame surface the
Wolverine EF Core static-codegen slice exercises:

- LazyServiceLocationFrame  -> GetRequiredService<T>(provider) (the frame
  the EF Core render needed)
- AppendActivityEventFrame  -> if not (isNull Activity.Current) then
  ...AddEvent(...) |> ignore  (no null-conditional in F#)
- ReturnValueTask           -> trailing ValueTask<T>(result) expression
- NowFetchFrame             -> let now = System.DateTime.UtcNow
- CreateArrayFrame          -> F# array literal [| a; b |] + keyed-mirror guard
- MemberAccessFrame         -> let x = parent.Member

TemplateFrame is intentionally left throwing: its body is an arbitrary C#
template supplied by the subclass, so a generic F# re-emit is unsafe.

Each frame is covered by a new sample type in the checked-in F# compile-gate
fixture (FSharpCodegenSample / FSharpCodegenTarget); the gate compiles the
regenerated Generated.fs on net9.0 and net10.0. Bumps to 2.2.7.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@jeremydmiller jeremydmiller merged commit 51a0230 into main May 29, 2026
1 check passed
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.

F# code generation: complete the remaining service/codegen frame surface

1 participant