Skip to content

Commit 89d9f86

Browse files
committed
Parse existentials
1 parent 323d0e0 commit 89d9f86

2 files changed

Lines changed: 119 additions & 4 deletions

File tree

src/annot.rs

Lines changed: 115 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use rustc_ast::token::{BinOpToken, Delimiter, LitKind, Token, TokenKind};
1212
use rustc_ast::tokenstream::{RefTokenTreeCursor, Spacing, TokenStream, TokenTree};
1313
use rustc_index::IndexVec;
1414
use rustc_span::symbol::Ident;
15+
use std::collections::HashMap;
1516

1617
use crate::chc;
1718
use crate::pretty::PrettyDisplayExt as _;
@@ -185,6 +186,7 @@ impl<T> FormulaOrTerm<T> {
185186
struct Parser<'a, T> {
186187
resolver: T,
187188
cursor: RefTokenTreeCursor<'a>,
189+
formula_existentials: HashMap<String, chc::Sort>,
188190
}
189191

190192
impl<'a, T> Parser<'a, T>
@@ -232,6 +234,15 @@ where
232234
}
233235
}
234236

237+
fn expect_next_ident(&mut self) -> Result<Ident> {
238+
let t = self.next_token("ident")?;
239+
if let Some((ident, _)) = t.ident() {
240+
Ok(ident)
241+
} else {
242+
Err(ParseAttrError::unexpected_token("ident", t.clone()))
243+
}
244+
}
245+
235246
fn consume(&mut self) {
236247
self.cursor.next().unwrap();
237248
}
@@ -296,6 +307,7 @@ where
296307
let mut parser = Parser {
297308
resolver: self.boxed_resolver(),
298309
cursor: s.trees(),
310+
formula_existentials: self.formula_existentials.clone(),
299311
};
300312
let formula_or_term = parser.parse_formula_or_term_or_tuple()?;
301313
parser.end_of_input()?;
@@ -305,9 +317,17 @@ where
305317
};
306318

