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
SMTChecker: Parse invariants from SMT-LIB response #15032
Conversation
921240a
to
e2fb54d
Compare
libsmtutil/CHCSmtLib2Interface.cpp
Outdated
}; | ||
|
||
|
||
#define precondition(CONDITION) if(!(CONDITION)) return {} |
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.
Is there a better for to achieve this?
If I don't what to explicitly write 10 if
checks like this
if (!<condition>)
return {};
Yet, I want to check these conditions, but only bail out on further processing, not throwing an exception.
It feels like there currently isn't a better way than a macro.
b7b26b5
to
e98f8ed
Compare
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.
These are (almost) exclusively stylistic - unfortunately I can't seem to help much with the actual SMT stuff :)
libsmtutil/CHCSmtLib2Interface.cpp
Outdated
CHCSmtLib2Interface const& m_chcInterface; | ||
std::map<std::string, SortPointer> knownVariables; | ||
|
||
bool isNumber(std::string const& _expr) |
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.
Is this supposed to handle only positive numbers?
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.
Good question. It turns out yes, because in SMT-LIB, unary minus is an operator, so negative number should be represented as (- <number>)
.
I'll try invariant with a negative number, to check this case.
libsmtutil/CHCSmtLib2Interface.cpp
Outdated
else if (isNumber(_atom)) | ||
return smtutil::Expression(_atom, {}, SortProvider::sintSort); | ||
else if (knownVariables.find(_atom) != knownVariables.end()) | ||
return smtutil::Expression(_atom, {}, knownVariables.at(_atom)); |
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.
return smtutil::Expression(_atom, {}, knownVariables.at(_atom)); | |
return smtutil::Expression(_atom, {}, knownVariables[_atom]); |
libsmtutil/CHCSmtLib2Interface.cpp
Outdated
std::vector<std::pair<std::string, SortPointer>> boundVariables; | ||
for (auto const& sortedVar: varList) | ||
{ | ||
solAssert(!isAtom(sortedVar)); |
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.
Just curious - why do you sometimes use smtAssert()
, and other times solAssert()
?
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 don't know :)
I've changed everything to smtAssert
.
switch (_sort.kind) | ||
if (!m_sortNames.count(_sort)) | ||
m_sortNames[_sort] = toSmtLibSortInternal(_sort); | ||
return m_sortNames.at(_sort); |
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.
return m_sortNames.at(_sort); | |
return m_sortNames.at[_sort]; |
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.
What is it about at
that you don't like?
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.
at()
throws an exception if the element is not present in the container, but you already check for that in the if
above, so it's just unnecessary overhead.
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.
Well, for map
operator []
default-initializes a new value and insert the new pair into the map, if the key was not present. So I think it has even more overhead than at
.
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.
Sure, but not in this case, because you've already checked for the existence of the element. It's not a big deal regardless, so no need to make this change.
The failing tests have been fixed by the way, you just need to rebase. |
4866974
to
5df3915
Compare
5df3915
to
271bb4f
Compare
@nikola-matic , @pgebal , I fixed the code according to your suggestions, or at least commented on your comments :) |
@blishko the code looks good to me |
libsmtutil/CHCSmtLib2Interface.cpp
Outdated
if (typeArgs.size() == 4 && typeArgs[0].toString() == "_") | ||
{ | ||
if (typeArgs[1].toString() == "extract") | ||
{ | ||
return smtutil::Expression( | ||
"extract", | ||
{toSMTUtilExpression(typeArgs[2]), toSMTUtilExpression(typeArgs[3])}, | ||
SortProvider::bitVectorSort // TODO: Compute bit size properly? | ||
); | ||
} | ||
} |
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.
if (typeArgs.size() == 4 && typeArgs[0].toString() == "_") | |
{ | |
if (typeArgs[1].toString() == "extract") | |
{ | |
return smtutil::Expression( | |
"extract", | |
{toSMTUtilExpression(typeArgs[2]), toSMTUtilExpression(typeArgs[3])}, | |
SortProvider::bitVectorSort // TODO: Compute bit size properly? | |
); | |
} | |
} | |
if (typeArgs.size() == 4 && typeArgs[0].toString() == "_" && typeArgs[1].toString() == "extract") | |
return smtutil::Expression( | |
"extract", | |
{toSMTUtilExpression(typeArgs[2]), toSMTUtilExpression(typeArgs[3])}, | |
SortProvider::bitVectorSort // TODO: Compute bit size properly? | |
); |
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.
Eh, there are a few tiny style issues (mostly around overuse of scoping braces with conditional statements), but it's our fault for not having a sane formatting check, so merge away :)
@@ -223,3 +226,282 @@ std::string CHCSmtLib2Interface::createHeaderAndDeclarations() { | |||
std::string CHCSmtLib2Interface::createQueryAssertion(std::string name) { | |||
return "(assert\n(forall " + forall() + "\n" + "(=> " + name + " false)))"; | |||
} | |||
|
|||
class SMTLibTranslationContext |
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.
Uh, everything in the class has an extra indent by the way.
Parser code was originally written by @chriseth for solsmt, an SMT solver developed internally for Solidity
We add support for parsing CHC solver response containing a model, i.e., invariants. We utilise our SMT parser to build S-expression representation which we then interpret using the context we remembered while building the query. We have to rememeber all predicates declared to the solver, and, consequently, all sorts we have declared to the solver.
271bb4f
to
048ce0b
Compare
This PR adds initial support for parsing invariants, computed by CHC solver, in SMT-LIB format.
This is done in a few separate steps (found in individual commits):
Expression
representation of the invariants.Note: This is only initial support and will require more iterations as we add more tests.