-
Notifications
You must be signed in to change notification settings - Fork 11
Implement get models #96
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
maditaP
wants to merge
10
commits into
moves-rwth:main
Choose a base branch
from
maditaP:implement-get-models
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
3851b13
get-models: Add command to get models for preexpectations
maditaP 257c3c7
get-models: Add pretty models
maditaP 73c32d2
get-models: Linearize flow
maditaP 5b09fdb
get-models: Change name of command to "get-pre-models"
maditaP 11586a5
get-models: Extract "run_smt_check_sat" function
maditaP de104f6
get-model: Rename CoreVerifyTask to CoreHeyVLTask & refactor
maditaP c8ad8f6
get-models: Improve comments
maditaP 891a4a5
get-models: Import BinOpKind normally
maditaP db7f15a
get-models: Use reduce in encode-preexpectation
maditaP e2bdae0
get-models: Move def. of top/bot to relevant branches
maditaP File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,215 @@ | ||
| use std::{ops::DerefMut, process::ExitCode, sync::Arc}; | ||
|
|
||
| use crate::{ | ||
| ast::{BinOpKind, Direction, ExprBuilder, FileId, Span, TyKind}, | ||
| driver::{ | ||
| commands::{mk_cli_server, print_timings, verify::VerifyCommand}, | ||
| core_heyvl::{lower_core_heyvl_task, CoreHeyVLTask}, | ||
| error::{finalize_caesar_result, CaesarError}, | ||
| front::parse_and_tycheck, | ||
| item::Item, | ||
| quant_proof::BoolVcProveTask, | ||
| smt_proof::{run_smt_check_sat, set_global_z3_params}, | ||
| }, | ||
| resource_limits::{await_with_resource_limits, LimitsRef}, | ||
| servers::{Server, SharedServer}, | ||
| }; | ||
| use z3::SatResult; | ||
|
|
||
| pub async fn run_nontrivial_model_command(options: VerifyCommand) -> ExitCode { | ||
| let (user_files, server) = match mk_cli_server(&options.input_options) { | ||
| Ok(value) => value, | ||
| Err(value) => return value, | ||
| }; | ||
| let options = Arc::new(options); | ||
| let nontrivial_models_result = nontrivial_model_files(&options, &server, user_files).await; | ||
|
|
||
| if options.debug_options.timing { | ||
| print_timings(); | ||
| } | ||
|
|
||
| finalize_caesar_result(server, &options.rlimit_options, nontrivial_models_result) | ||
| } | ||
|
|
||
| /// This is just like verify_files() | ||
| pub async fn nontrivial_model_files( | ||
| options: &Arc<VerifyCommand>, | ||
| server: &SharedServer, | ||
| user_files: Vec<FileId>, | ||
| ) -> Result<bool, CaesarError> { | ||
| let handle = |limits_ref: LimitsRef| { | ||
| let options = options.clone(); | ||
| let server = server.clone(); | ||
| tokio::task::spawn_blocking(move || { | ||
| // execute the verifier with a larger stack size of 50MB. the | ||
| // default stack size might be quite small and we need to do quite a | ||
| // lot of recursion. | ||
| let stack_size = 50 * 1024 * 1024; | ||
| stacker::maybe_grow(stack_size, stack_size, move || { | ||
| let mut server = server.lock().unwrap(); | ||
| nontrivial_model_files_main(&options, limits_ref, server.deref_mut(), &user_files) | ||
| }) | ||
| }) | ||
| }; | ||
| // Unpacking lots of Results with `.await??` :-) | ||
| await_with_resource_limits( | ||
| Some(options.rlimit_options.timeout()), | ||
| Some(options.rlimit_options.mem_limit()), | ||
| handle, | ||
| ) | ||
| .await?? | ||
| } | ||
|
|
||
| fn nontrivial_model_files_main( | ||
| options: &VerifyCommand, | ||
| limits_ref: LimitsRef, | ||
| server: &mut dyn Server, | ||
| user_files: &[FileId], | ||
| ) -> Result<bool, CaesarError> { | ||
| let (mut module, mut tcx) = parse_and_tycheck( | ||
| &options.input_options, | ||
| &options.debug_options, | ||
| server, | ||
| user_files, | ||
| )?; | ||
|
|
||
| // Register all relevant source units with the server | ||
| module.register_with_server(server)?; | ||
|
|
||
| // explain high-level HeyVL if requested | ||
| if options.lsp_options.explain_vc { | ||
| module.explain_high_level_vc(&tcx, &limits_ref, server)?; | ||
| } | ||
|
|
||
| // Desugar encodings from source units. | ||
| module.apply_encodings(&mut tcx, server)?; | ||
|
|
||
| if options.debug_options.print_core_procs { | ||
| println!("HeyVL get nontrivial model task with generated procs:"); | ||
| println!("{module}"); | ||
| } | ||
|
|
||
| // generate dependency graph to determine which declarations are needed for | ||
| // the SMT translation later | ||
| let mut depgraph = module.generate_depgraph(&options.opt_options.function_encoding)?; | ||
|
|
||
| // translate program to relevant preexpectation conditions | ||
| let mut verify_units: Vec<Item<CoreHeyVLTask>> = module | ||
| .items | ||
| .into_iter() | ||
| .flat_map(|item| { | ||
| item.flat_map(|unit| CoreHeyVLTask::from_proc_pre_model(unit, &mut depgraph)) | ||
| }) | ||
| .collect(); | ||
|
|
||
| if options.debug_options.z3_trace && verify_units.len() > 1 { | ||
| tracing::warn!("Z3 tracing is enabled with multiple units. Intermediate tracing results will be overwritten."); | ||
| } | ||
| // set requested global z3 options | ||
| set_global_z3_params(options, &limits_ref); | ||
|
|
||
| let mut num_sat: usize = 0; | ||
| let mut num_unsat: usize = 0; | ||
|
|
||
| for verify_unit in &mut verify_units { | ||
| limits_ref.check_limits()?; | ||
|
|
||
| let (name, mut verify_unit) = verify_unit.enter_with_name(); | ||
|
|
||
| // Set the current unit as ongoing | ||
| server.set_ongoing_unit(name)?; | ||
|
|
||
| // no slicing | ||
| let mut new_options = VerifyCommand::default(); | ||
| new_options.slice_options.no_slice_error = true; | ||
|
|
||
| let (vc_expr, _slice_vars) = lower_core_heyvl_task( | ||
| &mut tcx, | ||
| name, | ||
| &new_options, | ||
| &limits_ref, | ||
| server, | ||
| &mut verify_unit, | ||
| )?; | ||
|
|
||
| // Lowering the quantitative task to a Boolean one. | ||
| let mut quant_task = vc_expr; | ||
|
|
||
| // Unfolding (applies substitutions) | ||
| quant_task.unfold(options, &limits_ref, &tcx)?; | ||
|
|
||
| quant_task.trace_expr_stats(); | ||
|
|
||
| // Turn quantitative formula into a Boolean one | ||
| let builder = ExprBuilder::new(Span::dummy_span()); | ||
| let expr = quant_task.expr.clone(); | ||
|
|
||
| // Construct the condition based on quantifier direction | ||
| let res = match quant_task.direction { | ||
| Direction::Up => { | ||
| // For coprocs, check if expr < top | ||
| let top = builder.top_lit(quant_task.expr.ty.as_ref().unwrap()); | ||
| builder.binary(BinOpKind::Lt, Some(TyKind::Bool), expr, top) | ||
| } | ||
| Direction::Down => { | ||
| // For procs, check if expr > bot | ||
| let bot = builder.bot_lit(quant_task.expr.ty.as_ref().unwrap()); | ||
| builder.binary(BinOpKind::Gt, Some(TyKind::Bool), expr, bot) | ||
| } | ||
| }; | ||
|
|
||
| // Create a Boolean verification task with the comparison | ||
| let mut bool_task = BoolVcProveTask { | ||
| quant_vc: quant_task, | ||
| vc: res, | ||
| }; | ||
|
|
||
| // Optimizations | ||
| if !options.opt_options.no_boolify || options.opt_options.opt_rel { | ||
| bool_task.remove_parens(); | ||
| } | ||
| if !options.opt_options.no_boolify { | ||
| bool_task.opt_boolify(); | ||
| } | ||
| if options.opt_options.opt_rel { | ||
| bool_task.opt_relational(); | ||
| } | ||
|
|
||
| if options.debug_options.print_theorem { | ||
| bool_task.print_theorem(name); | ||
| } | ||
|
|
||
| // Running the SMT check sat task: translating to Z3, running the solver. | ||
| // This also handles printing the result | ||
| let sat_result = run_smt_check_sat( | ||
| &options, | ||
| &limits_ref, | ||
| &tcx, | ||
| &depgraph, | ||
| &name, | ||
| bool_task, | ||
| server, | ||
| )?; | ||
|
|
||
| // Handle reasons to stop the verifier. | ||
| match sat_result { | ||
| SatResult::Unknown => return Err(CaesarError::Interrupted), | ||
| _ => {} | ||
| } | ||
|
|
||
| // Increment counters. | ||
| match sat_result { | ||
| SatResult::Sat => num_sat += 1, | ||
| SatResult::Unsat | SatResult::Unknown => num_unsat += 1, | ||
| } | ||
| } | ||
|
|
||
| if !options.lsp_options.language_server { | ||
| println!(); | ||
| println!( | ||
| "Found models for {num_sat} (co)procedures, No models for {num_unsat} (co)procedures." | ||
| ); | ||
| } | ||
|
|
||
| Ok(num_unsat == 0) | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think a
BoolVcProveTaskwas intended to be used only in the context of verification (i.e. vc == top/bot), but the operations should be sound here as well, because they're all equivalence transformations (I think).Please make a note of this in the PR description, I'll refactor that at some point :)