Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
1abad7f
feat: unify quantifier/map/filter translation on helper functions
andreistefanescu Apr 11, 2026
0a554aa
feat: strengthen quantifier axioms and add loop/empty-vector tests
andreistefanescu Apr 11, 2026
f7cd403
test: add range_map incremental axiom + loop/multi-arg/nested/big tests
andreistefanescu Apr 11, 2026
d6dbd51
test: add suffix-invariant loop test exercising count start-recursion
andreistefanescu Apr 11, 2026
afec5cd
docs: document the quantifier_helpers_module macro pattern
andreistefanescu Apr 11, 2026
5b39373
feat: add vector concat native, align find_indices to return &vector
andreistefanescu Apr 11, 2026
35de703
test: shrink big concrete-vector tests to 8 elements
andreistefanescu Apr 11, 2026
6042d6a
feat: add start-step axioms for map/filter with compound triggers
andreistefanescu Apr 12, 2026
0fb8dce
feat: add find_indices start-step axiom via compound trigger
andreistefanescu Apr 12, 2026
72e8de8
test: strip map.ok.move to just map, move empty cases to their own files
andreistefanescu Apr 12, 2026
2bba5f0
test: restore exact-value find_indices tests via per-spec extra_bpl
andreistefanescu Apr 12, 2026
3f00d77
test: split multi_arg_loop into separate count and filter tests
andreistefanescu Apr 12, 2026
283ee65
fix: strengthen map/range_map axioms, split sum_map into separate axioms
andreistefanescu Apr 12, 2026
4627868
feat: add range_map start-step + suffix-loop tests for all helpers
andreistefanescu Apr 12, 2026
655b718
feat: restore completeness clause for find_indices
andreistefanescu Apr 12, 2026
d9089b5
feat: make all vector-valued helpers use compound triggers symmetrically
andreistefanescu Apr 13, 2026
45f097b
feat: restore filter completeness and provenance clauses
andreistefanescu Apr 13, 2026
3591957
docs: update quantifier_helpers_module docstring + remove stale guard
andreistefanescu Apr 13, 2026
8e2e6f9
fix: simplify false-branch equality + add $IsValid axioms per review
andreistefanescu Apr 13, 2026
44fd0dd
feat: add $IsEqual congruence axioms for all vector-taking helpers
andreistefanescu Apr 13, 2026
7c06a12
refactor: use InRangeVec instead of manual 0 <= i && i < LenVec
andreistefanescu Apr 13, 2026
847fc08
refactor: consolidate same-trigger axioms for vector-valued helpers
andreistefanescu Apr 13, 2026
8aadedc
style: compact comments, use lowercase for inline comments
andreistefanescu Apr 13, 2026
06ebfc7
fix: remove redundant 0 <= LenVec(res), implied by $IsValid
andreistefanescu Apr 13, 2026
79c31e5
refactor: eliminate captured_args_tail, derive CAT from EAB and EAA
andreistefanescu Apr 13, 2026
4e10d53
refactor: separate FindIndices and Count in dst_elem_boogie_type match
andreistefanescu Apr 13, 2026
d7a30e9
refactor: only compute vec element type for vector-valued helpers
andreistefanescu Apr 13, 2026
7e2f638
refactor: move vec_elem_type inside the vector-valued branch
andreistefanescu Apr 13, 2026
14581f9
style: clean up formatting in quantifier_helpers_module
andreistefanescu Apr 13, 2026
4e103ed
refactor: compute EAB and CAT once at macro top, drop EABC
andreistefanescu Apr 13, 2026
e115b4a
style: single-line inner foralls, one set per line in quantifier macro
andreistefanescu Apr 13, 2026
96467ca
docs: update stale captured_args_tail references to CAT
andreistefanescu Apr 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions crates/move-model/src/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1638,6 +1638,7 @@ impl GlobalEnv {
const PROVER_VEC_SUM: &'static str = "sum";
const PROVER_VEC_SUM_RANGE: &'static str = "sum_range";
const PROVER_VEC_SLICE: &'static str = "slice";
const PROVER_VEC_CONCAT: &'static str = "concat";

// vector function names
const VECTOR_REVERSE_FUNCTION_NAME: &'static str = "reverse";
Expand Down Expand Up @@ -2153,6 +2154,14 @@ impl GlobalEnv {
self.get_fun_qid_opt(Self::PROVER_VECTOR_MODULE_NAME, Self::PROVER_VEC_SLICE)
}

pub fn prover_vec_concat_qid(&self) -> QualifiedId<FunId> {
self.get_fun_qid(Self::PROVER_VECTOR_MODULE_NAME, Self::PROVER_VEC_CONCAT)
}

pub fn prover_vec_concat_qid_opt(&self) -> Option<QualifiedId<FunId>> {
self.get_fun_qid_opt(Self::PROVER_VECTOR_MODULE_NAME, Self::PROVER_VEC_CONCAT)
}

pub fn vector_module_id(&self) -> ModuleId {
self.find_module_id(Self::VECTOR_MODULE_NAME)
}
Expand Down Expand Up @@ -3552,6 +3561,7 @@ impl GlobalEnv {
self.prover_vec_sum_qid(),
self.prover_vec_sum_range_qid(),
self.prover_vec_slice_qid(),
self.prover_vec_concat_qid(),
]);
}

