Skip to content

Commit b6e766e

Browse files
committed
Merge experimental feature axiom-usage-info
2 parents 11e5afe + 099446a commit b6e766e

26 files changed

+351
-92
lines changed

source/air/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,4 @@ win32job = "1"
1919

2020
[features]
2121
singular = []
22+
axiom-usage-info = []

source/air/src/ast.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,12 @@ pub enum StmtX {
176176
Switch(Stmts),
177177
}
178178

179+
#[derive(Debug)]
180+
pub struct Axiom {
181+
pub named: Option<Ident>,
182+
pub expr: Expr,
183+
}
184+
179185
pub type Field = Binder<Typ>;
180186
pub type Fields = Binders<Typ>;
181187
pub type Variant = Binder<Fields>;
@@ -192,7 +198,7 @@ pub enum DeclX {
192198
Const(Ident, Typ),
193199
Fun(Ident, Typs, Typ),
194200
Var(Ident, Typ),
195-
Axiom(Expr),
201+
Axiom(Axiom),
196202
}
197203

198204
pub type Query = Arc<QueryX>;

source/air/src/ast_util.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::ast::{
2-
BinaryOp, Bind, BindX, Binder, BinderX, Command, CommandX, Constant, DeclX, Expr, ExprX, Exprs,
3-
Ident, MultiOp, Qid, Quant, Trigger, Typ, TypX, Typs, UnaryOp,
2+
Axiom, BinaryOp, Bind, BindX, Binder, BinderX, Command, CommandX, Constant, Decl, DeclX, Expr,
3+
ExprX, Exprs, Ident, MultiOp, Qid, Quant, Trigger, Typ, TypX, Typs, UnaryOp,
44
};
55
use std::fmt::Debug;
66
use std::sync::Arc;
@@ -295,3 +295,7 @@ pub fn mk_neg(e: &Expr) -> Expr {
295295
pub fn mk_sub(e1: &Expr, e2: &Expr) -> Expr {
296296
Arc::new(ExprX::Multi(MultiOp::Sub, Arc::new(vec![e1.clone(), e2.clone()])))
297297
}
298+
299+
pub fn mk_unnamed_axiom(expr: Expr) -> Decl {
300+
Arc::new(DeclX::Axiom(Axiom { named: None, expr: expr.clone() }))
301+
}

source/air/src/closure.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use crate::ast::{
2-
BinaryOp, BindX, Binder, Binders, Constant, Decl, DeclX, Expr, ExprX, Ident, MultiOp, Qid,
3-
Quant, Stmt, StmtX, Stmts, Trigger, Triggers, Typ, TypX, Typs, UnaryOp,
2+
Axiom, BinaryOp, BindX, Binder, Binders, Constant, Decl, DeclX, Expr, ExprX, Ident, MultiOp,
3+
Qid, Quant, Stmt, StmtX, Stmts, Trigger, Triggers, Typ, TypX, Typs, UnaryOp,
44
};
5-
use crate::ast_util::{ident_binder, mk_and, mk_eq, mk_forall};
5+
use crate::ast_util::{ident_binder, mk_and, mk_eq, mk_forall, mk_unnamed_axiom};
66
use crate::context::Context;
77
use crate::typecheck::{typ_eq, DeclaredX};
88
use crate::util::vec_map;
@@ -248,7 +248,7 @@ fn simplify_lambda(
248248
trigs
249249
});
250250
let forall = mk_forall(&bs, &trigs, qid.clone(), &eq);
251-
let decl = Arc::new(DeclX::Axiom(forall));
251+
let decl = mk_unnamed_axiom(forall);
252252
state.generated_decls.push(decl);
253253

