Skip to content

Commit 1a17cb3

Browse files
authored
Merge pull request #19 from coord-e/more-annot-2
More annotation syntax
2 parents 0216270 + 80de383 commit 1a17cb3

5 files changed

Lines changed: 126 additions & 3 deletions

File tree

src/annot.rs

Lines changed: 66 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ enum FormulaOrTerm<T> {
196196
Term(chc::Term<T>, chc::Sort),
197197
BinOp(chc::Term<T>, AmbiguousBinOp, chc::Term<T>),
198198
Not(Box<FormulaOrTerm<T>>),
199+
Literal(bool),
199200
}
200201

201202
impl<T> FormulaOrTerm<T> {
@@ -215,6 +216,13 @@ impl<T> FormulaOrTerm<T> {
215216
chc::Formula::Atom(chc::Atom::new(pred.into(), vec![lhs, rhs]))
216217
}
217218
FormulaOrTerm::Not(formula_or_term) => formula_or_term.into_formula()?.not(),
219+
FormulaOrTerm::Literal(b) => {
220+
if b {
221+
chc::Formula::top()
222+
} else {
223+
chc::Formula::bottom()
224+
}
225+
}
218226
};
219227
Some(fo)
220228
}
@@ -233,6 +241,7 @@ impl<T> FormulaOrTerm<T> {
233241
let (t, _) = formula_or_term.into_term()?;
234242
(t.not(), chc::Sort::bool())
235243
}
244+
FormulaOrTerm::Literal(b) => (chc::Term::bool(b), chc::Sort::bool()),
236245
};
237246
Some((t, s))
238247
}
@@ -461,8 +470,8 @@ where
461470
ident.as_str(),
462471
self.formula_existentials.get(ident.name.as_str()),
463472
) {
464-
("true", _) => FormulaOrTerm::Formula(chc::Formula::top()),
465-
("false", _) => FormulaOrTerm::Formula(chc::Formula::bottom()),
473+
("true", _) => FormulaOrTerm::Literal(true),
474+
("false", _) => FormulaOrTerm::Literal(false),
466475
(_, Some(sort)) => {
467476
let var =
468477
chc::Term::FormulaExistentialVar(sort.clone(), ident.name.to_string());
@@ -502,6 +511,31 @@ where
502511
),
503512
_ => unimplemented!(),
504513
},
514+
TokenKind::Lt => {
515+
let (t1, s1) = self
516+
.parse_binop_2()?
517+
.into_term()
518+
.ok_or_else(|| ParseAttrError::unexpected_formula("in box/mut term"))?;
519+
520+
match self.next_token("> or ,")? {
521+
Token {
522+
kind: TokenKind::Gt,
523+
..
524+
} => FormulaOrTerm::Term(chc::Term::box_(t1), chc::Sort::box_(s1)),
525+
Token {
526+
kind: TokenKind::Comma,
527+
..
528+
} => {
529+
let (t2, _s2) = self
530+
.parse_binop_2()?
531+
.into_term()
532+
.ok_or_else(|| ParseAttrError::unexpected_formula("in mut term"))?;
533+
self.expect_next_token(TokenKind::Gt, ">")?;
534+
FormulaOrTerm::Term(chc::Term::mut_(t1, t2), chc::Sort::mut_(s1))
535+
}
536+
t => return Err(ParseAttrError::unexpected_token("> or ,", t.clone())),
537+
}
538+
}
505539
_ => {
506540
return Err(ParseAttrError::unexpected_token(
507541
"identifier, or literal",
@@ -801,6 +835,26 @@ where
801835
fn parse_sort(&mut self) -> Result<chc::Sort> {
802836
let tt = self.next_token_tree("sort")?.clone();
803837
match tt {
838+
TokenTree::Token(
839+
Token {
840+
kind: TokenKind::BinOp(BinOpToken::And),
841+
..
842+
},
843+
_,
844+
) => match self.look_ahead_token(0) {
845+
Some(Token {
846+
kind: TokenKind::Ident(sym, _),
847+
..
848+
}) if sym.as_str() == "mut" => {
849+
self.consume();
850+
let inner_sort = self.parse_sort()?;
851+
Ok(chc::Sort::mut_(inner_sort))
852+
}
853+
_ => {
854+
let inner_sort = self.parse_sort()?;
855+
Ok(chc::Sort::box_(inner_sort))
856+
}
857+
},
804858
TokenTree::Token(
805859
Token {
806860
kind: TokenKind::Ident(sym, _),
@@ -814,7 +868,16 @@ where
814868
"string" => unimplemented!(),
815869
"null" => chc::Sort::null(),
816870
"fn" => unimplemented!(),
817-
_ => unimplemented!(),
871+
name => {
872+
// TODO: ad-hoc
873+
if let Some(i) =
874+
name.strip_prefix('T').and_then(|s| s.parse::<usize>().ok())
875+
{
876+
chc::Sort::param(i)
877+
} else {
878+
unimplemented!();
879+
}
880+
}
818881
};
819882
Ok(sort)
820883
}

tests/ui/fail/annot_box_term.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//@error-in-other-file: Unsat
2+
//@compile-flags: -C debug-assertions=off
3+
4+
#[thrust::sig(fn(x: int) -> {r: Box<int> | r == <x>})]
5+
fn box_create(x: i64) -> Box<i64> {
6+
Box::new(x)
7+
}
8+
9+
#[thrust::requires(b == <v>)]
10+
fn box_consume(b: Box<i64>, v: i64) {
11+
assert!(*b == v);
12+
}
13+
14+
fn main() {
15+
let b = box_create(42);
16+
box_consume(b, 10);
17+
}

tests/ui/fail/annot_mut_term.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//@error-in-other-file: Unsat
2+
3+
#[thrust::requires(true)]
4+
#[thrust::ensures(x == <*x, y>)]
5+
fn f(x: &mut i64, y: i64) {
6+
*x = y;
7+
}
8+
9+
fn main() {
10+
let mut a = 1;
11+
f(&mut a, 2);
12+
assert!(a == 1);
13+
}

tests/ui/pass/annot_box_term.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//@check-pass
2+
//@compile-flags: -C debug-assertions=off
3+
4+
#[thrust::sig(fn(x: int) -> {r: Box<int> | r == <x>})]
5+
fn box_create(x: i64) -> Box<i64> {
6+
Box::new(x)
7+
}
8+
9+
#[thrust::requires(b == <v>)]
10+
fn box_consume(b: Box<i64>, v: i64) {
11+
assert!(*b == v);
12+
}
13+
14+
fn main() {
15+
let b = box_create(42);
16+
box_consume(b, 42);
17+
}

tests/ui/pass/annot_mut_term.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//@check-pass
2+
3+
#[thrust::requires(true)]
4+
#[thrust::ensures(x == <*x, y>)]
5+
fn f(x: &mut i64, y: i64) {
6+
*x = y;
7+
}
8+
9+
fn main() {
10+
let mut a = 1;
11+
f(&mut a, 2);
12+
assert!(a == 2);
13+
}

0 commit comments

Comments
 (0)