Documentation
¶
Overview ¶
Package contract provides function behavior specifications using Hoare-style contracts.
A contract (Spec) specifies the complete behavioral interface of a function:
Preconditions (Requires): Constraints that must hold at the call site. The type checker verifies these at each call and reports errors when preconditions cannot be proven.
-- Precondition: first argument must be non-nil
function assert_not_nil(x)
if x == nil then error("nil!") end
return x
end
Postconditions (Ensures): Facts that become true after the call returns. The type checker adds these to the type environment for subsequent code, enabling narrowing.
-- Postcondition: return value is non-nil local y = assert_not_nil(x) -- y is narrowed to non-nil
Effects: Type-level side effects from types/effect, including mutations, return type derivations, and control effects like throw/diverge.
Callbacks: Specifications for callback parameters, describing how they are invoked (cardinality), what they return (boolean for predicates), and whether they are pure.
Return specifications: Conditional return types based on argument conditions, enabling precise return types that depend on runtime values.
Usage:
spec := contract.NewSpec().
WithRequires(constraint.NotNil{Path: constraint.Path{Root: "p0"}}).
WithEnsures(constraint.NotNil{Path: constraint.Path{Root: "r0"}}).
WithEffects(effect.Throw{})
fn := typ.Func().Param("x", typ.Any).Returns(typ.Any).Spec(spec).Build()
Index ¶
- type CallbackSpec
- type Cardinality
- type ReturnCase
- type ReturnSpec
- type Spec
- func (s *Spec) EffectRow() effect.Row
- func (s *Spec) Equals(other any) bool
- func (s *Spec) GetCallback(paramIdx int) *CallbackSpec
- func (s *Spec) GetIterator() *effect.Iterator
- func (s *Spec) GetMutation() *effect.Mutate
- func (s *Spec) GetMutationAt(paramIdx int) *effect.Mutate
- func (s *Spec) GetReturnCases() []ReturnCase
- func (s *Spec) GetReturnDefault() typ.Type
- func (s *Spec) GetReturnLength(retIdx int) *effect.ReturnLength
- func (s *Spec) GetReturnType(retIdx int) *effect.Return
- func (s *Spec) GetTableMutator() *effect.TableMutator
- func (s *Spec) HasMutation() bool
- func (s *Spec) IsFilter() bool
- func (s *Spec) IsIndexedIterator() bool
- func (s *Spec) IsKeyedIterator() bool
- func (s *Spec) IsSpecInfo()
- func (s *Spec) IsTableMutator() bool
- func (s *Spec) String() string
- func (s *Spec) WithCallback(paramIdx int, spec *CallbackSpec) *Spec
- func (s *Spec) WithDefaultReturn(t typ.Type) *Spec
- func (s *Spec) WithEffectRow(row effect.Row) *Spec
- func (s *Spec) WithEffects(labels ...effect.Label) *Spec
- func (s *Spec) WithEnsures(constraints ...constraint.Constraint) *Spec
- func (s *Spec) WithExprEnsures(constraints ...constraint.ExprCompare) *Spec
- func (s *Spec) WithExprRequires(constraints ...constraint.ExprCompare) *Spec
- func (s *Spec) WithRequires(constraints ...constraint.Constraint) *Spec
- func (s *Spec) WithReturnCase(cond constraint.Condition, t typ.Type) *Spec
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type CallbackSpec ¶
type CallbackSpec struct {
// InputSource references the parameter providing input to the callback.
InputSource effect.ParamRef
// ReturnsBoolean indicates the callback returns a boolean (predicate).
ReturnsBoolean bool
// Cardinality describes how many times the callback is invoked.
Cardinality Cardinality
// Pure indicates the callback has no side effects.
Pure bool
// EnvOverlay describes callback-scoped globals injected into the callback environment.
EnvOverlay map[string]typ.Type
}
CallbackSpec describes a callback parameter's expected behavior.
CallbackSpec enables precise typing of higher-order functions by describing how a callback is used:
For table.filter(t, predicate):
CallbackSpec{
InputSource: ParamRef{Index: 0}, // callback receives elements from t
ReturnsBoolean: true, // callback is a predicate
Cardinality: CardAtMostOncePerElement,
Pure: true,
}
This enables the type checker to:
- Infer callback parameter types from InputSource
- Verify callback return type matches ReturnsBoolean
- Track cardinality for escape analysis
- Inject EnvOverlay bindings into callback scope
func MapperSpec ¶
func MapperSpec(inputParam int) *CallbackSpec
MapperSpec creates a callback spec for mapping functions.
func PredicateSpec ¶
func PredicateSpec(inputParam int) *CallbackSpec
PredicateSpec creates a callback spec for predicate functions.
func (*CallbackSpec) Clone ¶
func (c *CallbackSpec) Clone() *CallbackSpec
Clone returns a deep copy of the CallbackSpec.
func (*CallbackSpec) Equals ¶
func (c *CallbackSpec) Equals(other *CallbackSpec) bool
Equals returns true if two CallbackSpec values are structurally equal.
func (*CallbackSpec) WithEnvOverlay ¶
func (c *CallbackSpec) WithEnvOverlay(env map[string]typ.Type) *CallbackSpec
WithEnvOverlay sets callback-scoped globals.
type Cardinality ¶
type Cardinality int
Cardinality describes invocation count for callbacks.
Cardinality is used for escape analysis and optimization. A callback that is only called once per element may have different optimization opportunities than one called an unknown number of times.
const ( // CardOncePerElement: callback is called exactly once per input element. // Used by table.map, table.foreach. CardOncePerElement Cardinality = iota // CardAtMostOncePerElement: callback may be called 0 or 1 times per element. // Used by table.filter (stops on first match in some variants). CardAtMostOncePerElement // CardExactlyOnce: callback is called exactly once total. // Used by pcall, xpcall. CardExactlyOnce // CardAtMostOnce: callback may be called 0 or 1 times total. // Used by table.find (calls predicate until match). CardAtMostOnce // CardUnknown: invocation count is not known. // Conservative default for user-defined higher-order functions. CardUnknown )
func (Cardinality) String ¶
func (c Cardinality) String() string
type ReturnCase ¶
type ReturnCase struct {
// When is the condition under which this return type applies.
When constraint.Condition
// Type is the refined return type when the condition holds.
Type typ.Type
}
ReturnCase describes a conditional return type.
A ReturnCase pairs a condition with a return type. When the condition can be proven from the call context, the associated type is used instead of the default return type.
func (ReturnCase) Equals ¶
func (r ReturnCase) Equals(other ReturnCase) bool
Equals returns true if two ReturnCase values are structurally equal.
type ReturnSpec ¶
type ReturnSpec struct {
// Cases holds condition-dependent return type refinements.
Cases []ReturnCase
// Default is the return type when no case condition matches.
Default typ.Type
}
ReturnSpec describes conditional return types.
ReturnSpec enables overload-like behavior where the return type depends on the argument types or values. Cases are checked in order; the first matching condition determines the return type.
Example for tonumber(s):
ReturnSpec{
Cases: []ReturnCase{
{When: HasType{p0, integer}, Type: integer}, // integer input
{When: HasType{p0, number}, Type: number}, // number input
},
Default: typ.NewOptional(typ.Number), // string input may fail
}
func (*ReturnSpec) Equals ¶
func (r *ReturnSpec) Equals(other *ReturnSpec) bool
Equals returns true if two ReturnSpec values are structurally equal.
type Spec ¶
type Spec struct {
// Requires holds preconditions that must be satisfied at call site.
// Checked by the type checker before the call; errors if not provable.
Requires constraint.Condition
// Ensures holds postconditions that become facts after the call returns.
// Added to the type environment for code following the call.
Ensures constraint.Condition
// ExprRequires holds arithmetic preconditions on parameters.
// Used for length/index bounds checking.
ExprRequires []constraint.ExprCompare
// ExprEnsures holds arithmetic postconditions on return values.
// Used for return length guarantees.
ExprEnsures []constraint.ExprCompare
// Effects describes type-level side effects (mutations, returns).
// See types/effect for the effect label vocabulary.
Effects effect.Row
// Callbacks maps parameter indices to their callback specifications.
// Key is the 0-based parameter index of the callback.
Callbacks map[int]*CallbackSpec
// Return describes conditional return type refinements.
// Enables different return types based on argument conditions.
Return *ReturnSpec
}
Spec is the complete specification of a function's behavior.
A Spec captures everything the type checker needs to know about a function's contract with its callers. This information enables:
- Precondition checking at call sites
- Type narrowing from postconditions
- Effect propagation through call chains
- Precise return type derivation
- Higher-order function analysis via callback specs
func ExtractSpec ¶
ExtractSpec unwraps a function type and returns its contract spec, or nil.
func (*Spec) Equals ¶
Equals returns true if two Specs are structurally equal. Implements internal.Equaler interface for use in typ.Function.
func (*Spec) GetCallback ¶
func (s *Spec) GetCallback(paramIdx int) *CallbackSpec
GetCallback returns the callback spec for a parameter.
func (*Spec) GetIterator ¶
GetIterator returns the iterator effect.
func (*Spec) GetMutation ¶
GetMutation returns the first mutation effect.
func (*Spec) GetMutationAt ¶
GetMutationAt returns the mutation effect for a specific parameter.
func (*Spec) GetReturnCases ¶
func (s *Spec) GetReturnCases() []ReturnCase
GetReturnCases returns conditional return cases.
func (*Spec) GetReturnDefault ¶
GetReturnDefault returns the default return type if set.
func (*Spec) GetReturnLength ¶
func (s *Spec) GetReturnLength(retIdx int) *effect.ReturnLength
GetReturnLength returns the return length effect.
func (*Spec) GetReturnType ¶
GetReturnType returns the return type effect.
func (*Spec) GetTableMutator ¶
func (s *Spec) GetTableMutator() *effect.TableMutator
GetTableMutator returns the table mutator effect.
func (*Spec) HasMutation ¶
HasMutation returns true if the spec mutates any parameter.
func (*Spec) IsIndexedIterator ¶
IsIndexedIterator returns true if this spec has an indexed iterator effect.
func (*Spec) IsKeyedIterator ¶
IsKeyedIterator returns true if this spec has a keyed iterator effect.
func (*Spec) IsTableMutator ¶
IsTableMutator returns true if this spec has a table mutator effect.
func (*Spec) WithCallback ¶
func (s *Spec) WithCallback(paramIdx int, spec *CallbackSpec) *Spec
WithCallback adds a callback specification.
func (*Spec) WithDefaultReturn ¶
WithDefaultReturn sets the default return when no case matches.
func (*Spec) WithEffectRow ¶
WithEffectRow sets the effect row directly.
func (*Spec) WithEffects ¶
WithEffects adds type effects.
func (*Spec) WithEnsures ¶
func (s *Spec) WithEnsures(constraints ...constraint.Constraint) *Spec
WithEnsures adds postconditions.
func (*Spec) WithExprEnsures ¶
func (s *Spec) WithExprEnsures(constraints ...constraint.ExprCompare) *Spec
WithExprEnsures adds expression postconditions.
func (*Spec) WithExprRequires ¶
func (s *Spec) WithExprRequires(constraints ...constraint.ExprCompare) *Spec
WithExprRequires adds expression preconditions.
func (*Spec) WithRequires ¶
func (s *Spec) WithRequires(constraints ...constraint.Constraint) *Spec
WithRequires adds preconditions.
func (*Spec) WithReturnCase ¶
WithReturnCase adds a conditional return case.