Skip to content

Shared expression-visitor base for codegen backends (PChecker migration)#950

Merged
ankushdesai merged 1 commit into
masterfrom
claude/shared-expr-visitor
May 24, 2026
Merged

Shared expression-visitor base for codegen backends (PChecker migration)#950
ankushdesai merged 1 commit into
masterfrom
claude/shared-expr-visitor

Conversation

@ankushdesai

Copy link
Copy Markdown
Member

Summary

First step of consolidating the imperative code-generator backends (PChecker, PEx, PObserve). Today each one independently walks the AST with its own parallel ~31-case WriteExpr switch. They handle the identical set of 31 expression nodes, but nothing enforces that — a missed node fails silently (wrong generated output) instead of at compile time, so the backends drift as the language evolves.

This PR introduces ExpressionGenerator<TContext> (Backend/ExpressionGenerator.cs), which owns the IPExpr dispatch once and declares one abstract Write*Expr method per expression node. Backends extend it and implement the per-node emission. Adding a new IPExpr node (plus its dispatch arm) now forces every backend to implement it or the build breaks — that compile-time exhaustiveness is the whole point.

This commit migrates PChecker onto the base; PEx and PObserve follow in separate PRs. PVerifier stays separate by design — it's functional (ExprToString returns UCLID5 terms) and handles a different, verification-specific node set, so forcing it under this base would be a leaky abstraction.

What changed

  • New ExpressionGenerator<TContext> base (dispatch + 31 abstract methods).
  • PCheckerCodeGenerator's WriteExpr switch replaced by 31 override methods, bodies moved verbatim. Class changed publicinternal (it's only referenced from TargetLanguage, same assembly) to satisfy accessibility for the protected overrides over the internal CompilationContext.

Verification

  • Build: CompilerCore builds, 0 errors (only the pre-existing unrelated TransformASTPass.cs:796 CS0162 warning).
  • Output is byte-identical: compiled tutorials 1–6 (ClientServer, TwoPhaseCommit, EspressoMachine, FailureDetector, Paxos, Raft — together exercising the full expression set) with the master compiler and with this branch, then diff -rq on the generated C#: identical, no differences.

Notes

  • No behavior change; pure structural refactor.
  • The CI full test suite will exercise the broader Samples/Regression corpus.

Context: implements the "shared visitor base for the imperative backends" simplification (PVerifier kept separate, phased rollout) discussed for reducing multi-backend maintenance cost. Follow-ups: PEx expressions, then statements, then PObserve.


Generated by Claude Code

First step of consolidating the imperative code-generator backends
(PChecker, PEx, PObserve), which each independently walk the AST with a
parallel ~31-case WriteExpr switch. A missed node fails silently (wrong
output) rather than at compile time, so the backends drift apart as the
language evolves.

Introduces ExpressionGenerator<TContext>, which owns the IPExpr dispatch
once and declares one abstract Write*Expr method per expression node.
Backends extend it and implement the per-node emission; adding a new
IPExpr node (plus a dispatch arm) now forces every backend to handle it
or fail to compile.

This commit migrates PChecker: its WriteExpr switch is replaced by 31
overrides whose bodies are moved verbatim, so generated code is
unchanged. Verified by compiling tutorials 1-6 with the old and new
compiler and diffing the generated C# -- byte-for-byte identical.

PEx and PObserve will be migrated in follow-up PRs; PVerifier stays on
its own functional ExprToString (different paradigm) by design.
Copilot AI review requested due to automatic review settings May 24, 2026 22:48

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Introduces a shared ExpressionGenerator<TContext> base class to centralize IPExpr dispatch for imperative codegen backends, and migrates the PChecker backend to implement per-expression emission via overrides (eliminating the local WriteExpr switch).

Changes:

  • Added ExpressionGenerator<TContext> with a single IPExpr dispatch switch and one abstract Write*Expr method per supported expression node.
  • Refactored PCheckerCodeGenerator to inherit from ExpressionGenerator<CompilationContext> and replace its expression switch with protected override Write*Expr implementations.
  • Adjusted PCheckerCodeGenerator visibility from public to internal to align accessibility with the internal base/context usage.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
Src/PCompiler/CompilerCore/Backend/PChecker/PCheckerCodeGenerator.cs Migrates PChecker expression emission to ExpressionGenerator overrides and updates generator visibility.
Src/PCompiler/CompilerCore/Backend/ExpressionGenerator.cs Adds shared expression dispatch base class to enforce backend exhaustiveness at compile time.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@ankushdesai ankushdesai merged commit 9aee1da into master May 24, 2026
11 checks passed
@ankushdesai ankushdesai deleted the claude/shared-expr-visitor branch May 24, 2026 23:46
@ankushdesai ankushdesai restored the claude/shared-expr-visitor branch May 24, 2026 23:47
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