-
Notifications
You must be signed in to change notification settings - Fork 1
Insert raw definition into .smt2 file with #![raw_definie()] attribute #21
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
base: main
Are you sure you want to change the base?
Changes from all commits
fbed2dc
a0863f1
3f3740d
155dc27
be16c1f
e050fc3
547dd78
2529cdb
afcd68c
b222ede
44a97da
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,12 +2,14 @@ | |
|
|
||
| use std::collections::HashSet; | ||
|
|
||
| use rustc_hir::def_id::CRATE_DEF_ID; | ||
| use rustc_middle::ty::{self as mir_ty, TyCtxt}; | ||
| use rustc_span::def_id::{DefId, LocalDefId}; | ||
|
|
||
| use crate::analyze; | ||
| use crate::chc; | ||
| use crate::rty::{self, ClauseBuilderExt as _}; | ||
| use crate::annot; | ||
|
|
||
| /// An implementation of local crate analysis. | ||
| /// | ||
|
|
@@ -26,6 +28,21 @@ pub struct Analyzer<'tcx, 'ctx> { | |
| } | ||
|
|
||
| impl<'tcx, 'ctx> Analyzer<'tcx, 'ctx> { | ||
| fn analyze_raw_define_annot(&mut self) { | ||
| for attrs in self.tcx.get_attrs_by_path( | ||
| CRATE_DEF_ID.to_def_id(), | ||
| &analyze::annot::raw_define_path(), | ||
| ) { | ||
| let ts = analyze::annot::extract_annot_tokens(attrs.clone()); | ||
| let parser = annot::AnnotParser::new( | ||
| // TODO: this resolver is not actually used. | ||
| analyze::annot::ParamResolver::default() | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think it needs to be implemented in AnnotParser. How about extracting the string from the annotation in a method within crate_::Analyzer? |
||
| ); | ||
| let raw_definition = parser.parse_raw_definition(ts).unwrap(); | ||
| self.ctx.system.borrow_mut().push_raw_definition(raw_definition); | ||
| } | ||
| } | ||
|
|
||
| fn refine_local_defs(&mut self) { | ||
| for local_def_id in self.tcx.mir_keys(()) { | ||
| if self.tcx.def_kind(*local_def_id).is_fn_like() { | ||
|
|
@@ -187,6 +204,7 @@ impl<'tcx, 'ctx> Analyzer<'tcx, 'ctx> { | |
| let span = tracing::debug_span!("crate", krate = %self.tcx.crate_name(rustc_span::def_id::LOCAL_CRATE)); | ||
| let _guard = span.enter(); | ||
|
|
||
| self.analyze_raw_define_annot(); | ||
| self.refine_local_defs(); | ||
| self.analyze_local_defs(); | ||
| self.assert_callable_entry(); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -370,6 +370,30 @@ impl<'ctx, 'a> Clause<'ctx, 'a> { | |
| } | ||
| } | ||
|
|
||
| /// A wrapper around a [`chc::RawDefinition`] that provides a [`std::fmt::Display`] implementation in SMT-LIB2 format. | ||
| #[derive(Debug, Clone)] | ||
| pub struct RawDefinition<'a> { | ||
| inner: &'a chc::RawDefinition, | ||
| } | ||
|
|
||
| impl<'a> std::fmt::Display for RawDefinition<'a> { | ||
| fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
| write!( | ||
| f, | ||
| "{}", | ||
| self.inner.definition, | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| impl<'a> RawDefinition<'a> { | ||
| pub fn new(inner: &'a chc::RawDefinition) -> Self { | ||
| Self { | ||
| inner | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /// A wrapper around a [`chc::DatatypeSelector`] that provides a [`std::fmt::Display`] implementation in SMT-LIB2 format. | ||
| #[derive(Debug, Clone)] | ||
| pub struct DatatypeSelector<'ctx, 'a> { | ||
|
|
@@ -555,6 +579,11 @@ impl<'a> std::fmt::Display for System<'a> { | |
| fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
| writeln!(f, "(set-logic HORN)\n")?; | ||
|
|
||
| // insert definition from #![thrust::define_chc()] here | ||
| for raw_def in self.ctx.raw_definitions() { | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How about just using |
||
| writeln!(f, "{}\n", RawDefinition::new(raw_def))?; | ||
| } | ||
|
|
||
| writeln!(f, "{}\n", Datatypes::new(&self.ctx, self.ctx.datatypes()))?; | ||
| for datatype in self.ctx.datatypes() { | ||
| writeln!(f, "{}", DatatypeDiscrFun::new(&self.ctx, datatype))?; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| //@error-in-other-file: UnexpectedToken | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How can I test that the Thrust panics with a specific error message? I tried using
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think testing panic messages is not possible with the current testing framework (ui_test https://docs.rs/ui_test/). However, I don't think we want tests for panicking cases anyway; it would be beneficial if we supported reporting rustc diagnostics for parse errors, but it's out of scope for now. |
||
| //@compile-flags: -Adead_code -C debug-assertions=off | ||
|
|
||
| // Insert definitions written in SMT-LIB2 format into .smt file directly. | ||
| // This feature is intended for debug or experiment purpose. | ||
| #![feature(custom_inner_attributes)] | ||
| #![thrust::raw_define(true)] // argument must be single string literal | ||
|
|
||
| #[thrust::requires(true)] | ||
| #[thrust::ensures(result == 2 * x)] | ||
| // #[thrust::ensures(is_double(x, result))] | ||
| fn double(x: i64) -> i64 { | ||
| x + x | ||
| } | ||
|
|
||
| fn main() { | ||
| let a = 3; | ||
| assert!(double(a) == 6); | ||
| // assert!(is_double(a, double(a))); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| //@error-in-other-file: invalid attribute | ||
| //@compile-flags: -Adead_code -C debug-assertions=off | ||
|
|
||
| // Insert definitions written in SMT-LIB2 format into .smt file directly. | ||
| // This feature is intended for debug or experiment purpose. | ||
| #![feature(custom_inner_attributes)] | ||
| #![thrust::raw_define] // argument must be single string literal | ||
|
|
||
| #[thrust::requires(true)] | ||
| #[thrust::ensures(result == 2 * x)] | ||
| // #[thrust::ensures(is_double(x, result))] | ||
| fn double(x: i64) -> i64 { | ||
| x + x | ||
| } | ||
|
|
||
| fn main() { | ||
| let a = 3; | ||
| assert!(double(a) == 6); | ||
| // assert!(is_double(a, double(a))); | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,25 @@ | ||||||
| //@check-pass | ||||||
| //@compile-flags: -Adead_code -C debug-assertions=off | ||||||
|
|
||||||
| // Insert definitions written in SMT-LIB2 format into .smt file directly. | ||||||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit
Suggested change
|
||||||
| // This feature is intended for debug or experiment purpose. | ||||||
| #![feature(custom_inner_attributes)] | ||||||
| #![thrust::raw_define("(define-fun is_double ((x Int) (doubled_x Int)) Bool | ||||||
| (= | ||||||
| (* x 2) | ||||||
| doubled_x | ||||||
| ) | ||||||
| )")] | ||||||
|
|
||||||
| #[thrust::requires(true)] | ||||||
| #[thrust::ensures(result == 2 * x)] | ||||||
| // #[thrust::ensures(is_double(x, result))] | ||||||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you plan to uncomment this in a future PR, please add a note about it in the comments. |
||||||
| fn double(x: i64) -> i64 { | ||||||
| x + x | ||||||
| } | ||||||
|
|
||||||
| fn main() { | ||||||
| let a = 3; | ||||||
| assert!(double(a) == 6); | ||||||
| // assert!(is_double(a, double(a))); | ||||||
| } | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| //@check-pass | ||
| //@compile-flags: -Adead_code -C debug-assertions=off | ||
|
|
||
| // Insert definitions written in SMT-LIB2 format into .smt file directly. | ||
| // This feature is intended for debug or experiment purpose. | ||
| #![feature(custom_inner_attributes)] | ||
| #![thrust::raw_define("(define-fun is_double ((x Int) (doubled_x Int)) Bool | ||
| (= | ||
| (* x 2) | ||
| doubled_x | ||
| ) | ||
| )")] | ||
|
|
||
| // multiple raw definitions can be inserted. | ||
| #![thrust::raw_define("(define-fun is_triple ((x Int) (tripled_x Int)) Bool | ||
| (= | ||
| (* x 3) | ||
| tripled_x | ||
| ) | ||
| )")] | ||
|
|
||
| #[thrust::requires(true)] | ||
| #[thrust::ensures(result == 2 * x)] | ||
| // #[thrust::ensures(is_double(x, result))] | ||
| fn double(x: i64) -> i64 { | ||
| x + x | ||
| } | ||
|
|
||
| fn main() { | ||
| let a = 3; | ||
| assert!(double(a) == 6); | ||
| // assert!(is_double(a, double(a))); | ||
| } |
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 this feature could also be used to insert non-definitions into the resulting SMT-LIB2, such as set-option or set-info, so how about naming it something like thrust::raw_command or just thrust::raw? The same applies to RawDefinition and related data structures/functions.