This file defines mandatory engineering rules for the compiler repository.
Use existing functions directly. If behavior is identical, do not add a new function that only forwards arguments/returns results.
Why:
- Increases maintenance cost
- Creates multiple sources of truth
- Causes inconsistent behavior across modules/backends
Good:
result := calculateTotal(items)func formatPrice(p float64) string {
return fmt.Sprintf("$%.2f", p)
}
display1 := formatPrice(100)
display2 := formatPrice(200)Bad:
func getTotal(items []Item) int {
return calculateTotal(items)
}display1 := fmt.Sprintf("$%.2f", price1)
display2 := fmt.Sprintf("$%.2f", price2)A new helper is allowed only if at least one is true:
- It removes repeated logic used in 2+ places.
- It centralizes domain logic that must stay consistent (mangling, symbol lookup, receiver shaping, type formatting, ABI decisions).
- It is needed to cross a real boundary (public API, interface contract, backend abstraction).
A new helper is not allowed when:
- It only renames an existing function.
- It only forwards params/return unchanged.
- It is used once and does not clarify complex logic.
- Prefer existing shared modules before adding new code.
- If LLVM and QBE (or multiple phases) share identical logic, move it to a common utility.
- Keep one canonical implementation for:
- type text formatting
- symbol/mangle decisions
- receiver/parameter shape conversion
- repeated diagnostics text
- Keep diffs minimal and task-focused.
- Do not refactor unrelated areas in the same change.
- Do not add temporary workaround code in multiple places; fix at the source layer when possible.
- Remove dead code immediately after migration.
- Name functions by behavior, not by location or temporary intent.
- Avoid vague names (
handle,processData,helper2). - Keep functions short and single-purpose.
- Prefer data-driven logic over repeated
if/switchblocks copied across files.
- Preserve root-cause context in error messages.
- Do not hide failures with generic wrappers.
- Reuse shared diagnostic phrasing/constants where available.
For behavior changes:
- Add or update focused tests near the changed subsystem.
- Add regression tests for bugs that previously failed.
- Validate both relevant backends when backend behavior is affected.
Minimum validation before commit:
gofmton touched Go filesgo testfor touched packages- targeted Ferret smoke/repro if language/runtime behavior changed
- Commit only relevant source/test/docs.
- Do not commit generated binaries or temporary repro executables.
- Keep commit message specific to real behavior change.
Agents must:
- Search for existing implementations before writing new logic.
- Reuse existing function directly when possible.
- Justify any new helper in code review notes/commit rationale.
- Avoid creating compatibility wrappers unless explicitly requested.
Before merge, verify:
- No pass-through wrappers were introduced.
- No duplicated logic remains in touched areas.
- Shared logic was centralized when repeated.
- Tests cover the changed behavior and previous failure mode.
- No unrelated files/artifacts were included.