Expand Down Expand Up @@ -3796,6 +3806,7 @@ impl GlobalEnv {
self.prover_vec_sum_qid(),
self.prover_vec_sum_range_qid(),
self.prover_vec_slice_qid(),
self.prover_vec_concat_qid(),
]);
}

Expand Down Expand Up @@ -4088,6 +4099,7 @@ impl GlobalEnv {
self.vec_map_get_idx_opt_qid(),
self.vec_map_keys_qid(),
self.prover_vec_slice_qid_opt(),
self.prover_vec_concat_qid_opt(),
self.prover_vec_sum_qid_opt(),
self.prover_vec_sum_range_qid_opt(),
self.prover_range_qid_opt(),
Expand Down

Large diffs are not rendered by default.

75 changes: 54 additions & 21 deletions crates/move-prover-boogie-backend/src/boogie_backend/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ use move_stackless_bytecode::{

use crate::boogie_backend::{
boogie_helpers::{
boogie_bv_type, boogie_function_name, boogie_module_name, boogie_type,
boogie_bv_type, boogie_function_name, boogie_module_name, boogie_type, boogie_type_suffix,
boogie_type_suffix_bv, FunctionTranslationStyle,
},
bytecode_translator::has_native_equality,
Expand Down Expand Up @@ -67,6 +67,14 @@ struct QuantifierHelperInfo {
quantifier_params: String,
quantifier_args: String,
result_type: String,
/// e.g. "vec'u64'" — for `$IsValid'<suffix>'(helper(...))`.
result_is_valid_suffix: String,
/// e.g. "vec'u64'" — for `$IsEqual'<suffix>'(v1, v2)` in congruence axioms.
/// Empty for range_map (no input vector).
input_vec_is_equal_suffix: String,
/// e.g. "int" — Boogie type of input vector elements, for `v2` declaration
/// in congruence axioms. Empty for range_map.
input_elem_type: String,
extra_args_before: String,
extra_args_after: String,
}
Expand Down Expand Up @@ -560,15 +568,6 @@ impl QuantifierHelperInfo {
} else {
"v, start, end".to_string()
};

let dst_elem_boogie_type = if matches!(info.qht, QuantifierHelperType::FindIndices) {
&Type::Primitive(PrimitiveType::U64)
} else if matches!(info.qht, QuantifierHelperType::Filter) {
&params_types[info.li].skip_reference()
} else {
&Type::instantiate(&func_env.get_return_type(0), &info.inst)
};

if func_env.get_parameter_count() > 1 {
quantifier_params = format!(
"{}, {}",
Expand All @@ -585,25 +584,59 @@ impl QuantifierHelperInfo {
})
.join(", ")
);
quantifier_args = format!(
"{}, {}",
quantifier_args,
(0..func_env.get_parameter_count())
.filter(|idx| *idx != info.li)
.map(|val| format!("$t{}", val.to_string()))
.join(", ")
);
let captured_list = (0..func_env.get_parameter_count())
.filter(|idx| *idx != info.li)
.map(|val| format!("$t{}", val.to_string()))
.join(", ");
quantifier_args = format!("{}, {}", quantifier_args, captured_list);
}

// RT and $IsValid suffix are only used by vector-valued helpers
let (result_type, result_is_valid_suffix) = if matches!(
info.qht,
QuantifierHelperType::Map
| QuantifierHelperType::RangeMap
| QuantifierHelperType::Filter
| QuantifierHelperType::FindIndices
) {
let vec_elem_type = match info.qht {
QuantifierHelperType::FindIndices => &Type::Primitive(PrimitiveType::U64),
QuantifierHelperType::Filter => &params_types[info.li].skip_reference(),
_ => &Type::instantiate(&func_env.get_return_type(0), &info.inst),
};
let vec_type = Type::Vector(Box::new(vec_elem_type.clone()));
(
boogie_type(env, vec_elem_type),
boogie_type_suffix(env, &vec_type),
)
} else {
(String::new(), String::new())
};

let (input_vec_is_equal_suffix, input_elem_type) =
if matches!(info.qht, QuantifierHelperType::RangeMap) {
(String::new(), String::new()) // no input vector
} else {
let elem_ty = params_types[info.li].skip_reference();
let vec_type = Type::Vector(Box::new(elem_ty.clone()));
(
boogie_type_suffix(env, &vec_type),
boogie_type(env, &elem_ty),
)
};

Self {
qht: info.qht.str().to_string(),
name: boogie_function_name(&func_env, &info.inst, FunctionTranslationStyle::Pure),
quantifier_params,
quantifier_args,
result_type: boogie_type(env, dst_elem_boogie_type),
result_type,
result_is_valid_suffix,
input_vec_is_equal_suffix,
input_elem_type,
extra_args_before: (0..info.li)
.map(|i| format!("$t{}, ", i.to_string()))
.join(""),
.map(|i| format!("$t{}", i.to_string()))
.join(", "),
extra_args_after: (info.li + 1..func_env.get_parameter_count())
.map(|i| format!(", $t{}", i.to_string()))
.join(""),
Expand Down
Loading
Loading