Closed sampsyo closed 1 year ago
As we discussed synchronously today, I've mucked things up so that our crate builds. That meant temporarily:
encoded_ops
todo!()
It works! I haven't tried running any tests, because I don't feel qualified to know which tests should be runnable in this semi-broken state. (I could probably figure that out, but I'm going to move on to trying to rewrite the encoded ops stuff instead of spending time on that.)
In the name of expediency—that is, to get something actually working as quickly as possible, so we can iterate on it—I had to change tactics a bit. The original plan had been to port the generation code from Python to Rust, so we could generate S-expressions directly (instead of generating Rust that generates S-expressions). But what I didn't quite realize is that the "source of truth" is in SMT-LIBv2 code already, and that the Python code acts as a translator for that code.
In light of that, I saw two fast routes to getting something working:
easy-smt
SExpr
values instead of strings.I opted for option 2 because getting an S-expression parser going on the Rust side seemed like a big drag. We may want to revisit this later.
Logistically, my goal was to keep the "source of truth" in the original templatized SMT-LIBv2 files—not in the generated Rust code. With that philosophy, if we need to fix a bug in the encoding, we never fix the generated Rust; we fix the original SMT S-expressions (or the Python converter) and then just regenerate the Rust. The goal, then, is to have no (or at least minimal) human massaging after conversion. To that end, I did these things:
encodings
directory).easy-smt
-based generator code instead of the string-based stuff.a64cls32
from cls32
so it has its own file, and I added cl*1
files (even though they are super simple and you could just write them directly in Rust instead).python3 convert.py cls16.smt2 | pbcopy
, for example, and paste this into the corresponding Rust function body.Here are some loose ends to address next:
rbit32
and a64clz32
. Perhaps @mpardeshi has these sitting around?One thing I'm not sure about is: What is the best way to check whether these encodings are working at all? Even if it's not an automatable test, being able to check whether these encodings work in isolation seems really handy… especially if it can happen separately from the rest of the verification machinery.
Less-urgent things that would be good to do but not in this PR include:
SExpr
-construction code could be improved. It doesn't use as many helpers as it could, instead opting to use mostly the low-level utilities.rev1
, the simplest possible thing, and then abandoned it.)Woohoo that was super fast!!!
Here are some quick, minor comments:
rev32
should be in the Slack threadveri_engine/examples
Awesome; thanks! As for testing specifically, I suppose I want to try setting up something (semi-)automated, since I am not very good at getting the details right when manually setting things up for one-off tests… still not 100% sure what that would look like. Maybe running the solver from an isolated Rust test?
Something we could try for testing (that would be good for testing the rules in general):
But, I don't think this needs to happen in this PR.
Other important TODO before this becomes the default: easy-smt
's debugging doesn't list the actual values. We should make sure things like this get displayed in a more useful way:
Assertion list is feasible
LHS and RHS equality condition:
SExpr::List(14853) // <- this should have named values
^ Doing a pass to add ctx.smt.display(...)
calls.
Ok, I think the clz
and ctz
encodings might actually be broken. Investigating!
As discussed on Slack, here's a first attempt to move from rsmt2 to easy-smt. Here are the high-level takeaways:
SExpr
type.I got everything in
solver.rs
converted, including all the SMT generation and the interaction with the solver. This took me about 3 hours to move everything over—almost all of that was replacing calls toformat!
with explicit S-expression construction calls. It's not exactly fun, but it's not exactly hard either.There is more drudgery ahead: the files in
encoded_ops
have a lot of raw SMT strings in them and will be a lot of work to convert.There is a chance I have made a terrible mistake and I should not have tried to do all this annoying conversion at all: instead, we could try to parse the strings we're already generating and turn them into
SExpr
s. Or we could attempt to hackeasy-smt
to allow us to shove strings directly into the solver, which it doesn't currently allow (you have to provide anSExpr
). Both of those seem very reasonable in retrospect, but now I wonder if either of them would be simpler than just forging ahead and finishing the conversion. I'd be interested in others' opinions, given what the code looks like insolver.rs
after the conversion.