307319
let formula_or_term = if let Some((ident, _)) = t.ident() {
308-
match ident.as_str() {
309-
"true" => FormulaOrTerm::Formula(chc::Formula::top()),
310-
"false" => FormulaOrTerm::Formula(chc::Formula::bottom()),
320+
match (
321+
ident.as_str(),
322+
self.formula_existentials.get(ident.name.as_str()),
323+
) {
324+
("true", _) => FormulaOrTerm::Formula(chc::Formula::top()),
325+
("false", _) => FormulaOrTerm::Formula(chc::Formula::bottom()),
326+
(_, Some(sort)) => {
327+
let var =
328+
chc::Term::FormulaExistentialVar(sort.clone(), ident.name.to_string());
329+
FormulaOrTerm::Term(var, sort.clone())
330+
}
311331
_ => {
312332
let (v, sort) = self.resolve(ident)?;
313333
FormulaOrTerm::Term(chc::Term::var(v), sort)
@@ -575,8 +595,94 @@ where
575595
Ok(formula_or_term)
576596
}
577597

598+
fn parse_exists(&mut self) -> Result<FormulaOrTerm<T::Output>> {
599+
match self.look_ahead_token(0) {
600+
Some(Token {
601+
kind: TokenKind::Ident(sym, _),
602+
..
603+
}) if sym.as_str() == "exists" => {
604+
self.consume();
605+
let mut vars = Vec::new();
606+
loop {
607+
let ident = self.expect_next_ident()?;
608+
self.expect_next_token(TokenKind::Colon, ":")?;
609+
let sort = self.parse_sort()?;
610+
vars.push((ident.name.to_string(), sort));
611+
match self.next_token(". or ,")? {
612+
Token {
613+
kind: TokenKind::Comma,
614+
..
615+
} => {}
616+
Token {
617+
kind: TokenKind::Dot,
618+
..
619+
} => break,
620+
t => return Err(ParseAttrError::unexpected_token(". or ,", t.clone())),
621+
}
622+
}
623+
self.formula_existentials.extend(vars.iter().cloned());
624+
let formula = self
625+
.parse_formula_or_term()?
626+
.into_formula()
627+
.ok_or_else(|| ParseAttrError::unexpected_term("in exists formula"))?;
628+
for (name, _) in &vars {
629+
self.formula_existentials.remove(name);
630+
}
631+
Ok(FormulaOrTerm::Formula(chc::Formula::exists(vars, formula)))
632+
}
633+
_ => self.parse_binop_5(),
634+
}
635+
}
636+
578637
fn parse_formula_or_term(&mut self) -> Result<FormulaOrTerm<T::Output>> {
579-
self.parse_binop_5()
638+
self.parse_exists()
639+
}
640+
641+
fn parse_sort(&mut self) -> Result<chc::Sort> {
642+
let tt = self.next_token_tree("sort")?.clone();
643+
match tt {
644+
TokenTree::Token(
645+
Token {
646+
kind: TokenKind::Ident(sym, _),
647+
..
648+
},
649+
_,
650+
) => {
651+
let sort = match sym.as_str() {
652+
"bool" => chc::Sort::bool(),
653+
"int" => chc::Sort::int(),
654+
"string" => unimplemented!(),
655+
"null" => chc::Sort::null(),
656+
"fn" => unimplemented!(),
657+
_ => unimplemented!(),
658+
};
659+
Ok(sort)
660+
}
661+
TokenTree::Delimited(_, _, Delimiter::Parenthesis, ts) => {
662+
let mut parser = Parser {
663+
resolver: self.boxed_resolver(),
664+
cursor: ts.trees(),
665+
formula_existentials: self.formula_existentials.clone(),
666+
};
667+
let mut sorts = Vec::new();
668+
loop {
669+
sorts.push(parser.parse_sort()?);
670+
match parser.look_ahead_token(0) {
671+
Some(Token {
672+
kind: TokenKind::Comma,
673+
..
674+
}) => {
675+
parser.consume();
676+
}
677+
None => break,
678+
Some(t) => return Err(ParseAttrError::unexpected_token(",", t.clone())),
679+
}
680+
}
681+
parser.end_of_input()?;
682+
Ok(chc::Sort::tuple(sorts))
683+
}
684+
t => Err(ParseAttrError::unexpected_token_tree("sort", t.clone())),
685+
}
580686
}
581687

582688
fn parse_ty(&mut self) -> Result<rty::Type<T::Output>> {
@@ -662,6 +768,7 @@ where
662768
let mut parser = Parser {
663769
resolver: self.boxed_resolver(),
664770
cursor: ts.trees(),
771+
formula_existentials: self.formula_existentials.clone(),
665772
};
666773
let mut rtys = Vec::new();
667774
loop {
@@ -697,6 +804,7 @@ where
697804
let mut parser = Parser {
698805
resolver: self.boxed_resolver(),
699806
cursor: ts.trees(),
807+
formula_existentials: self.formula_existentials.clone(),
700808
};
701809
let self_ident = if matches!(
702810
parser.look_ahead_token(1),
@@ -720,6 +828,7 @@ where
720828
let mut parser = Parser {
721829
resolver: RefinementResolver::new(self.boxed_resolver()),
722830
cursor: parser.cursor,
831+
formula_existentials: self.formula_existentials.clone(),
723832
};
724833
if let Some(self_ident) = self_ident {
725834
parser.resolver.set_self(self_ident, ty.to_sort());
@@ -859,6 +968,7 @@ where
859968
let mut parser = Parser {
860969
resolver: &self.resolver,
861970
cursor: ts.trees(),
971+
formula_existentials: Default::default(),
862972
};
863973
let rty = parser.parse_rty()?;
864974
parser.end_of_input()?;
@@ -869,6 +979,7 @@ where
869979
let mut parser = Parser {
870980
resolver: &self.resolver,
871981
cursor: ts.trees(),
982+
formula_existentials: Default::default(),
872983
};
873984
let formula = parser.parse_annot_formula()?;
874985
parser.end_of_input()?;

src/chc.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1228,6 +1228,10 @@ impl<V> Formula<V> {
12281228
}
12291229
}
12301230

1231+
pub fn exists(vars: Vec<(String, Sort)>, body: Self) -> Self {
1232+
Formula::Exists(vars, Box::new(body))
1233+
}
1234+
12311235
pub fn subst_var<F, W>(self, f: F) -> Formula<W>
12321236
where
12331237
F: FnMut(V) -> Term<W>,

0 commit comments

Comments
 (0)