123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142(***************************************************************************)(* This file is part of the third-party OCaml library `smtml`. *)(* Copyright (C) 2023-2024 formalsec *)(* *)(* This program is free software: you can redistribute it and/or modify *)(* it under the terms of the GNU General Public License as published by *)(* the Free Software Foundation, either version 3 of the License, or *)(* (at your option) any later version. *)(* *)(* This program is distributed in the hope that it will be useful, *)(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)(* GNU General Public License for more details. *)(* *)(* You should have received a copy of the GNU General Public License *)(* along with this program. If not, see <https://www.gnu.org/licenses/>. *)(***************************************************************************)includeSolver_intflet(let+)of=Option.mapfomoduleBase(M:Mappings_intf.S)=structtypet=M.solvertypesolver=tletsolver_time=ref0.0letsolver_count=ref0letpp_statisticsfmtsolver=M.Solver.pp_statisticsfmtsolverletcreate?params?logic():t=M.Solver.make?params?logic()letinterruptsolver=M.Solver.interruptsolverletclone(solver:t):t=M.Solver.clonesolverletpush(solver:t):unit=M.Solver.pushsolverletpop(solver:t)(lvl:int):unit=M.Solver.popsolverlvlletreset(solver:t):unit=M.Solver.resetsolverletadd(solver:t)(es:Expr.tlist):unit=M.Solver.addsolveresletget_assertions(_solver:t):Expr.tlist=assertfalseletcheck(solver:M.solver)(es:Expr.tlist):satisfiability=solver_count:=!solver_count+1;Utils.run_and_time_call~use:(funtime->solver_time:=!solver_time+.time)(fun()->M.Solver.checksolver~assumptions:es)letget_value(solver:M.solver)(e:Expr.t):Expr.t=matchM.Solver.modelsolverwith|Somem->Expr.make@@Val(M.valueme)|None->Log.err"get_value: Trying to get a value from an unsat solver"letmodel?(symbols:Symbol.tlistoption)(s:M.solver):Model.toption=let+model=M.Solver.modelsinM.values_of_model?symbolsmodelendmoduleMake_batch(Mappings:Mappings_intf.S)=structincludeBase(Mappings)typesolver=Mappings.solvertypet={solver:solver;mutabletop:Expr.tlist;stack:Expr.tlistStack.t}letpp_statisticsfmts=pp_statisticsfmts.solverletcreate?params?logic()={solver=Mappings.Solver.make?params?logic();top=[];stack=Stack.create()}letclone({solver;top;stack}:t):t={solver;top;stack=Stack.copystack}letpush({top;stack;_}:t):unit=Stack.pushtopstackletpop(s:t)(lvl:int):unit=assert(lvl<=Stack.lengths.stack);for_=1tolvldos.top<-Stack.pops.stackdoneletreset(s:t)=Mappings.Solver.resets.solver;Stack.clears.stack;s.top<-[]letadd(s:t)(es:Expr.tlist):unit=s.top<-es@s.topletget_assertions(s:t):Expr.tlist=s.top[@@inline]letcheck(s:t)(es:Expr.tlist):satisfiability=checks.solver(es@s.top)letget_value(solver:t)(e:Expr.t):Expr.t=get_valuesolver.solvereletmodel?(symbols:Symbol.tlistoption)(s:t):Model.toption=model?symbolss.solverletinterrupt{solver;_}=interruptsolverend(* TODO: Our base solver can be incrmental itself? *)moduleBatch(M:Mappings_intf.S):Solver_intf.S=Make_batch(M)moduleCached(M:Mappings_intf.S):sigincludeSolver_intf.SmoduleCache:Cache_intf.Send=structincludeMake_batch(M)moduleCache=Cache.Strongletcache=Cache.create256letcheckses=matchCache.find_optcacheeswith|Someres->res|None->letresult=checksesinCache.addcacheesresult;resultendmoduleIncremental(M:Mappings_intf.S):Solver_intf.S=Base(M)moduleZ3_batch:Solver_intf.S=Batch(Z3_mappings)moduleZ3_incremental:Solver_intf.S=Incremental(Z3_mappings)