Skip to content

Migrate PEx expressions to the shared expression-visitor base#953

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

Migrate PEx expressions to the shared expression-visitor base#953
ankushdesai merged 1 commit into
masterfrom
claude/shared-expr-visitor-pex

Conversation

@ankushdesai

Copy link
Copy Markdown
Member

Summary

Migrates PEx onto ExpressionGenerator<TContext> (the base merged to master in #950). Phase 2 of consolidating the imperative backends' expression handling.

PExCodeGenerator now extends ExpressionGenerator<CompilationContext>, and its WriteExpr switch is replaced by the 31 Write*Expr overrides, bodies moved verbatim. PEx's NondetExpr/FairNondetExpr previously shared one switch arm; they're now two overrides routed through a small private WriteRandomBool helper, so emitted code is unchanged.

With PChecker (already on master) and PEx both on the base, adding a new IPExpr node forces both backends to handle it or fail to compile.

Rebased onto current master; targets master directly. (Supersedes the earlier stacked PEx branch, whose remote was removed when #950 landed.)

Verification (local, .NET 8)

  • CompilerCore builds clean (only the unrelated pre-existing TransformASTPass.cs:796 CS0162 warning).
  • PEx-generated Java for Tutorials 1–6 is byte-for-byte identical to master (diff -rq clean). EspressoMachine fails PEx codegen identically on old and new — the pre-existing "receive in a loop body is not supported" limitation (TransformASTPass.cs:793), unrelated to this change.

Note on the old default arm

PEx's previous WriteExpr default emitted a /* Skipping expr ... */ comment; the shared base throws instead. Since all three imperative backends handle the identical 31-node set, that arm was dead for real input — confirmed by the byte-identical tutorial output.

Follow-ups

  • StatementGenerator<TContext> : ExpressionGenerator<TContext> + migrate PChecker/PEx statements.
  • Adapt PObserve (its WriteExpr takes no context/output params — writes to instance fields — so it needs a signature change).

Generated by Claude Code

PExCodeGenerator now extends ExpressionGenerator<CompilationContext>;
its WriteExpr switch is replaced by the 31 Write*Expr overrides (bodies
moved verbatim). PEx's Nondet/FairNondet shared a switch arm, now routed
through a small WriteRandomBool helper to keep the emission identical.

With both PChecker and PEx on the base, adding a new IPExpr node forces
both to handle it at compile time.

Verified: CompilerCore builds clean; PEx-generated Java for tutorials
1-6 is byte-for-byte identical to master (EspressoMachine fails PEx
codegen identically on both, due to the pre-existing 'receive in loop'
limitation, unrelated to this change).
Copilot AI review requested due to automatic review settings May 25, 2026 01:07

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

Migrates the PEx backend’s expression emission to the shared ExpressionGenerator<TContext> visitor base so expression dispatch is centralized and backend implementations become compile-time exhaustive when new IPExpr nodes are added.

Changes:

  • Updated PExCodeGenerator to inherit from ExpressionGenerator<CompilationContext> while still implementing ICodeGenerator.
  • Replaced the monolithic WriteExpr switch with per-node Write*Expr overrides (moved verbatim).
  • Split NondetExpr and FairNondetExpr handling into separate overrides routed through a shared WriteRandomBool helper.

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

protected override void WriteTupleAccessExpr(CompilationContext context, StringWriter output, TupleAccessExpr tupleAccessExpr)
{
context.Write(output, $"({GetPExType(tupleAccessExpr.Type)})(");
var tupleType = tupleAccessExpr.SubExpr.Type.Canonicalize() as TupleType;
Comment on lines +1775 to +1784
PLanguageType elementType;
var isMap = PLanguageType.TypeIsOfKind(containsExpr.Collection.Type, TypeKind.Map);
var isSet = PLanguageType.TypeIsOfKind(containsExpr.Collection.Type, TypeKind.Set);
if (isMap)
elementType = ((MapType)containsExpr.Collection.Type.Canonicalize()).KeyType;
else if (isSet)
elementType = ((SetType)containsExpr.Collection.Type.Canonicalize()).ElementType;
else
elementType = ((SequenceType)containsExpr.Collection.Type.Canonicalize()).ElementType;

@ankushdesai ankushdesai merged commit 60d7be3 into master May 25, 2026
10 of 11 checks passed
@ankushdesai ankushdesai deleted the claude/shared-expr-visitor-pex branch May 25, 2026 01:13
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