254254
closure_fun
@@ -370,7 +370,7 @@ fn simplify_choose(
370370
let trigs = Arc::new(vec![trig]);
371371
let forall_qid = None; // The forall uses a trivial trigger, so no need to profile
372372
let forall = mk_forall(&bs, &trigs, forall_qid, &imply);
373-
let decl = Arc::new(DeclX::Axiom(forall));
373+
let decl = mk_unnamed_axiom(forall);
374374
state.generated_decls.push(decl);
375375

376376
closure_fun
@@ -664,9 +664,9 @@ pub(crate) fn simplify_decl(ctxt: &mut Context, decl: &Decl) -> (Vec<Decl>, Decl
664664
DeclX::Const(..) => decl.clone(),
665665
DeclX::Fun(..) => decl.clone(),
666666
DeclX::Var(..) => decl.clone(),
667-
DeclX::Axiom(expr) => {
667+
DeclX::Axiom(Axiom { named, expr }) => {
668668
let (_, expr, _) = simplify_expr(ctxt, &mut state, expr);
669-
Arc::new(DeclX::Axiom(expr))
669+
Arc::new(DeclX::Axiom(Axiom { named: named.clone(), expr }))
670670
}
671671
};
672672
(state.generated_decls, decl)

source/air/src/context.rs

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,16 @@ pub(crate) struct AxiomInfo {
3636
pub(crate) decl: Decl,
3737
}
3838

39+
#[cfg(feature = "axiom-usage-info")]
40+
#[derive(Debug)]
41+
pub enum UsageInfo {
42+
None,
43+
UsedAxioms(Vec<Ident>),
44+
}
45+
3946
#[derive(Debug)]
4047
pub enum ValidityResult {
41-
Valid,
48+
Valid(#[cfg(feature = "axiom-usage-info")] UsageInfo),
4249
Invalid(Option<Model>, Option<ArcDynMessage>, Option<AssertId>),
4350
Canceled,
4451
TypeError(TypeError),
@@ -91,6 +98,7 @@ pub struct Context {
9198
pub(crate) expected_solver_version: Option<String>,
9299
pub(crate) profile_logfile_name: Option<String>,
93100
pub(crate) disable_incremental_solving: bool,
101+
pub(crate) usage_info_enabled: bool,
94102
pub(crate) check_valid_used: bool,
95103
}
96104

@@ -128,6 +136,7 @@ impl Context {
128136
expected_solver_version: None,
129137
profile_logfile_name: None,
130138
disable_incremental_solving: false,
139+
usage_info_enabled: false,
131140
check_valid_used: false,
132141
};
133142
context.axiom_infos.push_scope(false);
@@ -206,6 +215,12 @@ impl Context {
206215
self.air_final_log.log_set_option("disable_incremental_solving", "true");
207216
}
208217

218+
pub fn enable_usage_info(&mut self) {
219+
assert!(matches!(self.state, ContextState::NotStarted));
220+
self.usage_info_enabled = true;
221+
self.set_z3_param_bool("produce-unsat-cores", true, true);
222+
}
223+
209224
// emit blank line into log files
210225
pub fn blank_line(&mut self) {
211226
self.air_initial_log.blank_line();
@@ -466,21 +481,33 @@ impl Context {
466481
match &**command {
467482
CommandX::Push => {
468483
self.push();
469-
ValidityResult::Valid
484+
ValidityResult::Valid(
485+
#[cfg(feature = "axiom-usage-info")]
486+
UsageInfo::None,
487+
)
470488
}
471489
CommandX::Pop => {
472490
self.pop();
473-
ValidityResult::Valid
491+
ValidityResult::Valid(
492+
#[cfg(feature = "axiom-usage-info")]
493+
UsageInfo::None,
494+
)
474495
}
475496
CommandX::SetOption(option, value) => {
476497
self.set_z3_param(option, value);
477-
ValidityResult::Valid
498+
ValidityResult::Valid(
499+
#[cfg(feature = "axiom-usage-info")]
500+
UsageInfo::None,
501+
)
478502
}
479503
CommandX::Global(decl) => {
480504
if let Err(err) = self.global(&decl) {
481505
ValidityResult::TypeError(err)
482506
} else {
483-
ValidityResult::Valid
507+
ValidityResult::Valid(
508+
#[cfg(feature = "axiom-usage-info")]
509+
UsageInfo::None,
510+
)
484511
}
485512
}
486513
CommandX::CheckValid(query) => {

source/air/src/emitter.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::ast::{Decl, Expr, Query};
1+
use crate::ast::{Decl, Expr, Ident, Query};
22
use crate::printer::{macro_push_node, NodeWriter, Printer};
33
use crate::{node, nodes};
44
use sise::Node;
@@ -137,9 +137,14 @@ impl Emitter {
137137
}
138138
}
139139

140-
pub fn log_assert(&mut self, expr: &Expr) {
140+
pub fn log_assert(&mut self, named: &Option<Ident>, expr: &Expr) {
141141
if !self.is_none() {
142-
self.log_node(&nodes!(assert {self.printer.expr_to_node(expr)}));
142+
self.log_node(&
143+
if let Some(named) = named {
144+
nodes!(assert ({Node::Atom("!".to_string())} {self.printer.expr_to_node(expr)} {Node::Atom(":named".to_string())} {Node::Atom((**named).clone())}))
145+
} else {
146+
nodes!(assert {self.printer.expr_to_node(expr)})
147+
})
143148
}
144149
}
145150

source/air/src/main.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
use air::ast::CommandX;
2+
#[cfg(feature = "axiom-usage-info")]
3+
use air::context::UsageInfo;
24
use air::context::{Context, ValidityResult};
35
use air::messages::{AirMessage, AirMessageLabel, Reporter};
46
use air::profiler::{Profiler, PROVER_LOG_FILE};
@@ -138,11 +140,29 @@ pub fn main() {
138140
let result =
139141
air_context.command(&*message_interface, &reporter, &command, Default::default());
140142
match result {
141-
ValidityResult::Valid => {
143+
#[cfg(not(feature = "axiom-usage-info"))]
144+
ValidityResult::Valid() => {
142145
if let CommandX::CheckValid(_) = &**command {
143146
count_verified += 1;
144147
}
145148
}
149+
#[cfg(feature = "axiom-usage-info")]
150+
ValidityResult::Valid(usage_info) => {
151+
if let CommandX::CheckValid(_) = &**command {
152+
count_verified += 1;
153+
154+
if let UsageInfo::UsedAxioms(axioms) = usage_info {
155+
println!(
156+
"Query used named axioms: {}",
157+
axioms
158+
.iter()
159+
.map(|x| (**x).clone())
160+
.collect::<Vec<String>>()
161+
.join(", ")
162+
)
163+
}
164+
}
165+
}
146166
ValidityResult::TypeError(err) => {
147167
panic!("Type error: {}", err);
148168
}

source/air/src/parser.rs

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::ast::{
2-
BinaryOp, BindX, Binder, BinderX, Binders, Command, CommandX, Commands, Constant, Decl, DeclX,
3-
Decls, Expr, ExprX, Exprs, Ident, MultiOp, Qid, Quant, QueryX, Relation, Stmt, StmtX, Stmts,
4-
Trigger, Triggers, Typ, TypX, UnaryOp,
2+
Axiom, BinaryOp, BindX, Binder, BinderX, Binders, Command, CommandX, Commands, Constant, Decl,
3+
DeclX, Decls, Expr, ExprX, Exprs, Ident, MultiOp, Qid, Quant, QueryX, Relation, Stmt, StmtX,
4+
Stmts, Trigger, Triggers, Typ, TypX, UnaryOp,
55
};
66
use crate::def::mk_skolem_id;
77
use crate::messages::ArcDynMessageLabel;
@@ -444,6 +444,28 @@ impl Parser {
444444
}
445445
}
446446

447+
fn nodes_to_named(&self, nodes: &[Node]) -> Result<Option<Ident>, String> {
448+
let mut named = None;
449+
let mut consume_named = false;
450+
451+
for node in nodes {
452+
match node {
453+
Node::Atom(s) if s.to_string() == ":named" => {
454+
consume_named = true;
455+
}
456+
Node::Atom(s) if consume_named && named.is_none() => {
457+
named = Some(Arc::new(s.clone()));
458+
consume_named = false;
459+
}
460+
_ => {
461+
return Err(format!("expected :named; found {}", node_to_string(node)));
462+
}
463+
}
464+
}
465+
466+
Ok(named)
467+
}
468+
447469
fn node_to_quant_or_lambda_expr(
448470
&self,
449471
quantchooselambda: QuantOrChooseOrLambda,
@@ -621,9 +643,19 @@ impl Parser {
621643
let typ = self.node_to_typ(t)?;
622644
Ok(Arc::new(DeclX::Var(Arc::new(x.clone()), typ)))
623645
}
624-
[Node::Atom(s), e] if s.to_string() == "axiom" => {
646+
[Node::Atom(s), axiom_node] if s.to_string() == "axiom" => {
647+
let (e, named) = match &axiom_node {
648+
Node::List(nodes) if nodes.len() >= 2 => match &nodes[0] {
649+
Node::Atom(s) if s.to_string() == "!" => {
650+
let named = self.nodes_to_named(&nodes[2..])?;
651+
(&nodes[1], named)
652+
}
653+
_ => (axiom_node, None),
654+
},
655+
_ => (axiom_node, None),
656+
};
625657
let expr = self.node_to_expr(e)?;
626-
Ok(Arc::new(DeclX::Axiom(expr)))
658+
Ok(Arc::new(DeclX::Axiom(Axiom { named, expr })))
627659
}
628660
_ => Err(format!("expected declaration, found: {}", node_to_string(node))),
629661
},

source/air/src/printer.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::ast::{
2-
BinaryOp, BindX, Binder, Binders, Constant, Datatypes, Decl, DeclX, Expr, ExprX, Exprs, Ident,
3-
MultiOp, Qid, Quant, Query, QueryX, Stmt, StmtX, Triggers, Typ, TypX, Typs, UnaryOp,
2+
Axiom, BinaryOp, BindX, Binder, Binders, Constant, Datatypes, Decl, DeclX, Expr, ExprX, Exprs,
3+
Ident, MultiOp, Qid, Quant, Query, QueryX, Stmt, StmtX, Triggers, Typ, TypX, Typs, UnaryOp,
44
};
55
use crate::def::mk_skolem_id;
66
use crate::util::vec_map;
@@ -366,14 +366,23 @@ impl Printer {
366366
nodes!(declare-var {str_to_node(x)} {self.typ_to_node(typ)})
367367
}
368368

369+
pub fn axiom_to_node(&self, axiom: &Axiom) -> Node {
370+
let Axiom { named, expr } = axiom;
371+
if let Some(named) = named {
372+
nodes!(axiom ({str_to_node("!")} {self.expr_to_node(expr)} {str_to_node(":named")} {str_to_node(named)}))
373+
} else {
374+
nodes!(axiom {self.expr_to_node(expr)})
375+
}
376+
}
377+
369378
pub fn decl_to_node(&self, decl: &Decl) -> Node {
370379
match &**decl {
371380
DeclX::Sort(x) => self.sort_decl_to_node(x),
372381
DeclX::Datatypes(datatypes) => self.datatypes_decl_to_node(datatypes),
373382
DeclX::Const(x, typ) => self.const_decl_to_node(x, typ),
374383
DeclX::Fun(x, typs, typ) => self.fun_decl_to_node(x, typs, typ),
375384
DeclX::Var(x, typ) => self.var_decl_to_node(x, typ),
376-
DeclX::Axiom(expr) => nodes!(axiom {self.expr_to_node(expr)}),
385+
DeclX::Axiom(axiom) => self.axiom_to_node(axiom),
377386
}
378387
}
379388

0 commit comments

Comments
 (0)