Skip to content

Latest commit

 

History

History
18 lines (14 loc) · 2.32 KB

AGENTS.md

File metadata and controls

18 lines (14 loc) · 2.32 KB

References

Arbitrary instances for Ast types

Each PostgresqlSyntax.Ast.* module's instance Qc.Arbitrary <Type> must terminate at size 0 and stay proportionally bounded as size grows. Don't reach for blanket Qc.scale/Qc.resize guesswork on a whole generator or oneof block - apply Gens.downscale (from PostgresqlSyntax.Helpers.Gens) individually, per field, using this rule:

  • An arbitrary call gets wrapped in Gens.downscale if and only if the value it produces is:
    1. the type being defined itself (direct self-recursion) - including nested inside a container like Maybe X, [X], NonEmpty X, or Either X Y, in which case the whole container-producing call gets one Gens.downscale, not each element, OR
    2. a type imported into that module via import {-# SOURCE #-} ....
  • Every other field (plain, non-recursive, non-SOURCE types) stays plain Qc.arbitrary/arbitrary - no downscaling.
  • This holds even for fields whose type is only mutually recursive with the type being defined through an ordinary (non-SOURCE) import: that recursion is already terminated on the other side of the cycle, at whichever module has the SOURCE import breaking it. Downscaling both sides would over-shrink.
  • Every Arbitrary instance must terminate at size 0 - i.e. escape every recursive strongly-connected component and yield a small/leaf value, not an unbounded random walk. Use the Gens.terminatingMaybe helper (also in PostgresqlSyntax.Helpers.Gens) for Maybe X fields where X is self-recursive or SOURCE-imported - it forces Nothing at small sizes instead of relying on the default Maybe instance's non-size-aware frequency.
  • Reference implementations: PostgresqlSyntax.Ast.AExpr, PostgresqlSyntax.Ast.AnyOperator, PostgresqlSyntax.Ast.ExprList, PostgresqlSyntax.Ast.CaseExpr.