View Source cure_refinement_types (cure v0.7.0)
Refinement Types with SMT Verification
This module implements refinement types - types augmented with logical predicates that are verified at compile-time using the Z3 SMT solver.
Refinement Types
A refinement type refines a base type with a logical predicate:
type Positive = Int when x > 0
type NonZero = Int when x != 0
type Percentage = Int when x >= 0 and x =< 100Subtyping
Refinement subtyping is verified using SMT:
Positive <: NonZero (proven by Z3: x > 0 => x /= 0)Features
- Extract constraints from refinement type definitions
- Verify subtyping relationships via SMT
- Check function preconditions and postconditions
- Propagate constraints through function calls
- Generate counterexamples for constraint violations
Summary
Types
-type expr() :: #literal_expr{value :: term(), location :: term()} | #identifier_expr{name :: term(), location :: term()} | #function_call_expr{function :: term(), args :: term(), location :: term()} | #match_expr{expr :: term(), patterns :: term(), location :: term()} | #let_expr{bindings :: term(), body :: term(), location :: term()} | #binary_op_expr{op :: term(), left :: term(), right :: term(), location :: term()} | #unary_op_expr{op :: term(), operand :: term(), location :: term()} | #list_expr{elements :: term(), location :: term()} | #vector_expr{elements :: term(), location :: term()} | #tuple_expr{elements :: term(), location :: term()} | #record_expr{name :: term(), fields :: term(), location :: term()} | #field_access_expr{record :: term(), field :: term(), location :: term()} | #record_update_expr{name :: term(), base :: term(), fields :: term(), location :: term()} | #lambda_expr{params :: term(), body :: term(), location :: term()} | #forall_expr{variables :: term(), body :: term(), location :: term()} | #exists_expr{variables :: term(), body :: term(), location :: term()} | #fsm_spawn_expr{fsm_name :: term(), init_args :: term(), init_state :: term(), location :: term()} | #fsm_send_expr{target :: term(), message :: term(), location :: term()} | #fsm_receive_expr{patterns :: term(), timeout :: term(), location :: term()} | #fsm_state_expr{location :: term()} | #melquiades_send_expr{message :: term(), target :: term(), location :: term()} | #qualified_call_expr{trait_name :: term(), type_args :: term(), method_name :: term(), receiver :: term(), args :: term(), location :: term()}.
-type type_expr() :: #primitive_type{name :: term(), location :: term()} | #dependent_type{name :: term(), type_params :: term(), value_params :: term(), location :: term()} | #function_type{params :: term(), return_type :: term(), location :: term()} | #union_type{types :: term(), location :: term()} | #list_type{element_type :: term(), length :: term(), location :: term()} | #tuple_type{element_types :: term(), location :: term()} | #fsm_type{name :: term(), states :: term(), message_types :: term(), location :: term()} | #process_type{fsm_type :: term(), current_state :: term(), location :: term()} | #genserver_ref_type{variant :: term(), location :: term()}.
Functions
-spec base_type(refinement_type()) -> type_expr().
-spec check_constraint(expr(), refinement_type(), map()) -> {ok, boolean()} | {error, term()}.
-spec create_refinement_type(type_expr(), atom(), expr()) -> refinement_type().
-spec extract_constraint(refinement_type()) -> {ok, expr()} | {error, term()}.
-spec generate_counterexample(expr(), refinement_type()) -> {ok, map()} | {error, term()}.
-spec refinement_predicate(refinement_type()) -> expr().
-spec strengthen_type(type_expr(), expr(), atom()) -> refinement_type().
-spec verify_postcondition(expr(), refinement_type(), map(), location()) -> ok | {error, term()}.
-spec verify_precondition(expr(), refinement_type(), map(), location()) -> ok | {error, term()}.
-spec verify_subtype_smt(refinement_type(), refinement_type(), map()) -> {ok, boolean()} | {error, term()}.
-spec weaken_type(refinement_type(), [atom()]) -> type_expr().