Skip to content

Add Python-first Model IR and Rust codegen prototype with docs and tests#33

Closed
blackopsrepl wants to merge 2 commits into
mainfrom
codex/design-python-interface-for-solverforge
Closed

Add Python-first Model IR and Rust codegen prototype with docs and tests#33
blackopsrepl wants to merge 2 commits into
mainfrom
codex/design-python-interface-for-solverforge

Conversation

@blackopsrepl
Copy link
Copy Markdown
Collaborator

Motivation

  • Introduce a Python-first declarative IR so Python users can describe SolverForge models that lower into typed Rust code and preserve zero-erasure execution.
  • Capture postmortem rationale for abandoning the prior dynamic solverforge-py experiment and set guardrails for Path 2 (IR -> codegen -> compile).

Description

  • Add python/solverforge_ir package implementing a typed IR (model.py), lambda lowering (lambda_to_expr), validation (validate_model), and a Rust code generator (codegen.py) that emits lib.rs and Cargo.toml and returns GeneratedRustProject metadata.
  • Emit expression lowering for comparisons, boolean ops, whitelisted calls (contains, len, overlaps), and map Python type hints like Option[...]/Vec[...] to Rust types via _map_type.
  • Add Python tests under python/tests exercising IR lowering, model validation, and Rust code generation (test_model_ir.py, test_codegen.py).
  • Add documentation files docs/python-model-ir.md and docs/python-path2-postmortem.md, and register the new doc pages in README.md.

Testing

  • Ran Python unit tests python/tests/test_model_ir.py which exercise lambda_to_expr and validate_model, and they passed.
  • Ran Python unit tests python/tests/test_codegen.py which validate generated Rust module snippets and project writing, and they passed.
  • No additional CI or Rust compilation was executed as part of these tests; write_rust_project writes files and tests assert their existence.

Codex Task

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 739bb7c807

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread python/solverforge_ir/codegen.py Outdated
lines.extend(_emit_entities(model.entities))
lines.extend(_emit_solution(model))

lines.append(f"use {model.solution.name}ConstraintStreams;")
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Move ConstraintStreams import out of module scope

generate_rust_module emits use <Solution>ConstraintStreams; at the top level, but #[planning_solution] generates that trait in the same module. In Rust this becomes a re-import of an already-defined item (E0255), so generated crates fail to compile before constraint code runs. Put this use inside define_constraints() (as done in existing examples) or remove it entirely.

Useful? React with 👍 / 👎.

Comment thread python/solverforge_ir/codegen.py Outdated

def _emit_constraint_builder(model: ModelDef, constraint: ConstraintDef, c_name: str, score_ty: str) -> list[str]:
solution_name = model.solution.name
source_entity_name = model.solution.entity_collections[constraint.source.collection_field]
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Accept fact collections as constraint sources in codegen

_emit_constraint_builder assumes every constraint.source.collection_field is an entity collection by indexing model.solution.entity_collections[...]. However, validate_model explicitly allows source collections from both entity and fact collections, so valid models with fact-based sources crash with KeyError during generation. Resolve the source type from both collection maps (like the join right-side lookup) before emitting stream types.

Useful? React with 👍 / 👎.

Comment thread python/solverforge_ir/codegen.py Outdated

def _impact_method(impact: ImpactSpec) -> str:
prefix = "penalize" if impact.impact == "penalize" else "reward"
return f"{prefix}_{impact.level}"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Guard medium impacts from unsupported builder methods

_impact_method blindly concatenates impact.level, which can emit penalize_medium/reward_medium for ImpactSpec(level="medium"). The stream API in this repo does not define medium-level builder methods, so these generated calls do not compile when users choose that IR value. Add validation/mapping so only supported method names are emitted for the selected score API.

Useful? React with 👍 / 👎.

@blackopsrepl blackopsrepl force-pushed the codex/design-python-interface-for-solverforge branch from 739bb7c to 4386f63 Compare April 12, 2026 14:43
@blackopsrepl
Copy link
Copy Markdown
Collaborator Author

Closing this PR because the Python implementation has moved to a standalone repository and is no longer intended for inclusion in the SolverForge Rust workspace.

@blackopsrepl blackopsrepl deleted the codex/design-python-interface-for-solverforge branch April 13, 2026 14:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant