liquid-fixpoint 0.2.3.2 → 0.3.0.0
raw patch · 39 files changed
+3326/−1599 lines, 39 filesdep +tastydep +tasty-hunitdep +tasty-rerundep ~basesetup-changedPVP ok
version bump matches the API change (PVP)
Dependencies added: tasty, tasty-hunit, tasty-rerun
Dependency ranges changed: base
API changes (from Hackage documentation)
- Language.Fixpoint.Interface: checkValid :: Hashable a => a -> [(Symbol, Sort)] -> Pred -> IO (FixResult a)
- Language.Fixpoint.Interface: solveFile :: Config -> IO ExitCode
- Language.Fixpoint.Names: intKvar :: Integer -> Symbol
- Language.Fixpoint.Parse: instance Inputable [Refa]
- Language.Fixpoint.Types: RConc :: !Pred -> Refa
- Language.Fixpoint.Types: RKvar :: !Symbol -> !Subst -> Refa
- Language.Fixpoint.Types: data Refa
- Language.Fixpoint.Types: data Subst
- Language.Fixpoint.Types: instance Constructor C1_1Refa
- Language.Fixpoint.Types: instance Fixpoint FEnv
- Language.Fixpoint.Types: isNonTrivialSortedReft :: SortedReft -> Bool
- Language.Fixpoint.Types: isTautoReft :: Reft -> Bool
- Language.Fixpoint.Types: mapSEnv :: (a1 -> a) -> SEnv a1 -> SEnv a
- Language.Fixpoint.Types: rawBindEnv :: [(BindId, Symbol, SortedReft)] -> BindEnv
- Language.Fixpoint.Types: reftKVars :: Reft -> [Symbol]
- Language.Fixpoint.Types: zero :: Expr
+ Language.Fixpoint.Config: eliminate :: Config -> Bool
+ Language.Fixpoint.Config: getOpts :: IO Config
+ Language.Fixpoint.Config: srcFile :: Config -> FilePath
+ Language.Fixpoint.Errors: exit :: a -> IO a -> IO a
+ Language.Fixpoint.Interface: parseFInfo :: [FilePath] -> IO (FInfo a)
+ Language.Fixpoint.Interface: solveFQ :: Config -> IO ExitCode
+ Language.Fixpoint.Misc: folds :: (a -> b -> (c, a)) -> a -> [b] -> ([c], a)
+ Language.Fixpoint.Misc: groupBase :: (Hashable k, Eq k) => HashMap k [a] -> [(k, a)] -> HashMap k [a]
+ Language.Fixpoint.Misc: mkGraph :: (Eq a, Eq b, Hashable a, Hashable b) => [(a, b)] -> HashMap a (HashSet b)
+ Language.Fixpoint.Misc: safeLookup :: (Hashable k, Eq k) => [Char] -> k -> HashMap k a -> a
+ Language.Fixpoint.Misc: safeUncons :: String -> ListNE a -> (a, [a])
+ Language.Fixpoint.Misc: safeUnsnoc :: String -> ListNE a -> ([a], a)
+ Language.Fixpoint.Misc: type ListNE a = [a]
+ Language.Fixpoint.Names: consName :: Symbol
+ Language.Fixpoint.Names: dropModuleUnique :: Symbol -> Symbol
+ Language.Fixpoint.Names: existSymbol :: Symbol -> Integer -> Symbol
+ Language.Fixpoint.Names: nilName :: Symbol
+ Language.Fixpoint.Parse: instance Inputable Refa
+ Language.Fixpoint.PrettyPrint: instance (PPrint a, PPrint b) => PPrint (HashMap a b)
+ Language.Fixpoint.PrettyPrint: instance PPrint Bool
+ Language.Fixpoint.PrettyPrint: instance PPrint KVar
+ Language.Fixpoint.PrettyPrint: tracepp :: PPrint a => String -> a -> a
+ Language.Fixpoint.SmtLib2: smtAssert :: Context -> Pred -> IO ()
+ Language.Fixpoint.SmtLib2: smtBracket :: Context -> IO a -> IO a
+ Language.Fixpoint.SmtLib2: smtCheckUnsat :: Context -> IO Bool
+ Language.Fixpoint.SmtLib2: smtDecl :: Context -> Symbol -> Sort -> IO ()
+ Language.Fixpoint.SmtLib2: smtDistinct :: Context -> [Expr] -> IO ()
+ Language.Fixpoint.Solver.Deps: Deps :: ![KVar] -> ![KVar] -> Deps
+ Language.Fixpoint.Solver.Deps: data Deps
+ Language.Fixpoint.Solver.Deps: depCuts :: Deps -> ![KVar]
+ Language.Fixpoint.Solver.Deps: depNonCuts :: Deps -> ![KVar]
+ Language.Fixpoint.Solver.Deps: deps :: FInfo a -> Deps
+ Language.Fixpoint.Solver.Deps: instance Eq Deps
+ Language.Fixpoint.Solver.Deps: instance Ord Deps
+ Language.Fixpoint.Solver.Deps: instance Show Deps
+ Language.Fixpoint.Solver.Deps: lhsKVars :: BindEnv -> SubC a -> [KVar]
+ Language.Fixpoint.Solver.Deps: rhsKVars :: SubC a -> [KVar]
+ Language.Fixpoint.Solver.Deps: solve :: Config -> FInfo a -> IO (FixResult a)
+ Language.Fixpoint.Solver.Eliminate: eliminateAll :: FInfo a -> FInfo a
+ Language.Fixpoint.Solver.Eliminate: instance Elimable (FInfo a)
+ Language.Fixpoint.Solver.Eliminate: instance Elimable (SubC a)
+ Language.Fixpoint.Solver.Eliminate: instance Elimable BindEnv
+ Language.Fixpoint.Solver.Eliminate: instance Elimable Reft
+ Language.Fixpoint.Solver.Eliminate: instance Elimable SortedReft
+ Language.Fixpoint.Solver.Monad: filterValid :: Pred -> Cand a -> SolveM [a]
+ Language.Fixpoint.Solver.Monad: getBinds :: SolveM BindEnv
+ Language.Fixpoint.Solver.Monad: runSolverM :: Config -> FInfo b -> SolveM a -> IO a
+ Language.Fixpoint.Solver.Monad: tickIter :: SolveM Int
+ Language.Fixpoint.Solver.Monad: type SolveM = StateT SolverState IO
+ Language.Fixpoint.Solver.Solution: EQL :: !Qualifier -> !Pred -> ![Expr] -> EQual
+ Language.Fixpoint.Solver.Solution: apply :: Solvable a => Solution -> a -> Pred
+ Language.Fixpoint.Solver.Solution: class Solvable a
+ Language.Fixpoint.Solver.Solution: data EQual
+ Language.Fixpoint.Solver.Solution: eqArgs :: EQual -> ![Expr]
+ Language.Fixpoint.Solver.Solution: eqPred :: EQual -> !Pred
+ Language.Fixpoint.Solver.Solution: eqQual :: EQual -> !Qualifier
+ Language.Fixpoint.Solver.Solution: init :: Config -> FInfo a -> Solution
+ Language.Fixpoint.Solver.Solution: instance Eq EQual
+ Language.Fixpoint.Solver.Solution: instance Ord EQual
+ Language.Fixpoint.Solver.Solution: instance PPrint EQual
+ Language.Fixpoint.Solver.Solution: instance Show EQual
+ Language.Fixpoint.Solver.Solution: instance Solvable (KVar, Subst)
+ Language.Fixpoint.Solver.Solution: instance Solvable (Symbol, SortedReft)
+ Language.Fixpoint.Solver.Solution: instance Solvable EQual
+ Language.Fixpoint.Solver.Solution: instance Solvable KVar
+ Language.Fixpoint.Solver.Solution: instance Solvable Pred
+ Language.Fixpoint.Solver.Solution: instance Solvable Refa
+ Language.Fixpoint.Solver.Solution: instance Solvable Reft
+ Language.Fixpoint.Solver.Solution: instance Solvable SortedReft
+ Language.Fixpoint.Solver.Solution: instance Solvable a => Solvable [a]
+ Language.Fixpoint.Solver.Solution: lookup :: Solution -> KVar -> KBind
+ Language.Fixpoint.Solver.Solution: type Cand a = [(Pred, a)]
+ Language.Fixpoint.Solver.Solution: type Solution = Sol KBind
+ Language.Fixpoint.Solver.Solution: update :: Solution -> [KVar] -> [(KVar, EQual)] -> (Bool, Solution)
+ Language.Fixpoint.Solver.Solve: solve :: Config -> FInfo a -> IO (Result a)
+ Language.Fixpoint.Solver.Validate: symbolSorts :: FInfo a -> Either Error [(Symbol, Sort)]
+ Language.Fixpoint.Solver.Validate: validate :: Config -> FInfo a -> Either Error (FInfo a)
+ Language.Fixpoint.Solver.Worklist: data Worklist a
+ Language.Fixpoint.Solver.Worklist: init :: Config -> FInfo a -> Worklist a
+ Language.Fixpoint.Solver.Worklist: instance PPrint (Worklist a)
+ Language.Fixpoint.Solver.Worklist: pop :: Worklist a -> Maybe (SubC a, Worklist a)
+ Language.Fixpoint.Solver.Worklist: push :: SubC a -> Worklist a -> Worklist a
+ Language.Fixpoint.Sort: apply :: TVSubst -> Sort -> Sort
+ Language.Fixpoint.Sort: data TVSubst
+ Language.Fixpoint.Sort: unify :: Sort -> Sort -> Maybe TVSubst
+ Language.Fixpoint.Types: KV :: Symbol -> KVar
+ Language.Fixpoint.Types: PKVar :: !KVar -> !Subst -> Pred
+ Language.Fixpoint.Types: Refa :: Pred -> Refa
+ Language.Fixpoint.Types: Su :: [(Symbol, Expr)] -> Subst
+ Language.Fixpoint.Types: WfC :: !IBindEnv -> !SortedReft -> !(Maybe Integer) -> !a -> WfC a
+ Language.Fixpoint.Types: bindEnvFromList :: [(BindId, Symbol, SortedReft)] -> BindEnv
+ Language.Fixpoint.Types: bindEnvToList :: BindEnv -> [(BindId, Symbol, SortedReft)]
+ Language.Fixpoint.Types: conjuncts :: Pred -> [Pred]
+ Language.Fixpoint.Types: elemsIBindEnv :: IBindEnv -> [BindId]
+ Language.Fixpoint.Types: envCs :: BindEnv -> IBindEnv -> [(Symbol, SortedReft)]
+ Language.Fixpoint.Types: functionSort :: Sort -> Maybe (Int, [Sort], Sort)
+ Language.Fixpoint.Types: instance Constructor C1_0KVar
+ Language.Fixpoint.Types: instance Constructor C1_11Pred
+ Language.Fixpoint.Types: instance Data KVar
+ Language.Fixpoint.Types: instance Datatype D1KVar
+ Language.Fixpoint.Types: instance Eq KVar
+ Language.Fixpoint.Types: instance Fixpoint KVar
+ Language.Fixpoint.Types: instance Generic KVar
+ Language.Fixpoint.Types: instance Hashable Bop
+ Language.Fixpoint.Types: instance Hashable Brel
+ Language.Fixpoint.Types: instance Hashable Constant
+ Language.Fixpoint.Types: instance Hashable Expr
+ Language.Fixpoint.Types: instance Hashable KVar
+ Language.Fixpoint.Types: instance Hashable Pred
+ Language.Fixpoint.Types: instance Hashable Subst
+ Language.Fixpoint.Types: instance Hashable SymConst
+ Language.Fixpoint.Types: instance IsString KVar
+ Language.Fixpoint.Types: instance Monoid (FInfo a)
+ Language.Fixpoint.Types: instance Monoid (SEnv a)
+ Language.Fixpoint.Types: instance Monoid BindEnv
+ Language.Fixpoint.Types: instance Monoid Kuts
+ Language.Fixpoint.Types: instance Monoid Refa
+ Language.Fixpoint.Types: instance Ord KVar
+ Language.Fixpoint.Types: instance Selector S1_0_0KVar
+ Language.Fixpoint.Types: instance Selector S1_0_0Refa
+ Language.Fixpoint.Types: instance Selector S1_0_2Located
+ Language.Fixpoint.Types: instance Show (FInfo a)
+ Language.Fixpoint.Types: instance Show (WfC a)
+ Language.Fixpoint.Types: instance Show BindEnv
+ Language.Fixpoint.Types: instance Show KVar
+ Language.Fixpoint.Types: instance Show Kuts
+ Language.Fixpoint.Types: instance Symbolic SymConst
+ Language.Fixpoint.Types: instance Typeable KVar
+ Language.Fixpoint.Types: isEmptySubst :: Subst -> Bool
+ Language.Fixpoint.Types: isFAppTyTC :: FTycon -> Bool
+ Language.Fixpoint.Types: isListTC :: FTycon -> Bool
+ Language.Fixpoint.Types: isNonTrivial :: Reftable r => r -> Bool
+ Language.Fixpoint.Types: ksVars :: Kuts -> HashSet KVar
+ Language.Fixpoint.Types: kv :: KVar -> Symbol
+ Language.Fixpoint.Types: listFTyCon :: FTycon
+ Language.Fixpoint.Types: locE :: Located a -> !SourcePos
+ Language.Fixpoint.Types: lookupBindEnv :: BindId -> BindEnv -> (Symbol, SortedReft)
+ Language.Fixpoint.Types: mapPredReft :: (Pred -> Pred) -> Reft -> Reft
+ Language.Fixpoint.Types: newtype KVar
+ Language.Fixpoint.Types: newtype Refa
+ Language.Fixpoint.Types: newtype Subst
+ Language.Fixpoint.Types: raPred :: Refa -> Pred
+ Language.Fixpoint.Types: refa :: [Pred] -> Refa
+ Language.Fixpoint.Types: reft :: Symbol -> Pred -> Reft
+ Language.Fixpoint.Types: reftBind :: Reft -> Symbol
+ Language.Fixpoint.Types: reftPred :: Reft -> Pred
+ Language.Fixpoint.Types: senv :: SubC a -> IBindEnv
+ Language.Fixpoint.Types: sgrd :: SubC a -> Pred
+ Language.Fixpoint.Types: slhs :: SubC a -> SortedReft
+ Language.Fixpoint.Types: srhs :: SubC a -> SortedReft
+ Language.Fixpoint.Types: strSort :: Sort
+ Language.Fixpoint.Types: type BindMap a = HashMap BindId a
+ Language.Fixpoint.Types: type Result a = (FixResult (SubC a), HashMap KVar Pred)
+ Language.Fixpoint.Types: unionIBindEnv :: IBindEnv -> IBindEnv -> IBindEnv
+ Language.Fixpoint.Types: vv_ :: Symbol
+ Language.Fixpoint.Types: wenv :: WfC a -> !IBindEnv
+ Language.Fixpoint.Types: wid :: WfC a -> !(Maybe Integer)
+ Language.Fixpoint.Types: winfo :: WfC a -> !a
+ Language.Fixpoint.Types: wrft :: WfC a -> !SortedReft
+ Language.Fixpoint.Visitor: envKVars :: BindEnv -> SubC a -> [KVar]
+ Language.Fixpoint.Visitor: foldSort :: (a -> Sort -> a) -> a -> Sort -> a
+ Language.Fixpoint.Visitor: kvars :: Visitable t => t -> [KVar]
+ Language.Fixpoint.Visitor: mapKVars :: Visitable t => (KVar -> Maybe Pred) -> t -> t
+ Language.Fixpoint.Visitor: mapSort :: (Sort -> Sort) -> Sort -> Sort
- Language.Fixpoint.Config: Config :: FilePath -> FilePath -> SMTSolver -> GenQualifierSort -> UeqAllSorts -> Bool -> Bool -> Config
+ Language.Fixpoint.Config: Config :: FilePath -> FilePath -> FilePath -> SMTSolver -> GenQualifierSort -> UeqAllSorts -> Bool -> Bool -> Bool -> Config
- Language.Fixpoint.Interface: resultExit :: FixResult t -> ExitCode
+ Language.Fixpoint.Interface: resultExit :: FixResult a -> ExitCode
- Language.Fixpoint.Interface: solve :: Config -> FilePath -> [FilePath] -> FInfo a -> IO (FixResult (SubC a), HashMap Symbol Pred)
+ Language.Fixpoint.Interface: solve :: Config -> FInfo a -> IO (Result a)
- Language.Fixpoint.Misc: safeHead :: [Char] -> [t] -> t
+ Language.Fixpoint.Misc: safeHead :: String -> ListNE a -> a
- Language.Fixpoint.Misc: safeInit :: [Char] -> [a] -> [a]
+ Language.Fixpoint.Misc: safeInit :: String -> ListNE a -> [a]
- Language.Fixpoint.Misc: safeLast :: [Char] -> [a] -> a
+ Language.Fixpoint.Misc: safeLast :: String -> ListNE a -> a
- Language.Fixpoint.Parse: class Inputable a where rr' = \ _ -> rr rr = rr' ""
+ Language.Fixpoint.Parse: class Inputable a where rr' _ = rr rr = rr' ""
- Language.Fixpoint.Parse: refBindP :: Parser Symbol -> Parser [Refa] -> Parser (Reft -> a) -> Parser a
+ Language.Fixpoint.Parse: refBindP :: Parser Symbol -> Parser Refa -> Parser (Reft -> a) -> Parser a
- Language.Fixpoint.Parse: refDefP :: Symbol -> Parser [Refa] -> Parser (Reft -> a) -> Parser a
+ Language.Fixpoint.Parse: refDefP :: Symbol -> Parser Refa -> Parser (Reft -> a) -> Parser a
- Language.Fixpoint.SmtLib2: makeContext :: SMTSolver -> IO Context
+ Language.Fixpoint.SmtLib2: makeContext :: SMTSolver -> FilePath -> IO Context
- Language.Fixpoint.Types: KS :: (HashSet Symbol) -> Kuts
+ Language.Fixpoint.Types: KS :: HashSet KVar -> Kuts
- Language.Fixpoint.Types: Kut :: Symbol -> Def a
+ Language.Fixpoint.Types: Kut :: KVar -> Def a
- Language.Fixpoint.Types: Loc :: !SourcePos -> a -> Located a
+ Language.Fixpoint.Types: Loc :: !SourcePos -> !SourcePos -> a -> Located a
- Language.Fixpoint.Types: Reft :: (Symbol, [Refa]) -> Reft
+ Language.Fixpoint.Types: Reft :: (Symbol, Refa) -> Reft
- Language.Fixpoint.Types: fTyconSymbol :: FTycon -> LocSymbol
+ Language.Fixpoint.Types: fTyconSymbol :: FTycon -> Located Symbol
- Language.Fixpoint.Types: intKvar :: Integer -> Symbol
+ Language.Fixpoint.Types: intKvar :: Integer -> KVar
- Language.Fixpoint.Types: ksUnion :: [Symbol] -> Kuts -> Kuts
+ Language.Fixpoint.Types: ksUnion :: [KVar] -> Kuts -> Kuts
- Language.Fixpoint.Types: removeLhsKvars :: SubC a -> [Symbol] -> SubC a
+ Language.Fixpoint.Types: removeLhsKvars :: t -> t1 -> t2
- Language.Fixpoint.Types: sortSubst :: (HashMap Symbol Sort) -> Sort -> Sort
+ Language.Fixpoint.Types: sortSubst :: HashMap Symbol Sort -> Sort -> Sort
- Language.Fixpoint.Types: substfExcept :: (Symbol -> Expr) -> [Symbol] -> (Symbol -> Expr)
+ Language.Fixpoint.Types: substfExcept :: (Symbol -> Expr) -> [Symbol] -> Symbol -> Expr
- Language.Fixpoint.Types: trueSubCKvar :: Symbol -> a -> [SubC a]
+ Language.Fixpoint.Types: trueSubCKvar :: KVar -> a -> [SubC a]
- Language.Fixpoint.Types: type FixSolution = HashMap Symbol Pred
+ Language.Fixpoint.Types: type FixSolution = HashMap KVar Pred
Files
- Fixpoint.hs +8/−70
- Setup.hs +1/−1
- external/fixpoint/ast.ml +88/−28
- external/fixpoint/ast.mli +56/−57
- external/fixpoint/fixConstraint.ml +136/−131
- external/fixpoint/fixLex.mll +2/−1
- external/fixpoint/fixParse.mly +10/−5
- external/fixpoint/fixpoint.native-i386-linux binary
- external/fixpoint/fixpoint.native-i686-w64-mingw32 too large to diff
- external/fixpoint/fixpoint.native-x86_64-darwin too large to diff
- external/fixpoint/fixpoint.native-x86_64-linux too large to diff
- external/fixpoint/predAbs.ml +243/−243
- external/fixpoint/qualifier.ml +96/−97
- external/fixpoint/smtLIB2.ml +103/−103
- external/fixpoint/smtZ3.ml +14/−14
- external/fixpoint/smtZ3.nomem.ml +14/−14
- external/fixpoint/tpGen.ml +158/−147
- external/ocamlgraph/src/version.ml +1/−1
- liquid-fixpoint.cabal +28/−22
- src/Language/Fixpoint/Config.hs +45/−9
- src/Language/Fixpoint/Errors.hs +11/−5
- src/Language/Fixpoint/Files.hs +6/−4
- src/Language/Fixpoint/Interface.hs +126/−60
- src/Language/Fixpoint/Misc.hs +41/−9
- src/Language/Fixpoint/Names.hs +32/−14
- src/Language/Fixpoint/Parse.hs +148/−74
- src/Language/Fixpoint/PrettyPrint.hs +27/−10
- src/Language/Fixpoint/SmtLib2.hs +84/−33
- src/Language/Fixpoint/Solver/Deps.hs +96/−0
- src/Language/Fixpoint/Solver/Eliminate.hs +126/−0
- src/Language/Fixpoint/Solver/Monad.hs +103/−0
- src/Language/Fixpoint/Solver/Solution.hs +229/−0
- src/Language/Fixpoint/Solver/Solve.hs +114/−0
- src/Language/Fixpoint/Solver/Validate.hs +100/−0
- src/Language/Fixpoint/Solver/Worklist.hs +128/−0
- src/Language/Fixpoint/Sort.hs +138/−116
- src/Language/Fixpoint/Types.hs +463/−304
- src/Language/Fixpoint/Visitor.hs +88/−27
- tests/test.hs +263/−0
Fixpoint.hs view
@@ -1,73 +1,11 @@--import Language.Fixpoint.Interface (solveFile)-import System.Environment (getArgs)--- import System.Console.GetOpt-import Language.Fixpoint.Config hiding (config)-import Data.Maybe (fromMaybe, listToMaybe)-import System.Console.CmdArgs +import Language.Fixpoint.Interface (solveFQ)+import Language.Fixpoint.Config (getOpts)+import System.Exit import System.Console.CmdArgs.Verbosity (whenLoud)-import Control.Applicative ((<$>))-import Language.Fixpoint.Parse-import Language.Fixpoint.Types-import Text.PrettyPrint.HughesPJ --------main = do cfg <- getOpts +main :: IO ExitCode+main = do cfg <- getOpts whenLoud $ putStrLn $ "Options: " ++ show cfg- if (native cfg) - then solveNative (inFile cfg) - else solveFile cfg----config = Config { - inFile = def &= typ "TARGET" &= args &= typFile - , outFile = "out" &= help "Output file" - , solver = def &= help "Name of SMT Solver" - , genSorts = def &= help "Generalize qualifier sorts"- , ueqAllSorts = def &= help "use UEq on all sorts"- , native = False &= help "Use (new, non-working) Haskell Solver"- , real = False &= help "Experimental support for the theory of real numbers"- } - &= verbosity- &= program "fixpoint" - &= help "Predicate Abstraction Based Horn-Clause Solver" - &= summary "fixpoint Copyright 2009-13 Regents of the University of California." - &= details [ "Predicate Abstraction Based Horn-Clause Solver"- , ""- , "To check a file foo.fq type:"- , " fixpoint foo.fq"- ]--getOpts :: IO Config -getOpts = do md <- cmdArgs config - putStrLn $ banner md- return md--banner args = "Liquid-Fixpoint Copyright 2009-13 Regents of the University of California.\n" - ++ "All Rights Reserved.\n"-------------------------------------------------------------------------------------- Hook for Haskell Solver ------------------------------------------------------------------------------------------------------------------------------------------solveNative file - = do str <- readFile file- let q = rr' file str :: FInfo ()- res <- solveQuery q- putStrLn $ "Result: " ++ show res- error "TODO: enzo"-----------------------------------------------------------------solveQuery :: FInfo a -> IO (FixResult a) ----------------------------------------------------------------solveQuery q - = do putStrLn $ "Query Was: " ++ (render $ toFixpoint q)- return Safe - -- error "TODO: Enzo"+ e <- solveFQ cfg+ putStrLn $ "EXIT: " ++ show e+ exitWith e
Setup.hs view
@@ -40,7 +40,7 @@ setEnv "Z3MEM" (show z3mem) executeShellCommand "./configure" executeShellCommand "./build.sh"- executeShellCommand "chmod a+x external/fixpoint/fixpoint.native "+ executeShellCommand "chmod a+x external/fixpoint/fixpoint.native" where allDirs = absoluteInstallDirs pkg lbi NoCopyDest binDir = bindir allDirs ++ "/"
external/fixpoint/ast.ml view
@@ -238,6 +238,19 @@ let rec unifyt s = function | Num,_ | _, Num -> None+(* NIKI: Unifycation of two variables should always succeed, +but the bellow code crashes tests/zipper0.hs.fq+*)+(*+ | (Var i), (Var j) -> + begin match lookup_var s i with+ | Some ct -> Some {s with vars = (j,ct) :: s.vars}+ | None -> begin match lookup_var s j with+ | Some ct -> Some {s with vars = (i, ct) :: s.vars}+ | None -> Some {s with vars = (i, Var j) :: s.vars}+ end+ end+*) | ct, (Var i) | (Var i), ct (* when ct != Bool *) ->@@ -318,9 +331,11 @@ let sub_args s = List.sort compare s.vars (* API *)- let check_arity n s = s.vars |>: fst |> Misc.sort_and_compact |> List.length |> (=) n- (* if ... then s else assertf "Type Inst. With Wrong Arity!" *)+ let check_arity n s = + let n_vars = s.vars |>: fst |> Misc.sort_and_compact |> List.length in + n == n_vars + end module Symbol =@@ -1154,7 +1169,37 @@ end | None -> None +let checkArity f uf = function+ | None -> None+ | Some (s, t) -> begin match uf_arity f uf with+ | Some n -> if Sort.check_arity n s then Some (s, t) else None+ | _ -> None+ end +let unifiable t1 t2 = + match Sort.unify [t1] [t2] with+ | Some _ -> true + | _ -> false+++(* added for sortcheck of Nothing([])+ it used to fail, as (su, Some (Just @0)) = sortcheck_expr (Nothing ([]))+ but su.vars is empty+ *)+let updateArity env f = function + | None -> None + | Some (su, t) -> begin match uf_arity f env with + | Some n -> + let rec go n + = if n < 0 + then [] + else match Sort.lookup_var su n with + | Some _ -> go (n-1)+ | None -> (n, Sort.Var n) :: go (n-1)+ in Some({su with Sort.vars = List.append su.Sort.vars (go n) }, t)+ | None -> None+ end + let rec sortcheck_expr g f e = match euw e with | Bot ->@@ -1172,10 +1217,14 @@ | Ite (p, e1, e2) -> if sortcheck_pred g f p then match Misc.map_pair (sortcheck_expr g f) (e1, e2) with- | (Some t1, Some t2) when t1 = t2 -> Some t1+ | (Some t1, Some t2) -> + begin + match Sort.unify [t1] [t2] with + | Some s -> Some (Sort.apply s t1) + | None -> None+ end | _ -> None else None- | Cst (e1, t) -> begin match euw e1 with | App (uf, es) -> sortcheck_app g f (Some t) uf es@@ -1194,7 +1243,7 @@ and sortcheck_app_sub g f so_expected uf es = let yikes uf = F.printf "sortcheck_app_sub: unknown sym = %s \n" (Symbol.to_string uf) in sortcheck_sym f uf- |> function None -> (yikes uf; None) | Some t ->+ |> function None -> (* yikes uf; *) None | Some t -> Sort.func_of_t t |> function None -> None | Some (tyArity, i_ts, o_t) -> let _ = asserts (List.length es = List.length i_ts)@@ -1214,17 +1263,19 @@ | None -> None | Some s' -> Some (s', Sort.apply s' t) -and sortcheck_app g f so_expected uf es =- sortcheck_app_sub g f so_expected uf es+and sortcheck_app g f tExp uf es =++ sortcheck_app_sub g f tExp uf es+ |> updateArity uf f (* THIS CHECK IS NEW, but will it break a bunch of tests? *) |> Misc.maybe_map snd- (* >> begin function+ (*+ >> begin function | Some t -> Format.printf "sortcheck_app: e = %s , t = %s \n" (expr_to_string (eApp (uf, es))) (Sort.to_string t) | None -> Format.printf "sortcheck_app: e = %s FAILS\n" (expr_to_string (eApp (uf, es))) end- *)-+ *) and sortcheck_op g f (e1, op, e2) = (* DEBUGGING@@ -1257,12 +1308,22 @@ when op = Minus && s = s' -> Some Sort.Int + | (Some (Sort.Var v), Some t)+ | (Some t, Some (Sort.Var v))+ -> begin match Sort.unify [Sort.Var v] [t] with+ | None -> None+ | Some _ -> Some t (* PV: subst is lost here *)+ end+ | _ -> None and sortcheck_rel g f (e1, r, e2) = let t1o, t2o = (e1,e2) |> Misc.map_pair (sortcheck_expr g f) in match r, t1o, t2o with+ | Ueq, Some (_), Some (_)+ | Une, Some (_), Some (_)+ -> true | _, Some (Sort.Ptr _) , Some (Sort.Ptr Sort.LFun) | _, Some (Sort.Ptr Sort.LFun), Some (Sort.Ptr _) -> true@@ -1274,21 +1335,18 @@ && (sortcheck_loc f l2 = Some Sort.Num)) || ((sortcheck_loc f l1 = Some Sort.Frac) && (sortcheck_loc f l2 = Some Sort.Frac))- -> true + -> true | _ , Some Sort.Real, Some (Sort.Ptr l) | _ , Some (Sort.Ptr l), Some Sort.Real -> sortcheck_loc f l = Some Sort.Frac | Eq, Some t1, Some t2 | Ne, Some t1, Some t2- -> t1 = t2- | Ueq, Some (Sort.App (_,_)), Some (Sort.App (_,_))- | Une, Some (Sort.App (_,_)), Some (Sort.App (_,_))- -> true+ -> unifiable t1 t2 | _ , Some (Sort.App (tc,_)), _ when (g tc) (* tc is an interpreted tycon *) -> false | _ , Some t1, Some t2- -> t1 = t2 && t1 != Sort.Bool+ -> unifiable t1 t2 && t1 != Sort.Bool | _ -> false and sortcheck_pred g f p =@@ -1296,8 +1354,8 @@ | True | False -> true- | Bexp e -> - sortcheck_expr g f e = Some Sort.Bool + | Bexp e ->+ sortcheck_expr g f e = Some Sort.Bool | Not p -> sortcheck_pred g f p | Imp (p1, p2) | Iff (p1, p2) ->@@ -1305,7 +1363,6 @@ | And ps | Or ps -> List.for_all (sortcheck_pred g f) ps- | Atom (e1, Ueq, e2) when !Constants.ueq_all_sorts -> (not (None = sortcheck_expr g f e1)) &&@@ -1316,9 +1373,9 @@ when not (!Constants.strictsortcheck) -> not (None = sortcheck_expr g f e) - | Atom (((Con _, _) as e) , Eq, (App (uf, es), _))+ | Atom (((Con _, _) as e), Eq, (App (uf, es), _)) | Atom ((App (uf, es), _), Eq, ((Con _, _) as e))- | Atom (((Var _, _) as e) , Eq, (App (uf, es), _))+ | Atom (((Var _, _) as e), Eq, (App (uf, es), _)) | Atom ((App (uf, es), _), Eq, ((Var _, _) as e)) (* -> begin match sortcheck_sym f x with *) -> begin match sortcheck_expr g f e with@@ -1330,7 +1387,7 @@ -> let t1o = solved_app f uf1 <| sortcheck_app_sub g f None uf1 e1s in let t2o = solved_app f uf2 <| sortcheck_app_sub g f None uf2 e2s in begin match t1o, t2o with- | (Some t1, Some t2) -> t1 = t2+ | (Some t1, Some t2) -> unifiable t1 t2 | (None, None) -> false | (None, Some t2) -> not (None = sortcheck_app g f (Some t2) uf1 e1s) | (Some t1, None) -> not (None = sortcheck_app g f (Some t1) uf2 e2s)@@ -1356,6 +1413,10 @@ (* API *) let sortcheck_app g f tExp uf es =+ sortcheck_app_sub g f tExp uf es+ |> checkArity f uf++ (* match uf_arity f uf, sortcheck_app_sub g f tExp uf es with | (Some n, Some (s, t)) -> if Sort.check_arity n s then@@ -1371,15 +1432,14 @@ (opt_to_string Sort.to_string tExp) in assertf "%s" msg- *)+ *) | _ -> None+ *) -(*-let sortcheck_pred f p =- sortcheck_pred f p- >> (fun b -> ignore <| F.printf "sortcheck_pred: p = %a, res = %b\n"- Predicate.print p b)+let sortcheck_pred g f p =+ sortcheck_pred g f p+(* >> (fun b -> ignore <| F.printf "DEBUG: sortcheck_pred: p = %a, res = %b\n" Predicate.print p b) *) (***************************************************************************)
external/fixpoint/ast.mli view
@@ -1,27 +1,27 @@ (*- * Copyright © 2009 The Regents of the University of California. All rights reserved. + * Copyright © 2009 The Regents of the University of California. All rights reserved. *- * Permission is hereby granted, without written agreement and without - * license or royalty fees, to use, copy, modify, and distribute this - * software and its documentation for any purpose, provided that the - * above copyright notice and the following two paragraphs appear in - * all copies of this software. - * - * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY - * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN - * IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * Permission is hereby granted, without written agreement and without+ * license or royalty fees, to use, copy, modify, and distribute this+ * software and its documentation for any purpose, provided that the+ * above copyright notice and the following two paragraphs appear in+ * all copies of this software.+ *+ * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY+ * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN+ * IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY+ * OF SUCH DAMAGE.+ *+ * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS *) (**- * This module implements a DAG representation for expressions and + * This module implements a DAG representation for expressions and * predicates: each sub-predicate or sub-expression is paired with- * a unique int ID, which enables constant time hashing. + * a unique int ID, which enables constant time hashing. * However, one must take care when using DAGS: * (1) they can only be constructed using the appropriate functions * (2) when destructed via pattern-matching, one must discard the ID@@ -31,22 +31,22 @@ (********************** Base Logic ********************) (*******************************************************) -module Cone : sig +module Cone : sig type 'a t = Empty | Cone of ('a * 'a t) list val map : ('a -> 'b) -> 'a t -> 'b t end module Sort : sig- type loc = - | Loc of string + type loc =+ | Loc of string | Lvar of int | LFun type tycon- type t + type t type sub- + val tycon : string -> tycon val tycon_string: tycon -> string @@ -63,19 +63,19 @@ val t_func : int -> t list -> t val t_app : tycon -> t list -> t (* val t_fptr : t *)- + val is_bool : t -> bool val is_int : t -> bool val is_real : t -> bool val is_func : t -> bool val is_kind : t -> bool- val app_of_t : t -> (tycon * t list) option + val app_of_t : t -> (tycon * t list) option val func_of_t : t -> (int * t list * t) option val ptr_of_t : t -> loc option- + val compat : t -> t -> bool val empty_sub : sub- val unifyWith : sub -> t list -> t list -> sub option + val unifyWith : sub -> t list -> t list -> sub option val unify : t list -> t list -> sub option val apply : sub -> t -> t val generalize : t list -> t list@@ -83,14 +83,14 @@ (* val check_arity : int -> sub -> bool *) end -module Symbol : - sig - type t +module Symbol :+ sig+ type t module SMap : FixMisc.EMapType with type key = t module SSet : FixMisc.ESetType with type elt = t- val mk_wild : unit -> t + val mk_wild : unit -> t val of_string : string -> t- val to_string : t -> string + val to_string : t -> string val is_wild_any : t -> bool val is_wild_fresh : t -> bool val is_wild : t -> bool@@ -116,20 +116,20 @@ type bop = Plus | Minus | Times | Div | Mod (* NOTE: For "Mod" 2nd expr should be a constant or a var *) -type expr = expr_int * tag +type expr = expr_int * tag and expr_int = | Con of Constant.t | Var of Symbol.t | App of Symbol.t * expr list- | Bin of expr * bop * expr + | Bin of expr * bop * expr | Ite of pred * expr * expr- | Fld of Symbol.t * expr (* NOTE: Fld (s, e) == App ("field"^s,[e]) *) - | Cst of expr * Sort.t + | Fld of Symbol.t * expr (* NOTE: Fld (s, e) == App ("field"^s,[e]) *)+ | Cst of expr * Sort.t | Bot | MExp of expr list- | MBin of expr * bop list * expr - + | MBin of expr * bop list * expr+ and pred = pred_int * tag and pred_int =@@ -141,7 +141,7 @@ | Imp of pred * pred | Iff of pred * pred | Bexp of expr- | Atom of expr * brel * expr + | Atom of expr * brel * expr | MAtom of expr * brel list * expr | Forall of ((Symbol.t * Sort.t) list) * pred @@ -154,8 +154,8 @@ val eModExp : expr * expr -> expr val eVar : Symbol.t -> expr val eApp : Symbol.t * expr list -> expr-val eBin : expr * bop * expr -> expr -val eMBin : expr * bop list * expr -> expr +val eBin : expr * bop * expr -> expr+val eMBin : expr * bop list * expr -> expr val eIte : pred * expr * expr -> expr val eFld : Symbol.t * expr -> expr val eCst : expr * Sort.t -> expr@@ -175,26 +175,26 @@ val pUequal : expr * expr -> pred val neg_brel : brel -> brel -module Expression : +module Expression : sig- module Hash : Hashtbl.S with type key = expr - + module Hash : Hashtbl.S with type key = expr+ val print : Format.formatter -> expr -> unit val show : expr -> unit val to_string : expr -> string- + val unwrap : expr -> expr_int val support : expr -> Symbol.t list- val subst : expr -> Symbol.t -> expr -> expr - val map : (pred -> pred) -> (expr -> expr) -> expr -> expr - val iter : (pred -> unit) -> (expr -> unit) -> expr -> unit + val subst : expr -> Symbol.t -> expr -> expr+ val map : (pred -> pred) -> (expr -> expr) -> expr -> expr+ val iter : (pred -> unit) -> (expr -> unit) -> expr -> unit end- + module Predicate : sig- module Hash : Hashtbl.S with type key = pred - + module Hash : Hashtbl.S with type key = pred+ val print : Format.formatter -> pred -> unit val show : pred -> unit val to_string : pred -> string@@ -202,13 +202,13 @@ val unwrap : pred -> pred_int val support : pred -> Symbol.t list val subst : pred -> Symbol.t -> expr -> pred- val map : (pred -> pred) -> (expr -> expr) -> pred -> pred - val iter : (pred -> unit) -> (expr -> unit) -> pred -> unit + val map : (pred -> pred) -> (expr -> expr) -> pred -> pred+ val iter : (pred -> unit) -> (expr -> unit) -> pred -> unit val is_contra : pred -> bool val is_tauto : pred -> bool end -module Subst : +module Subst : sig type t val empty : t@@ -227,7 +227,7 @@ sig type pr = string * string list type gd = C of pred | K of pr- type t = pr * gd list + type t = pr * gd list val print: Format.formatter -> t -> unit val support: t -> string list end@@ -241,7 +241,7 @@ val symm_pred : pred -> pred val unify_pred : pred -> pred -> Subst.t option val substs_expr : expr -> Subst.t -> expr-val substs_pred : pred -> Subst.t -> pred +val substs_pred : pred -> Subst.t -> pred val simplify_pred : pred -> pred val conjuncts : pred -> pred list @@ -250,4 +250,3 @@ val sortcheck_app : (Sort.tycon -> bool) -> (Symbol.t -> Sort.t option) -> Sort.t option -> Symbol.t -> expr list -> (Sort.sub * Sort.t) option val into_of_expr : expr -> int option-
external/fixpoint/fixConstraint.ml view
@@ -1,22 +1,22 @@ (*- * Copyright © 2009 The Regents of the University of California. All rights reserved. + * Copyright © 2009 The Regents of the University of California. All rights reserved. *- * Permission is hereby granted, without written agreement and without - * license or royalty fees, to use, copy, modify, and distribute this - * software and its documentation for any purpose, provided that the - * above copyright notice and the following two paragraphs appear in - * all copies of this software. - * - * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY - * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN - * IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION + * Permission is hereby granted, without written agreement and without+ * license or royalty fees, to use, copy, modify, and distribute this+ * software and its documentation for any purpose, provided that the+ * above copyright notice and the following two paragraphs appear in+ * all copies of this software.+ *+ * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY+ * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN+ * IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY+ * OF SUCH DAMAGE.+ *+ * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS+ * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION * TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONSy. * *)@@ -33,7 +33,7 @@ module BS = BNstats module Su = Ast.Subst module Co = Constants-module Misc = FixMisc +module Misc = FixMisc module MSM = Misc.StringMap open Misc.Ops@@ -47,7 +47,7 @@ type envt = reft SM.t type senvt = So.t SM.t type wf = envt * reft * (id option) * (Qualifier.t -> bool)-type t = { full : envt; +type t = { full : envt; nontriv : envt; guard : A.pred; iguard : A.pred;@@ -67,8 +67,8 @@ ; kvars : Ast.Symbol.SSet.t } *) -let mydebug = false - +let mydebug = false+ (***************************************************************) (*********************** Getter/Setter *************************) (***************************************************************)@@ -80,16 +80,16 @@ (* API *)-let env_of_t = fun t -> t.full -let grd_of_t = fun t -> t.guard -let lhs_of_t = fun t -> t.lhs +let env_of_t = fun t -> t.full+let grd_of_t = fun t -> t.guard+let lhs_of_t = fun t -> t.lhs let rhs_of_t = fun t -> t.rhs let tag_of_t = fun t -> t.tag let ido_of_t = fun t -> t.ido let id_of_t = fun t -> match t.ido with Some i -> i | _ -> assertf "C.id_of_t" let vv_of_t = fun t -> fst3 t.lhs let sort_of_t = fun t -> snd3 t.lhs-let senv_of_t = fun t -> SM.map snd3 t.full |> SM.add (vv_of_t t) (sort_of_t t) +let senv_of_t = fun t -> SM.map snd3 t.full |> SM.add (vv_of_t t) (sort_of_t t) (* let make_t = fun env p ((v,t,ras1) as r1) r2 io is ->@@ -97,11 +97,11 @@ let po, kras = split_ras ras1 in let ne, ps = non_trivial env in let gps = match po with Some p' -> p' :: p :: ps | _ -> p :: ps in- { full = env + { full = env ; nontriv = ne ; guard = p- ; iguard = A.pAnd gps - ; lhs = (v, t, kras) + ; iguard = A.pAnd gps+ ; lhs = (v, t, kras) ; rhs = r2 ; ido = io ; tag = is }@@ -114,53 +114,53 @@ let reft_of_wf = snd4 let id_of_wf = function (_,_,Some i,_) -> i | _ -> assertf "C.id_of_wf" let filter_of_wf = fth4- + (*************************************************************) (************************** Misc. ***************************) (*************************************************************) -let is_simple_refatom = function - | Kvar (s, _) -> Ast.Subst.is_empty s +let is_simple_refatom = function+ | Kvar (s, _) -> Ast.Subst.is_empty s | _ -> false -let is_tauto_refatom = function - | Conc p -> P.is_tauto p +let is_tauto_refatom = function+ | Conc p -> P.is_tauto p | _ -> false (* API *) let is_tauto = rhs_of_t <+> ras_of_reft <+> List.for_all is_tauto_refatom (* API *)-let fresh_kvar = +let fresh_kvar = let tick, _ = Misc.mk_int_factory () in tick <+> string_of_int <+> (^) "k_" <+> Sy.of_string (* API *) let kvars_of_reft (_, _, rs) =- Misc.map_partial begin function - | Kvar (subs, k) -> Some (subs,k) - | _ -> None + Misc.map_partial begin function+ | Kvar (subs, k) -> Some (subs,k)+ | _ -> None end rs -let meet x (v1, t1, ra1s) (v2, t2, ra2s) = - asserts (v1=v2 && t1=t2) "ERROR: FixConstraint.meet x=%s (v1=%s, t1=%s) (v2=%s, t2=%s)" +let meet x (v1, t1, ra1s) (v2, t2, ra2s) =+ asserts (v1=v2 && t1=t2) "ERROR: FixConstraint.meet x=%s (v1=%s, t1=%s) (v2=%s, t2=%s)" (Sy.to_string x) (Sy.to_string v1) (A.Sort.to_string t1) (Sy.to_string v2) (A.Sort.to_string t2) ; (v1, t1, Misc.sort_and_compact (ra1s ++ ra2s)) let env_of_bindings_ meetb xrs =- List.fold_left begin fun env (x, r) -> + List.fold_left begin fun env (x, r) -> let r = if meetb && SM.mem x env then meet x r (SM.find x env) else r in SM.add x r env end SM.empty xrs (* API *) let env_of_bindings = env_of_bindings_ true-let env_of_ordered_bindings = env_of_bindings_ false +let env_of_ordered_bindings = env_of_bindings_ false -(* +(* let env_of_bindings xrs =- List.fold_left begin fun env (x, r) -> + List.fold_left begin fun env (x, r) -> let r = if SM.mem x env then meet x r (SM.find x env) else r in SM.add x r env end SM.empty xrs@@ -168,40 +168,40 @@ let bindings_of_env = SM.to_list -(* let bindings_of_env env = +(* let bindings_of_env env = SM.fold (fun x y bs -> (x,y)::bs) env [] *) -let split_ras ras = +let split_ras ras = let cras, kras = List.partition (function (Conc _) -> true | _ -> false) ras in- cras |> Misc.map_partial (function Conc p -> Some p | _ -> None) + cras |> Misc.map_partial (function Conc p -> Some p | _ -> None) |> (function [] -> (None, kras) | ps -> (Some (A.pAnd ps), kras)) -let kbindings_of_lhs {nontriv = ne; lhs = (v, t, ras)} = +let kbindings_of_lhs {nontriv = ne; lhs = (v, t, ras)} = let xkss = SM.to_list ne in let _, kras = split_ras ras in (v, (v,t,kras)) :: xkss let map_env = SM.mapi-let lookup_env = Misc.flip SM.maybe_find +let lookup_env = Misc.flip SM.maybe_find (* let lookup_env env x = try Some (SM.find x env) with Not_found -> None *) (* API *)-let is_simple {lhs = (_,_,ra1s); rhs = (_,_,ra2s)} = - List.for_all is_simple_refatom ra1s - && List.for_all is_simple_refatom ra2s +let is_simple {lhs = (_,_,ra1s); rhs = (_,_,ra2s)} =+ List.for_all is_simple_refatom ra1s+ && List.for_all is_simple_refatom ra2s && !Co.simple let is_conc_refa = function Conc p -> not (P.is_tauto p) | _ -> false (* API *) let kvars_of_t {nontriv = env; lhs = lhs; rhs = rhs} =- [lhs; rhs] + [lhs; rhs] |> SM.fold (fun _ r acc -> r :: acc) env- |> Misc.flap kvars_of_reft + |> Misc.flap kvars_of_reft @@ -210,37 +210,37 @@ (*********************** Logic Embedding *********************) (*************************************************************) -let canon_ras ras = +let canon_ras ras = match split_ras ras with | None, kras -> kras | Some p, kras -> Conc p :: kras -(* -let non_trivial env = - SM.fold begin fun x r sm -> match thd3 r with - | [] -> sm +(*+let non_trivial env =+ SM.fold begin fun x r sm -> match thd3 r with+ | [] -> sm | _::_ -> SM.add x r sm end env SM.empty *) -let non_trivial env = +let non_trivial env = SM.fold begin fun x (v,t,ras) ((ne, ps) as acc) -> match ras with- | [] -> acc - | _ -> let po, kras = split_ras ras in + | [] -> acc+ | _ -> let po, kras = split_ras ras in let ne' = match kras with [] -> ne | _ -> SM.add x (v,t,kras) ne in let ps' = match po with None -> ps | Some p -> (P.subst p v (A.eVar x)) :: ps in ne', ps'- end env (SM.empty, []) + end env (SM.empty, []) (* API *) let make_t = fun env p r1 r2 io is -> let p = A.simplify_pred p in let ne, ps = non_trivial env in- { full = env + { full = env ; nontriv = ne ; guard = p- ; iguard = A.pAnd (p::ps) - ; lhs = r1 + ; iguard = A.pAnd (p::ps)+ ; lhs = r1 ; rhs = r2 ; ido = io ; tag = is }@@ -259,34 +259,34 @@ | Kvar (su,k) -> soln_read s k |> List.map (Misc.flip A.substs_pred su) (* API *)-let preds_of_reft f (_,_,ras) = +let preds_of_reft f (_,_,ras) = Misc.flap (preds_of_refa f) ras (* API *) let meet_solution s1 s2 = fun k -> s1 k ++ s2 k (* SM.extendWith (fun _ -> (++)) *) let empty_solution = fun _ -> [] -let apply_solution_refa f ra = +let apply_solution_refa f ra = Conc (A.pAnd (preds_of_refa f ra)) (* API *)-let apply_solution f (v, t, ras) = +let apply_solution f (v, t, ras) = (v, t, List.map (apply_solution_refa f) ras) let preds_of_envt f env = SM.fold- (fun x ((vv, t, ras) as r) ps -> + (fun x ((vv, t, ras) as r) ps -> let vps = preds_of_reft f r in let xps = List.map (fun p -> P.subst p vv (A.eVar x)) vps in xps ++ ps)- env [] + env [] (* API *)-let wellformed_pred senv = +let wellformed_pred senv = A.sortcheck_pred Theories.is_interp (Misc.flip SM.maybe_find senv) (* API *)-let preds_of_lhs_nofilter f c = +let preds_of_lhs_nofilter f c = let envps = preds_of_envt f c.nontriv in let r1ps = preds_of_reft f c.lhs in (c.iguard :: envps) ++ r1ps@@ -294,27 +294,35 @@ (* let preds_of_lhs f c = let env = SM.add (fst3 c.lhs) c.lhs c.full in- let wfp p = wellformed_pred env p + let wfp p = wellformed_pred env p >> (fun b -> if not b then F.eprintf "WARNING: Malformed Lhs Pred (%a)\n" P.print p) in let ps = preds_of_lhs_nofilter f c in let ps' = List.filter wfp ps in- if !Co.strictsortcheck && List.length ps != List.length ps' + if !Co.strictsortcheck && List.length ps != List.length ps' then raise (BadConstraint (Misc.maybe c.ido, c.tag, "Malformed Lhs Pred")) else ps *) -let report_wellformed senv c p wf = +let pred_context senv p =+ P.support p+ |> List.filter (fun x -> SM.mem x senv)+ |> List.map (fun x -> (x, SM.find x senv))+++let report_wellformed senv c p wf = if not wf then- let msg = F.sprintf "WARNING: Malformed Lhs Pred (%s)\n" (P.to_string p) in - let _ = F.eprintf "%s" msg in - let _ = SM.iter (fun s t -> F.eprintf "@[%a :: %a@]@." Sy.print s So.print t) senv in- let _ = F.eprintf "@[%a@]@.@." P.print p in+ let msg = F.sprintf "WARNING: Malformed Lhs Pred (%s)\n" (P.to_string p) in+ let _ = F.eprintf "%s" msg in+ let _ = pred_context senv p+ |> List.iter (fun (s,t) -> F.eprintf "@[%a :: %a@]@." Sy.print s So.print t) in+ let _ = F.eprintf "@[%a@]@.@." P.print p in if !Co.strictsortcheck then raise (BadConstraint (Misc.maybe c.ido, c.tag, msg)) (* API *)-let preds_of_lhs f c = +let preds_of_lhs f c = let senv = senv_of_t c in (* SM.add (fst3 c.lhs) c.lhs c.full in *)- preds_of_lhs_nofilter f c + preds_of_lhs_nofilter f c+ |> Misc.flap A.conjuncts |> List.filter (fun p -> wellformed_pred senv p >> report_wellformed senv c p) (* API *)@@ -332,24 +340,24 @@ (* (* API *)-let print_ras so ppf = function +let print_ras so ppf = function | [] -> F.fprintf ppf "true"- | ras -> begin match so with + | ras -> begin match so with | None ->- F.fprintf ppf "%a" (Misc.pprint_many_box false "" "; " "" print_refineatom) ras + F.fprintf ppf "%a" (Misc.pprint_many_box false "" "; " "" print_refineatom) ras | Some s -> let ps = Misc.flap (preds_of_refa s) ras in- (match ps with - | [] -> F.fprintf ppf "[]" + (match ps with+ | [] -> F.fprintf ppf "[]" | _ -> F.fprintf ppf "%a" P.print (A.pAnd ps)) end *) (* API *) let print_ras so ppf ras = match so with- | None -> + | None -> Misc.pprint_many_box false "[" "; " "]" print_refineatom ppf ras- | Some s -> - begin match Misc.flap (preds_of_refa s) ras with + | Some s ->+ begin match Misc.flap (preds_of_refa s) ras with | [] -> F.fprintf ppf "[]" | ps -> F.fprintf ppf "[%a]" P.print (A.pAnd ps) end@@ -358,7 +366,7 @@ (* API *) let print_reft_pred so ppf (v,t,ras) = F.fprintf ppf "@[{%a:%a | %a}@]"- Sy.print v + Sy.print v Ast.Sort.print t (print_ras so) ras @@ -370,18 +378,18 @@ (* API *) let print_reft so ppf (v, t, ras) =- F.fprintf ppf "@[{%a : %a | %a}@]" - Sy.print v + F.fprintf ppf "@[{%a : %a | %a}@]"+ Sy.print v Ast.Sort.print t (print_ras so) ras (* API *)-let print_binding so ppf (x, r) = - F.fprintf ppf "@[%a:%a@]" Sy.print x (print_reft so) r +let print_binding so ppf (x, r) =+ F.fprintf ppf "@[%a:%a@]" Sy.print x (print_reft so) r (* API *)-let print_env so ppf env = - bindings_of_env env +let print_env so ppf env =+ bindings_of_env env |> F.fprintf ppf "@[%a@]" (Misc.pprint_many_brackets true (print_binding so)) @@ -395,17 +403,17 @@ (* API *) let print_tag ppf = function | [],_ -> F.fprintf ppf ""- | is,s -> F.fprintf ppf "tag [%s] //%s" (string_of_intlist is) s + | is,s -> F.fprintf ppf "tag [%s] //%s" (string_of_intlist is) s (* API *) let print_dep ppf = function- | Adp ((t,_), (t',_)) + | Adp ((t,_), (t',_)) -> F.fprintf ppf "add_dep: [%s] => [%s]" (string_of_intlist t) (string_of_intlist t')- | Ddp ((t,_), (t',_)) + | Ddp ((t,_), (t',_)) -> F.fprintf ppf "del_dep: [%s] => [%s]" (string_of_intlist t) (string_of_intlist t')- | Ddp_s (t,_) - -> F.fprintf ppf "del_dep: [%s] => *" (string_of_intlist t) - | Ddp_t (t',_) + | Ddp_s (t,_)+ -> F.fprintf ppf "del_dep: [%s] => *" (string_of_intlist t)+ | Ddp_t (t',_) -> F.fprintf ppf "del_dep: * => [%s]" (string_of_intlist t') (* API *)@@ -416,46 +424,46 @@ pprint_id io let print_t so ppf c =- let env, g = if !Co.print_nontriv then c.nontriv, c.iguard else c.full, c.guard in - F.fprintf ppf + let env, g = if !Co.print_nontriv then c.nontriv, c.iguard else c.full, c.guard in+ F.fprintf ppf "constraint:@. env @[%a@] @\n grd @[%a@] @\n lhs @[%a@] @\n rhs @[%a@] @\n %a %a @\n"- (print_env so) env + (print_env so) env P.print g- (print_reft so) c.lhs + (print_reft so) c.lhs (print_reft so) c.rhs pprint_id c.ido- print_tag c.tag + print_tag c.tag (* API *) let to_string = Misc.fsprintf (print_t None)-let refa_to_string = Misc.fsprintf print_refineatom +let refa_to_string = Misc.fsprintf print_refineatom let reft_to_string = Misc.fsprintf (print_reft None)-let binding_to_string = Misc.fsprintf (print_binding None) +let binding_to_string = Misc.fsprintf (print_binding None) - + let intersect_maps m1 m2 = SM.filter begin fun k elt -> SM.mem k m2 && SM.find k m2 = elt end m1- + let intersect_wfs (e1, r1, id1, qf1) (e2, r2, id2, qf2) = let _ = assert (r1 = r2) in let env = intersect_maps e1 e2 in (env, r1, id1, fun x -> (qf1 x && qf2 x))- -let reduce_wfs wfs = - wfs - |> Misc.groupby reft_of_wf ++let reduce_wfs wfs =+ wfs+ |> Misc.groupby reft_of_wf |>: (fun wfs -> List.fold_left intersect_wfs (List.hd wfs) (List.tl wfs)) (* API *)-let matches_deps ds = +let matches_deps ds = let tt = H.create 37 in let s_tt = H.create 37 in let t_tt = H.create 37 in- List.iter begin function - | Adp (t, t') + List.iter begin function+ | Adp (t, t') | Ddp (t, t') -> H.add tt (t,t') () | Ddp_s t -> H.add s_tt t () | Ddp_t t' -> H.add t_tt t' ()@@ -466,8 +474,8 @@ let pol_of_dep = function Adp (_,_) -> true | _ -> false (* API *)-let tags_of_dep = function - | Adp (t, t') | Ddp (t, t') -> t,t' +let tags_of_dep = function+ | Adp (t, t') | Ddp (t, t') -> t,t' | _ -> assertf "tags_of_dep" (* API *)@@ -481,9 +489,9 @@ (* API *) let preds_kvars_of_reft reft =- List.fold_left begin fun (ps, ks) -> function + List.fold_left begin fun (ps, ks) -> function | Conc p -> p :: ps, ks- | Kvar (xes, kvar) -> ps, (xes, kvar) :: ks + | Kvar (xes, kvar) -> ps, (xes, kvar) :: ks end ([], []) (ras_of_reft reft) (***************************************************************************************)@@ -492,7 +500,7 @@ let theta_ra (su': Su.t) = function | Conc p -> Conc (A.substs_pred p su')- | Kvar (su, k) -> Kvar (Su.compose su su', k) + | Kvar (su, k) -> Kvar (Su.compose su su', k) (* API *) let make_reft = fun v so ras -> (v, so, List.map (theta_ra Su.empty) (canon_ras ras))@@ -518,23 +526,23 @@ (***************************************************************) let max_id n cs =- cs |> Misc.map_partial ido_of_t + cs |> Misc.map_partial ido_of_t >> (fun ids -> asserts (Misc.distinct ids) "Duplicate Ids") |> List.fold_left max n let max_wf_id n ws =- ws |> Misc.map_partial (fun (_,_,ido,_) -> ido) + ws |> Misc.map_partial (fun (_,_,ido,_) -> ido) >> (fun ids -> asserts (Misc.distinct ids) "Duplicate WF Ids") |> List.fold_left max n (* API *)-let add_wf_ids ws = +let add_wf_ids ws = Misc.mapfold begin fun j wf -> match wf with- | (x,y,None,z) -> j+1, (x, y, Some j, z) + | (x,y,None,z) -> j+1, (x, y, Some j, z) | _ -> j, wf end ((max_wf_id 0 ws) + 1) ws |> snd- + (* API *) let add_ids n cs = Misc.mapfold begin fun j c -> match c with@@ -549,6 +557,3 @@ let idn = match i with Some i -> i | None -> (-1) in List.exists is_conc_refa ras >> (fun rv -> if rv then (asserts (List.for_all is_conc_refa ras) "is_conc_rhs: id = %d" idn))-- -
external/fixpoint/fixLex.mll view
@@ -72,7 +72,7 @@ let digit = ['0'-'9' '-'] let letdig = ['0'-'9' 'a'-'z' 'A'-'Z' '_' '@' ''' '.' '#']-let alphlet = ['A'-'Z' 'a'-'z' '~' '_' ''' '@' ]+let alphlet = ['A'-'Z' 'a'-'z' '~' '_' ''' '@'] let capital = ['A'-'Z'] let small = ['a'-'z' '$' '_'] let ws = [' ' '\009' '\012']@@ -107,6 +107,7 @@ | '*' { TIMES } | '/' { DIV } | '?' { QM }+ | '$' { DOL } | '.' { DOT } | "not" { NOTWORD } | "tag" { TAG }
external/fixpoint/fixParse.mly view
@@ -70,7 +70,7 @@ %token MINUS %token TIMES %token DIV -%token QM DOT ASGN+%token DOL QM DOT ASGN %token OBJ REAL INT NUM PTR LFUN BOOL UNINT FUNC LIT FRAC %token SRT AXM CON CST WF SOL QUL KUT BIND ADP DDP %token ENV GRD LHS RHS REF@@ -132,7 +132,7 @@ | WF COLON wf { FixConfig.Wfc $3 } | sol { FixConfig.Sol $1 } | QUL qual { FixConfig.Qul $2 }- | KUT Id { FixConfig.Kut (Sy.of_string $2) }+ | KUT kvid { FixConfig.Kut $2 } | dep { FixConfig.Dep $1 } | BIND Num Id COLON reft { let (i, x, r) = ($2, Sy.of_string $3, $5) >> set_ibind @@ -395,10 +395,15 @@ refa { [$1] } | refa SEMI refasne { $1 :: $3 } ;- ++kvid:+ DOL Id { Sy.of_string $2 }+ | Id { Sy.of_string $1 }+ ;+ refa:- Id subs { C.Kvar ($2, (Sy.of_string $1)) }- | pred { C.Conc $1 }+ | kvid subs { C.Kvar ($2, $1) }+ | pred { C.Conc $1 } ; subs:
external/fixpoint/fixpoint.native-i386-linux view
binary file changed (1693827 → 1695021 bytes)
external/fixpoint/fixpoint.native-i686-w64-mingw32 view
file too large to diff
external/fixpoint/fixpoint.native-x86_64-darwin view
file too large to diff
external/fixpoint/fixpoint.native-x86_64-linux view
file too large to diff
external/fixpoint/predAbs.ml view
@@ -1,26 +1,26 @@ (*- * Copyright © 2009 The Regents of the University of California. All rights reserved. + * Copyright © 2009 The Regents of the University of California. All rights reserved. *- * Permission is hereby granted, without written agreement and without - * license or royalty fees, to use, copy, modify, and distribute this - * software and its documentation for any purpose, provided that the - * above copyright notice and the following two paragraphs appear in - * all copies of this software. - * - * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY - * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN - * IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION + * Permission is hereby granted, without written agreement and without+ * license or royalty fees, to use, copy, modify, and distribute this+ * software and its documentation for any purpose, provided that the+ * above copyright notice and the following two paragraphs appear in+ * all copies of this software.+ *+ * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY+ * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN+ * IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY+ * OF SUCH DAMAGE.+ *+ * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS+ * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION * TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. *) - + (*************************************************************) (******************** Solution Management ********************) (*************************************************************)@@ -45,23 +45,23 @@ module PH = A.Predicate.Hash module CX = Counterexample-module Misc = FixMisc +module Misc = FixMisc module IM = Misc.IntMap module IS = Misc.IntSet open Misc.Ops -let mydebug = false +let mydebug = false module Q2S = Misc.ESet (struct type t = Sy.t * Sy.t- let compare x y = compare x y + let compare x y = compare x y end) module V : Graph.Sig.COMPARABLE with type t = Sy.t = struct type t = Sy.t let hash = Sy.to_string <+> H.hash let compare = compare- let equal = (=) + let equal = (=) end @@ -84,9 +84,9 @@ *) module Id : Graph.Sig.ORDERED_TYPE_DFT with type t = unit = struct- type t = unit + type t = unit let default = ()- let compare = compare + let compare = compare end module G = Graph.Persistent.Digraph.ConcreteLabeled(V)(Id)@@ -101,79 +101,79 @@ | (_, Bot) -> b1 | (NonBot x, NonBot y) -> NonBot (x ++ y) -type t = +type t = { tpc : ProverArch.prover ; m : bind SM.t ; om : (Q.t list) SM.t ; wm : (Ast.Sort.t SM.t * Ast.Symbol.t * Ast.Sort.t) SM.t ; assm : FixConstraint.soln (* invariant assumption for K, must be a fixpoint wrt constraints *) (* ; qm : Q.t SM.t *) (* map from names to qualifiers *)- ; qs : Q.t list (* list of qualifiers *) + ; qs : Q.t list (* list of qualifiers *) ; qleqs : Q2S.t (* (q1,q2) \in qleqs implies q1 => q2 *)- ; seen : IS.t (* constraint (ids) that have been "refined" once *) + ; seen : IS.t (* constraint (ids) that have been "refined" once *) (* counterexamples *) ; step : CX.step (* which iteration *)- ; ctrace : CX.ctrace - ; lifespan : CX.lifespan - + ; ctrace : CX.ctrace+ ; lifespan : CX.lifespan+ (* stats *)- ; stat_simple_refines : int ref - ; stat_tp_refines : int ref - ; stat_imp_queries : int ref - ; stat_valid_queries : int ref - ; stat_matches : int ref - ; stat_umatches : int ref - ; stat_unsatLHS : int ref - ; stat_emptyRHS : int ref + ; stat_simple_refines : int ref+ ; stat_tp_refines : int ref+ ; stat_imp_queries : int ref+ ; stat_valid_queries : int ref+ ; stat_matches : int ref+ ; stat_umatches : int ref+ ; stat_unsatLHS : int ref+ ; stat_emptyRHS : int ref } -let lookup_bind k m = SM.find_default Bot k m +let lookup_bind k m = SM.find_default Bot k m let pprint_ps =- Misc.pprint_many false ";" P.print - -let pprint_dep ppf q = + Misc.pprint_many false ";" P.print++let pprint_dep ppf q = F.fprintf ppf "(%a, %a)" P.print (Q.pred_of_t q) Q.print_args q -let pprint_ds = +let pprint_ds = Misc.pprint_many false ";" pprint_dep -let pprint_bind ppf = function +let pprint_bind ppf = function | Bot -> F.fprintf ppf "(false, BOT())" | NonBot qs -> pprint_ds ppf qs -let pprint_qs ppf = +let pprint_qs ppf = F.fprintf ppf "[%a]" (Misc.pprint_many false ";" Q.print) -let pprint_qs' ppf = - List.map (fst <+> snd <+> snd <+> fst) <+> pprint_qs ppf +let pprint_qs' ppf =+ List.map (fst <+> snd <+> snd <+> fst) <+> pprint_qs ppf (*************************************************************) (************* Breadcrumbs for Cex Generation ****************) (*************************************************************) -let cx_iter c me = - { me with step = me.step + 1 } +let cx_iter c me =+ { me with step = me.step + 1 } -let cx_ctrace b c me = - let _ = if mydebug then F.printf "\nPredAbs.refine iter = %d cid = %d b = %b\n" +let cx_ctrace b c me =+ let _ = if mydebug then F.printf "\nPredAbs.refine iter = %d cid = %d b = %b\n" me.step (C.id_of_t c) b in if b then { me with ctrace = IM.adds (C.id_of_t c) [me.step] me.ctrace } else me -let lookup_qualifiers k m = - lookup_bind k m +let lookup_qualifiers k m =+ lookup_bind k m |> function | Bot -> [] | NonBot qs -> qs -let cx_update ks kqsm' me : t = - List.fold_left begin fun me k -> +let cx_update ks kqsm' me : t =+ List.fold_left begin fun me k -> let qs = QS.of_list (lookup_qualifiers k me.m) in let qs' = QS.of_list (SM.finds k kqsm') in let kills = QS.elements (QS.diff qs qs') in- if Misc.nonnull kills + if Misc.nonnull kills then {me with lifespan = SM.adds k [(me.step, kills)] me.lifespan} else me end me ks@@ -191,21 +191,21 @@ | None -> assertf "ERROR: unify q=%s p=%s" (P.to_string qp) (P.to_string p) let map_of_bindings bs =- List.fold_left begin fun s (k, ds) -> - ds |> List.map Misc.single + List.fold_left begin fun s (k, ds) ->+ ds |> List.map Misc.single |> Misc.flip (SM.add k) s- end SM.empty bs + end SM.empty bs *) let quals_of_bindings bm =- bm |> SM.range + bm |> SM.range |> Misc.flatten (* |> Misc.map (snd <+> fst) *) |> Misc.sort_and_compact >> (fun qs -> Co.bprintf mydebug "Quals of Bindings: \n%a" (Misc.pprint_many true "\n" Q.print) qs; flush stdout) (************************************************************************)-(*************************** Dumping to Dot *****************************) +(*************************** Dumping to Dot *****************************) (************************************************************************) module DotGraph = struct@@ -216,33 +216,33 @@ let iter_edges_e = G.iter_edges_e let graph_attributes = fun _ -> [`Size (11.0, 8.5); `Ratio (`Fill (* Float 1.29*))] let default_vertex_attributes = fun _ -> [`Shape `Box]- let vertex_name = Sy.to_string - let vertex_attributes = fun q -> [`Label (Sy.to_string q)] + let vertex_name = Sy.to_string+ let vertex_attributes = fun q -> [`Label (Sy.to_string q)] let default_edge_attributes = fun _ -> []- let edge_attributes = fun (_,(),_) -> [] + let edge_attributes = fun (_,(),_) -> [] let get_subgraph = fun _ -> None end -module Dot = Graph.Graphviz.Dot(DotGraph) +module Dot = Graph.Graphviz.Dot(DotGraph) -let dump_graph s g = - s |> open_out +let dump_graph s g =+ s |> open_out >> (fun oc -> Dot.output_graph oc g)- |> close_out + |> close_out (* INV: qs' \subseteq qs *) let update m k ds' =- let n' = List.length ds' in - let n = match SM.find_default Bot k m with - | Bot -> 1 + n' + let n' = List.length ds' in+ let n = match SM.find_default Bot k m with+ | Bot -> 1 + n' | NonBot qs -> List.length qs in- let _ = asserts (n = 0 || n' <= n) "PredAbs.update: Non-monotone k = %s |ds| = %d |ds'| = %d \n" (Sy.to_string k) n n' in + let _ = asserts (n = 0 || n' <= n) "PredAbs.update: Non-monotone k = %s |ds| = %d |ds'| = %d \n" (Sy.to_string k) n n' in ((n != n'), SM.add k (NonBot ds') m)- (* >> begin fun _ -> - if n' > n && n > 0 then - Co.bprintflush mydebug <| Printf.sprintf "OMFG: update k = %s |ds| = %d |ds'| = %d \n" + (* >> begin fun _ ->+ if n' > n && n > 0 then+ Co.bprintflush mydebug <| Printf.sprintf "OMFG: update k = %s |ds| = %d |ds'| = %d \n" (Sy.to_string k) n n' end *)@@ -252,31 +252,31 @@ * a "k-q" binding is ONLY preserved IF #bindings = #copies-of-k * If there are NO duplicate KVars there SHOULD BE no duplicate k-q pairs. *) -let group_ks_kqs ks kqs = - if (Misc.cardinality ks = List.length ks) then - kqs (* no duplicate kvars *) - else +let group_ks_kqs ks kqs =+ if (Misc.cardinality ks = List.length ks) then+ kqs (* no duplicate kvars *)+ else let km = SM.frequency ks in- kqs |> Misc.frequency + kqs |> Misc.frequency |> Misc.filter (fun ((k, _), n) -> n = SM.find_default 0 k km)- |> Misc.map fst + |> Misc.map fst -let p_update me ks kqs = +let p_update me ks kqs = (* let _ = Co.bprintflush mydebug (Printf.sprintf "p_update A: |kqs| = %d \n" (List.length kqs)) in *) let kqs = group_ks_kqs ks kqs in (* let _ = Co.bprintflush mydebug (Printf.sprintf "p_update B: |kqs| = %d \n" (List.length kqs)) in *) let kqsm = SM.of_alist kqs in- let me = me |> (!Co.cex <?> BS.time "cx_update" (cx_update ks) kqsm) in + let me = me |> (!Co.cex <?> BS.time "cx_update" (cx_update ks) kqsm) in List.fold_left begin fun (b, m) k ->- SM.finds k kqsm - |> update m k + SM.finds k kqsm+ |> update m k |> Misc.app_fst ((||) b) end (false, me.m) ks- |> Misc.app_snd (fun m -> { me with m = m }) + |> Misc.app_snd (fun m -> { me with m = m }) (* API *)-let top s ks = +let top s ks = ks (* |> List.partition (fun k -> SM.mem k s.m) >> (fun (_, badks) -> Co.bprintf mydebug "WARNING: Trueing Unbound KVars = %s \n" (Misc.fsprintf (Misc.pprint_many false "," Sy.print) badks)) |> fst *)@@ -309,7 +309,7 @@ (* DEBUG ONLY *) let print_param ppf (x, t) =- F.fprintf ppf "%a:%a" Sy.print x Ast.Sort.print t + F.fprintf ppf "%a:%a" Sy.print x Ast.Sort.print t let print_params ppf args = F.fprintf ppf "%a" (Misc.pprint_many false ", " print_param) args let print_valid_binding ppf (x,y) =@@ -317,8 +317,8 @@ let print_valid_bindings ppf xys = F.printf "[%a]" (Misc.pprint_many false "" print_valid_binding) xys -(* -let dupfree_binding xys : bool = +(*+let dupfree_binding xys : bool = let ys = List.map snd xys in let ys' = Misc.sort_and_compact ys in List.length ys = List.length ys'@@ -326,7 +326,7 @@ let varmatch_ctr = ref 0 -let varmatch (x, y) = +let varmatch (x, y) = let _ = varmatch_ctr += 1 in let (x,y) = Misc.map_pair Sy.to_string (x,y) in if x.[0] = '@' then@@ -336,8 +336,8 @@ let sort_compat t1 t2 = A.Sort.unify [t1] [t2] <> None -let wellformed_qual f q = - Q.pred_of_t q +let wellformed_qual f q =+ Q.pred_of_t q |> A.sortcheck_pred Theories.is_interp f (* >> (F.printf "\nwellformed: id = %d q = @[%a@] result %b\n" (C.id_of_wf wf) Q.print q) *) (* NEVER uncomment out the above. *)@@ -346,62 +346,62 @@ (**************** Lazy Instantiation: WF-Index *****************) (***************************************************************) -let kvars_of_wf wf = +let kvars_of_wf wf = let check_trivial su = asserts (Su.is_empty su) "non-trivial substitution in WF constraint!" in- wf |> C.reft_of_wf - |> C.kvars_of_reft + wf |> C.reft_of_wf+ |> C.kvars_of_reft >> List.iter (fst <+> check_trivial) |> List.map snd -let meet_wf_index k = function - | (Some (env, v, t), (env', (v', t', _))) when (v=v' && t=t') -> +let meet_wf_index k = function+ | (Some (env, v, t), (env', (v', t', _))) when (v=v' && t=t') -> env |> SM.filter (fun x _ -> SM.mem x env') |> (fun env' -> (env', v, t))- | (None, (env, (v, t, _))) -> + | (None, (env, (v, t, _))) -> (env, v, t)- | _ -> + | _ -> assertf "Conflicting v,t for WF %s" (Sy.to_string k) -let upds_wf_index z wm ks = - List.fold_left begin fun wm k -> +let upds_wf_index z wm ks =+ List.fold_left begin fun wm k -> SM.add k (meet_wf_index k (SM.maybe_find k wm, z)) wm end wm ks (* API *) let valid_after_substitution f su y =- Su.apply su y + Su.apply su y |> (function None -> [y] | Some ye -> E.support ye)- |> List.for_all f + |> List.for_all f -let kvars_of_bind (x, r) = +let kvars_of_bind (x, r) = let xv = (C.vv_of_reft r, A.eVar x) in C.kvars_of_reft r |>: (fun (su, k) -> (Su.extend su xv, k)) let kvars_of_c c =- (C.kvars_of_reft <| C.rhs_of_t c) ++ + (C.kvars_of_reft <| C.rhs_of_t c) ++ (Misc.flap kvars_of_bind <| C.kbindings_of_lhs c) (* MORE DEBUG NOISE -- NEVER DELETE! *) let pp_ikxts i k xts = F.printf "\n refine_wf_index removes at id = %d, k = %a, xs = %a\n" i Sy.print k- (Misc.pprint_many false ", " Sy.print) (List.map fst xts) - -let refine_wf_index wm c = + (Misc.pprint_many false ", " Sy.print) (List.map fst xts)++let refine_wf_index wm c = let senv = C.senv_of_t c in let ok z = SM.mem z senv in let ksus = kvars_of_c c in (* [(su, k)] *) List.fold_left begin fun wm (su, k) -> let (xts, v, t) = SM.safeFind k wm "refine_wf_index" in let (xts', dts) = Misc.tr_partition begin fun (x,t) -> A.Sort.is_kind t ||- valid_after_substitution ok su x - end xts + valid_after_substitution ok su x+ end xts in SM.add k (xts', v, t) wm- (* let xts' = Misc.filter (fun (x,t) -> A.Sort.is_kind t || valid_after_substitution ok su x) xts in - let _ = pp k xts; pp k xts' in - let _ = pp_ikxts (C.id_of_t c) k dts in + (* let xts' = Misc.filter (fun (x,t) -> A.Sort.is_kind t || valid_after_substitution ok su x) xts in+ let _ = pp k xts; pp k xts' in+ let _ = pp_ikxts (C.id_of_t c) k dts in *) end wm ksus -let create_wf_index_basic ws = +let create_wf_index_basic ws = List.fold_left begin fun wm w -> let env = SM.map C.sort_of_reft <| C.env_of_wf w in let r = C.reft_of_wf w in@@ -424,7 +424,7 @@ type qual_binding = (Sy.t * Sy.t) list -let is_valid_binding (xys : qual_binding) : bool = +let is_valid_binding (xys : qual_binding) : bool = List.for_all varmatch xys let valid_bindings ys (x,_) =@@ -440,7 +440,7 @@ xts (* >> F.printf "\n\ninst_qual: params q = %a: %a" Q.print q print_params *) |> List.map (valid_bindings ys) (* candidate bindings *)- |> Misc.product (* generate combinations *) + |> Misc.product (* generate combinations *) (* >> (List.iter (F.printf "\ninst_qual: pre-binds = %a\n" print_valid_bindings)) *) |> List.filter is_valid_binding (* remove bogus bindings *) (* >> (List.iter (F.printf "\ninst_qual: post-binds = %a\n" print_valid_bindings)) *)@@ -448,17 +448,17 @@ |> List.rev_map (fun xes -> Q.inst q (vve::xes)) (* quals *) (* >> (F.printf "\n\ninst_qual: result q = %a:\n%a DONE\n" Q.print q (Misc.pprint_many true "" Q.print)) *) -let inst_binds env = - env |> SM.to_list +let inst_binds env =+ env |> SM.to_list |> Misc.filter (not <.> A.Sort.is_func <.> snd) -let inst_ext env vv t qs = +let inst_ext env vv t qs = let _ = Misc.display_tick () in let ys = inst_binds env |>: fst in let env' = Misc.flip SM.maybe_find (SM.add vv t env) in qs |> List.filter (Q.sort_of_t <+> sort_compat t) |> Misc.flap (inst_qual env ys (A.eVar vv))- |> Misc.filter (wellformed_qual env') + |> Misc.filter (wellformed_qual env') (********************************************************************************) (****** Sort Based Qualifier Instantiation **************************************)@@ -472,24 +472,24 @@ let ext_bindings yts wkl (x, tx) = let yts = List.filter (fun (y,_) -> varmatch (x, y)) yts in Misc.tr_rev_flap (fun (su, xys) ->- Misc.map_partial (fun (y, ty) -> + Misc.map_partial (fun (y, ty) -> match A.Sort.unifyWith su [tx] [ty] with | None -> None | Some su' -> Some (su', (x,y) :: xys) ) yts- ) wkl + ) wkl -let inst_qual_sorted yts vv t q = +let inst_qual_sorted yts vv t q = let (qvv0, t0) :: xts = Q.all_params_of_t q in- match A.Sort.unify [t0] [t] with - | Some su0 -> + match A.Sort.unify [t0] [t] with+ | Some su0 -> xts |> List.fold_left (ext_bindings yts) [(su0, [(qvv0, vv)])] (* generate subs-bindings *) |> List.rev_map (List.rev <.> snd) (* extract sorted bindings *) |> List.rev_map (List.map (Misc.app_snd A.eVar)) (* instantiations *) |> List.rev_map (Q.inst q) (* quals *)- | None -> [] + | None -> [] -let inst_ext_sorted env vv t qs = +let inst_ext_sorted env vv t qs = let _ = Misc.display_tick () in let yts = inst_binds env in Misc.flap (inst_qual_sorted yts vv t) qs@@ -501,12 +501,12 @@ let inst_ext qs ckEnv env v t : Q.t list = let instf = if !Co.sorted_quals then inst_ext_sorted else inst_ext in let env' = Misc.flip SM.maybe_find (SM.add v t ckEnv) in- qs |> instf env v t - |> Misc.filter (wellformed_qual env') + qs |> instf env v t+ |> Misc.filter (wellformed_qual env') - + (*-let is_non_trivial_var me lps su = +let is_non_trivial_var me lps su = let cxs = SS.of_list <| Misc.flap P.support lps in let ok z = SS.mem z cxs in fun y _ -> valid_after_substitution ok su y@@ -519,9 +519,9 @@ (* RJ: DO NOT DELETE EVER! *)-let ppBinding k zs = - F.printf "ppBind %a := %a \n" - Sy.print k +let ppBinding k zs =+ F.printf "ppBind %a := %a \n"+ Sy.print k (Misc.pprint_many false ", " Q.print) zs (* API *)@@ -532,17 +532,17 @@ (* >> ppBinding k *) |> ((++) (SM.find_default [] k me.om)) - + (***************************************************************) (**************** Refinement ***********************************) (***************************************************************) (*** {{{ KEEP AROUND FOR DEBUG PRINTING SIGH. let rhs_cands me = function- | C.Kvar (su, k) -> - k + | C.Kvar (su, k) ->+ k (* >> (fun k -> Co.bprintflush mydebug ("rhs_cands: k = "^(Sy.to_string k)^"\n")) *)- |> p_read me + |> p_read me (* >> (fun xs -> Co.bprintflush mydebug ("rhs_cands: size="^(string_of_int (List.length xs))^" BEGIN \n")) *) |>: (Misc.app_snd (Misc.flip A.substs_pred su)) (* >> (fun xs -> Co.bprintflush mydebug ("rhs_cands: size="^(string_of_int (List.length xs))^" DONE\n")) *)@@ -557,10 +557,10 @@ List.exists begin function C.Conc _ -> false | C.Kvar (_,k) -> (bind_read me k = Bot) end ras- + let is_bot_lhs me c =- C.kbindings_of_lhs c - |>: snd + C.kbindings_of_lhs c+ |>: snd |> List.exists (is_bot_reft me) let is_bot_rhs me c =@@ -572,40 +572,40 @@ ((k, q), qp') let quals_of_bind me c lhs k su = function- | NonBot qs -> + | NonBot qs -> (qs, me)- | Bot -> + | Bot -> let qs = lazy_instantiate_with me c lhs k su in let (_, me) = p_update me [k] (qs |>: (fun q -> (k,q))) in (qs, me) (* only called when ALL RHS k are NONBOT *) let rhs_cands_noinst me = function- | C.Kvar (su, k) -> begin match bind_read me k with - | Bot -> assertf "rhs_cands_noinst" + | C.Kvar (su, k) -> begin match bind_read me k with+ | Bot -> assertf "rhs_cands_noinst" | NonBot qs -> qs |>: make_cand k su end | _ -> [] let rhs_cands_noinst me c = c |> C.rhs_of_t- |> thd3 + |> thd3 |> BS.time "rhs_cands" (Misc.flap (rhs_cands_noinst me)) (* only called when SOME RHS k is BOT *) let rhs_cands_inst c lhs me = function- | C.Conc _ -> + | C.Conc _ -> (me, [])- | C.Kvar (su, k) -> - let (qs, me) = SM.safeFind k me.m "rhs_cands" |> quals_of_bind me c lhs k su in + | C.Kvar (su, k) ->+ let (qs, me) = SM.safeFind k me.m "rhs_cands" |> quals_of_bind me c lhs k su in (me, qs |>: make_cand k su) let rhs_cands_inst me c lps = let (_, _, ras) = C.rhs_of_t c in- let (me, zs) = Misc.mapfold (rhs_cands_inst c lps) me ras in + let (me, zs) = Misc.mapfold (rhs_cands_inst c lps) me ras in (Misc.flatten zs, me) -let lhs_preds me c = +let lhs_preds me c = let lps = BS.time "preds_of_lhs" (C.preds_of_lhs (read me)) c in (lps, me) @@ -615,39 +615,39 @@ let senv = C.senv_of_t c in let rcs = Misc.filter (fun (_,p) -> C.wellformed_pred senv p) rcs in (true, me, lps, rcs)- -let refine_sort_first_time me c = ++let refine_sort_first_time me c = let (lps, me) = lhs_preds me c in- let rcs = rhs_cands_noinst me c in + let rcs = rhs_cands_noinst me c in let senv = C.senv_of_t c in let rcs' = Misc.filter (fun (_,p) -> C.wellformed_pred senv p) rcs in (List.length rcs != List.length rcs', me, lps, rcs') -let refine_sort_default me c = - let (lps, me) = lhs_preds me c in - let rcs = rhs_cands_noinst me c in +let refine_sort_default me c =+ let (lps, me) = lhs_preds me c in+ let rcs = rhs_cands_noinst me c in (false, me, lps, rcs) -let refine_sort me c = - if is_bot_rhs me c then +let refine_sort me c =+ if is_bot_rhs me c then refine_sort_bot_rhs me c else if not (IS.mem (C.id_of_t c) (me.seen)) then- refine_sort_first_time me c - else + refine_sort_first_time me c+ else refine_sort_default me c -let is_trivial_rhs me c = - let is_trivial_refa me = function - | C.Conc _ -> true - | C.Kvar (_,k) -> bind_read me k = NonBot [] - in +let is_trivial_rhs me c =+ let is_trivial_refa me = function+ | C.Conc _ -> true+ | C.Kvar (_,k) -> bind_read me k = NonBot []+ in C.rhs_of_t c- |> C.ras_of_reft - |> List.for_all (is_trivial_refa me) + |> C.ras_of_reft+ |> List.for_all (is_trivial_refa me) let is_trivial_c me c = is_bot_lhs me c || is_trivial_rhs me c -let refine_match me lps rcs = +let refine_match me lps rcs = let lt = PH.create 17 in let _ = List.iter (fun p -> PH.add lt p ()) lps in let (x1,x2) = List.partition (fun (_,p) -> PH.mem lt p) rcs in@@ -658,7 +658,7 @@ me.tpc#set_filter env vv lps rcs >> (fun _ -> me.stat_tp_refines += 1) >> (fun _ -> me.stat_imp_queries += List.length rcs)- >> (fun rv -> me.stat_valid_queries += List.length rv) + >> (fun rv -> me.stat_valid_queries += List.length rv) let refine_tp me c lps x2 = if C.is_simple c then@@ -669,9 +669,9 @@ let t = C.sort_of_t c in BS.time "check tp" (check_tp me senv vv t lps) x2 -let refine me c = - if is_trivial_c me c then - (false, me) +let refine me c =+ if is_trivial_c me c then+ (false, me) else let (ch, me, lps, rcs) = refine_sort me c in if BS.time "lhs_contra" (List.exists P.is_contra) lps then@@ -690,7 +690,7 @@ let (ch, me) = refine me c in (ch, {me with seen = IS.add (C.id_of_t c) me.seen}) -let refine me c = +let refine me c = let me = me |> (!Co.cex <?> cx_iter c) in let (b, me) = refine me c in let me = me |> (!Co.cex <?> cx_ctrace b c) in@@ -702,7 +702,7 @@ (************************* Satisfaction ************************) (***************************************************************) -let unsat me c = +let unsat me c = let s = read me in let (vv,t,_) = C.lhs_of_t c in let lps = C.preds_of_lhs s c in@@ -716,7 +716,7 @@ (****************************************************************) (*-let canonize_subs = +let canonize_subs = Su.to_list <+> List.sort (fun (x,_) (y,_) -> compare x y) let subst_leq =@@ -724,40 +724,40 @@ *) let args_leq q1 q2 =- let qArgs = List.map snd <.> Q.args_of_t in + let qArgs = List.map snd <.> Q.args_of_t in try List.for_all2 (=) (qArgs q1) (qArgs q2) with _ -> false (* P(v,x,y,z) => Q(v,x) if P => Q held and _intersection_ of args match. *)-let def_leq s q1 q2 = +let def_leq s q1 q2 = Q2S.mem (Q.name_of_t q1, Q.name_of_t q2) s.qleqs && args_leq q1 q2 -let pred_of_bind_name q = +let pred_of_bind_name q = let name = q |> Q.name_of_t in let args = q |> Q.args_of_t |> List.map snd in- A.pBexp (A.eApp (name, args)) + A.pBexp (A.eApp (name, args)) -let pred_of_bind_raw = Q.pred_of_t +let pred_of_bind_raw = Q.pred_of_t -let pred_of_bind q = - if !Co.shortannots - then pred_of_bind_name q - else pred_of_bind_raw q +let pred_of_bind q =+ if !Co.shortannots+ then pred_of_bind_name q+ else pred_of_bind_raw q -let min_binds_bot ds = +let min_binds_bot ds = match Misc.list_find_maybe (P.is_contra <.> pred_of_bind_raw) ds with | None -> ds- | Some d -> [d] + | Some d -> [d] (* API *) let min_binds s ds = ds |> min_binds_bot |> Misc.rootsBy (def_leq s)-let min_read s k = SM.find_default Bot k s.m |> function - | Bot -> [A.pFalse] +let min_read s k = SM.find_default Bot k s.m |> function+ | Bot -> [A.pFalse] | NonBot qs -> qs |> min_binds s |>: pred_of_bind let min_read s k = if !Co.minquals then min_read s k else read s k let min_read s k = BS.time "min_read" (min_read s) k let close_env qs sm =- qs |> Misc.flap (Q.pred_of_t <+> P.support) + qs |> Misc.flap (Q.pred_of_t <+> P.support) |> Misc.filter (not <.> Misc.flip SM.mem sm) |> Misc.map (fun x -> (x, Ast.Sort.t_int)) |> SM.of_list@@ -771,13 +771,13 @@ |> A.substs_pred (Q.pred_of_t q') |> (fun p' -> (q', p')) -let sm_of_qual sm q = - q |> Q.all_params_of_t - |> SM.of_list +let sm_of_qual sm q =+ q |> Q.all_params_of_t+ |> SM.of_list |> SM.extend sm (* check_leq tp sm q qs = [q' | q' <- qs, Z3 |- q => q'] *)-let check_leq (tp : ProverArch.prover) sm (q : Q.t) (qs : Q.t list) : Q.t list = +let check_leq (tp : ProverArch.prover) sm (q : Q.t) (qs : Q.t list) : Q.t list = let vv = Q.vv_of_t q in let lps = [Q.pred_of_t q] in let sm = q |> sm_of_qual sm |> close_env qs in@@ -797,6 +797,8 @@ let wellformed_qual sm q = let sm = sm_of_qual sm q in A.sortcheck_pred Theories.is_interp (fun x -> SM.maybe_find x sm) (Q.pred_of_t q)+(* >> (fun res ->F.printf "wellformed_qual: q = %a, res = %b\n" Q.print q res)+ *) let qleqs_of_qs ts sm cs ps qs = let tp = TpNull.create ts sm cs ps in@@ -804,7 +806,7 @@ |> Misc.groupby (List.map snd <.> Q.all_params_of_t) (* Q.sort_of_t *) |> Misc.flap (qimps_of_partition tp sm) |> Misc.flatten- |> Misc.map (Misc.map_pair Q.name_of_t) + |> Misc.map (Misc.map_pair Q.name_of_t) |> Q2S.of_list @@ -813,8 +815,8 @@ (*************************************************************************) let create_qleqs ts sm ps consts qs =- if !Co.minquals - then BS.time "Annots: make qleqs" (qleqs_of_qs ts sm consts ps) qs + if !Co.minquals+ then BS.time "Annots: make qleqs" (qleqs_of_qs ts sm consts ps) qs else Q2S.empty let create obm cs ws ts sm ps consts assm qs bm =@@ -824,12 +826,12 @@ ; assm = assm (*; qm = qs |>: Misc.pad_fst Q.name_of_t |> SM.of_list *) ; qs = qs- ; qleqs = Misc.with_ref_at Constants.strictsortcheck false - (fun () -> create_qleqs ts sm consts ps qs) + ; qleqs = Misc.with_ref_at Constants.strictsortcheck false+ (fun () -> create_qleqs ts sm consts ps qs) ; tpc = TpNull.create ts sm ps consts ; seen = IS.empty - (* Counterexamples *) + (* Counterexamples *) ; step = 0 ; ctrace = IM.empty ; lifespan = SM.empty@@ -840,7 +842,7 @@ ; stat_valid_queries = ref 0; stat_matches = ref 0 ; stat_umatches = ref 0; stat_unsatLHS = ref 0 ; stat_emptyRHS = ref 0- } + } (***************************************************************) (****************** Sort Check Based Refinement ****************)@@ -849,15 +851,15 @@ let refts_of_c c = [ C.lhs_of_t c ; C.rhs_of_t c] ++ (C.env_of_t c |> C.bindings_of_env |>: snd) -let refine_sort_reft env me ((vv, so, ras) as r) = - let env' = SM.add vv r env in +let refine_sort_reft env me ((vv, so, ras) as r) =+ let env' = SM.add vv r env in let ks = r |> C.kvars_of_reft |>: snd in (* let _ = let s = String.concat ", " (List.map Sy.to_string ks) in Co.bprintflush mydebug ("\n refine_sort_reft ks = "^s^"\n") in *)- ras + ras |> Misc.flap (rhs_cands me) (* OMFG blowup due to FLAP if kv appears multiple times...*) |> Misc.filter (fun (_, p) -> C.wellformed_pred env' p) |> List.rev_map fst-(* |> (fun xs -> Co.bprintflush mydebug (Printf.sprintf "refine_sort_reft map: size = %d\n" (List.length xs)); +(* |> (fun xs -> Co.bprintflush mydebug (Printf.sprintf "refine_sort_reft map: size = %d\n" (List.length xs)); List.rev_map fst xs) >> (fun _ -> Co.bprintflush mydebug "\n refine_sort_reft TICK 4 \n") *)@@ -868,7 +870,7 @@ let env = C.env_of_t c in c (* >> (fun _ -> Co.bprintflush mydebug ("\n refine_sort TICK 0 id = "^(string_of_int (C.id_of_t c))^"\n")) *) |> refts_of_c- |> List.fold_left (refine_sort_reft env) me + |> List.fold_left (refine_sort_reft env) me (* >> (fun _ -> Co.bprintflush mydebug "\n refine_sort TICK 2 \n") *) *) @@ -885,8 +887,8 @@ List.fold_left begin fun m k -> if not (SM.mem k fqm) then m else let false_qs = SM.safeFind k fqm "update_pruned 1" in- let qs = SM.safeFind k m "update_pruned 2" - |> List.filter (fun q -> (not (List.mem (k, q) false_qs))) + let qs = SM.safeFind k m "update_pruned 2"+ |> List.filter (fun q -> (not (List.mem (k, q) false_qs))) in SM.add k qs m end me.m ks @@ -921,15 +923,15 @@ *) (* LAZYINST: map each KVAR to BOT *)-let initial_solution c = +let initial_solution c = c.Cg.ws- |> Misc.flap kvars_of_wf + |> Misc.flap kvars_of_wf |>: (fun k -> (k, Bot)) |> SM.of_list (* API *) let create c = function- | None -> + | None -> initial_solution c |> create c.Cg.bm c.Cg.cs c.Cg.ws c.Cg.ts c.Cg.uops c.Cg.ps c.Cg.cons c.Cg.assm c.Cg.qs (* LAZYINST: this is factored into the canonical env for each K@@ -937,35 +939,35 @@ |> ((!Constants.refine_sort) <?> Misc.flip (List.fold_left refine_sort) c.Cg.cs) >> (fun _ -> Co.bprintflush mydebug "\nEND: refine_sort\n") *)- | _ -> assertf "PredAbs.create: does not support facts" + | _ -> assertf "PredAbs.create: does not support facts" (* API *) let empty () = create Cg.empty None (* API *)-let meet me you = {me with m = SM.extendWith (fun _ -> meet_bind) me.m you.m} +let meet me you = {me with m = SM.extendWith (fun _ -> meet_bind) me.m you.m} (****************************************************************) (************* Simplify Solution Using min_read *****************) (****************************************************************) -(* let minb s bs = min_binds s bs +(* let minb s bs = min_binds s bs >> Printf.printf "minBinds: [%a] \n\n" pprint_ds *) -let simplify s = { s with m = SM.map begin function - | Bot -> Bot +let simplify s = { s with m = SM.map begin function+ | Bot -> Bot | NonBot qs -> NonBot (min_binds s qs)- end s.m - } + end s.m+ } (************************************************************************) (****************** Counterexample Generation ***************************) (************************************************************************) - -let ctr_examples me cs ucs = - let cx = CX.create me.tpc (read me) cs me.ctrace me.lifespan in ++let ctr_examples me cs ucs =+ let cx = CX.create me.tpc (read me) cs me.ctrace me.lifespan in List.map (CX.explain cx) ucs @@ -973,24 +975,24 @@ (******************************** Profile/Stats ********************************) (*******************************************************************************) -let print_m ppf s = +let print_m ppf s = SM.iter begin fun k -> function | Bot -> F.fprintf ppf "solution: %a := [%a] \n\n" Sy.print k pprint_bind Bot- | NonBot ds -> ds + | NonBot ds -> ds |> (<?>) (!Co.minquals) (min_binds s)- |> F.fprintf ppf "solution: %a := [%a] \n\n" Sy.print k pprint_ds - end s.m - -let print_qs ppf s = + |> F.fprintf ppf "solution: %a := [%a] \n\n" Sy.print k pprint_ds+ end s.m++let print_qs ppf s = s.qs >> (fun _ -> F.fprintf ppf "//QUALIFIERS \n\n") |> F.fprintf ppf "%a" (Misc.pprint_many true "\n" Q.print)-(* |> List.iter (F.fprintf ppf "%a" Q.print) *) +(* |> List.iter (F.fprintf ppf "%a" Q.print) *) |> ignore (* API *) let print ppf s = s >> print_m ppf >> print_qs ppf |> ignore - + let botInt = function | Bot -> 1 | NonBot qs -> if List.exists (Q.pred_of_t <+> P.is_contra) qs then 1 else 0@@ -1001,19 +1003,19 @@ (* API *) let print_stats ppf me =- let (sum, max, min, bot) = + let (sum, max, min, bot) = (SM.fold (fun _ b x -> (+) x (bindSize b)) me.m 0, SM.fold (fun _ b x -> max x (bindSize b)) me.m min_int, SM.fold (fun _ b x -> min x (bindSize b)) me.m max_int, SM.fold (fun _ b x -> x + botInt b) me.m 0) in let n = SM.length me.m in let avg = (float_of_int sum) /. (float_of_int n) in- F.fprintf ppf "# Vars: (Total=%d, False=%d) Quals: (Total=%d, Avg=%f, Max=%d, Min=%d)\n" + F.fprintf ppf "# Vars: (Total=%d, False=%d) Quals: (Total=%d, Avg=%f, Max=%d, Min=%d)\n" n bot sum avg max min; F.fprintf ppf "#Iteration Profile = (si=%d tp=%d unsatLHS=%d emptyRHS=%d) \n" !(me.stat_simple_refines) !(me.stat_tp_refines) !(me.stat_unsatLHS) !(me.stat_emptyRHS);- F.fprintf ppf "#Queries: umatch=%d, match=%d, ask=%d, valid=%d\n" + F.fprintf ppf "#Queries: umatch=%d, match=%d, ask=%d, valid=%d\n" !(me.stat_umatches) !(me.stat_matches) !(me.stat_imp_queries) !(me.stat_valid_queries); me.tpc#print_stats ppf@@ -1025,8 +1027,8 @@ F.fprintf ppf "@[%a@] \n" print s; close_out oc -let key_of_quals qs = - qs |> List.map P.to_string +let key_of_quals qs =+ qs |> List.map P.to_string |> List.sort compare |> String.concat "," @@ -1034,15 +1036,13 @@ let mkbind qs = assertf "PredAbs.mkBind not supported in lazyinst" (* NonBot qs *)(* Misc.flatten <+> Misc.sort_and_compact *) (* API *)-let dump s = - s.m - |> SM.to_list - |> List.map (snd <+> preds_of_bind) +let dump s =+ s.m+ |> SM.to_list+ |> List.map (snd <+> preds_of_bind) |> Misc.groupby key_of_quals- |> List.map begin function - | [] -> assertf "impossible" + |> List.map begin function+ | [] -> assertf "impossible" | (ps::_ as pss) -> Co.bprintf mydebug "SolnCluster: preds %d = size %d \n" (List.length ps) (List.length pss) end |> ignore--
external/fixpoint/qualifier.ml view
@@ -1,23 +1,23 @@ (*- * Copyright © 2009-11 The Regents of the University of California. - * All rights reserved. + * Copyright © 2009-11 The Regents of the University of California.+ * All rights reserved. *- * Permission is hereby granted, without written agreement and without - * license or royalty fees, to use, copy, modify, and distribute this - * software and its documentation for any purpose, provided that the - * above copyright notice and the following two paragraphs appear in - * all copies of this software. - * - * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY - * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN - * IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION + * Permission is hereby granted, without written agreement and without+ * license or royalty fees, to use, copy, modify, and distribute this+ * software and its documentation for any purpose, provided that the+ * above copyright notice and the following two paragraphs appear in+ * all copies of this software.+ *+ * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY+ * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN+ * IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY+ * OF SUCH DAMAGE.+ *+ * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS+ * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION * TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. * *)@@ -46,13 +46,13 @@ (**************************************************************************) (***************************** Qualifiers *********************************) (**************************************************************************)- -type q = { name : Sy.t ++type q = { name : Sy.t ; vvar : Sy.t ; vsort : So.t ; params : (Sy.t * So.t) list ; pred : pred- ; args : expr list option + ; args : expr list option (* when args = Some es, es = vv'::[e1;...;en] where vv' is the applied vv and e1...en are the args applied to ~A1,...,~An *) }@@ -60,7 +60,7 @@ type t = q (* to appease the functor gods. *) -let rename = fun n -> fun q -> {q with name = n} +let rename = fun n -> fun q -> {q with name = n} let name_of_t = fun q -> q.name let vv_of_t = fun q -> q.vvar let sort_of_t = fun q -> q.vsort@@ -76,23 +76,23 @@ in Misc.combine "Qualifier.args_of_t" xs es let print_param ppf (x, t) =- F.fprintf ppf "%a:%a" Sy.print x So.print t + F.fprintf ppf "%a:%a" Sy.print x So.print t let print_params ppf args = F.fprintf ppf "%a" (Misc.pprint_many false ", " print_param) args let print_args ppf q =- q |> args_of_t |> List.map snd - |> F.fprintf ppf "%a(%a)" Sy.print q.name (Misc.pprint_many false ", " E.print) - -(* API *) -let print ppf q = - F.fprintf ppf "qualif %a(%a):%a" + q |> args_of_t |> List.map snd+ |> F.fprintf ppf "%a(%a)" Sy.print q.name (Misc.pprint_many false ", " E.print)++(* API *)+let print ppf q =+ F.fprintf ppf "qualif %a(%a):%a" Sy.print q.name- print_params (all_params_of_t q) + print_params (all_params_of_t q) P.print q.pred - + (**********************************************************************) (****************** Canonizing Wildcards (e.g. _ ---> ~A) *************) (**********************************************************************)@@ -103,18 +103,18 @@ let fresh = Misc.mk_string_factory "~AA" |> fst |> (fun f -> f <+> Sy.of_string <+> eVar) in let memo = Hashtbl.create 7 in function- | (Var x, _) when is_free params x && Hashtbl.mem memo x -> + | (Var x, _) when is_free params x && Hashtbl.mem memo x -> Hashtbl.find memo x | (Var x, _) when is_free params x && Sy.is_wild_fresh x ->- fresh () - | (Var x, _) when is_free params x && Sy.is_wild_any x -> - fresh () >> Hashtbl.replace memo x - | e -> e + fresh ()+ | (Var x, _) when is_free params x && Sy.is_wild_any x ->+ fresh () >> Hashtbl.replace memo x+ | e -> e (**************************************************************************) (*************** Expanding Away Sets of Ops and Rels **********************) (**************************************************************************)- + let expand_with_list f g = List.map f <+> Misc.cross_flatten <+> Misc.map g @@ -122,7 +122,7 @@ Misc.map_pair f <+> Misc.uncurry Misc.cross_product <+> Misc.map g let crunchExpr f e1s xs e2s =- List.map begin fun e1 -> + List.map begin fun e1 -> List.map begin fun e2 -> List.map begin fun x -> f (e1, x, e2)@@ -131,10 +131,10 @@ end e1s |> List.flatten |> List.flatten -let rec expand_p ((p,_) as pred) = match p with +let rec expand_p ((p,_) as pred) = match p with | And ps -> expand_ps pAnd ps | Or ps -> expand_ps pOr ps- | Not p -> expand_p p |> List.map pNot + | Not p -> expand_p p |> List.map pNot | Imp (p1,p2) -> expand_pp pImp (p1, p2) | Iff (p1,p2) -> expand_pp pIff (p1, p2) | Forall(qs, p) -> expand_p p |> List.map (fun p -> pForall (qs, p))@@ -148,13 +148,13 @@ and expand_e ((e,_) as expr) = match e with | MExp es -> Misc.flap expand_e es | App (f, es) -> expand_es (fun es -> eApp (f, es)) es- | Bin (e1, op, e2) -> expand_ep (fun (e1,e2) -> eBin (e1, op, e2)) (e1, e2) + | Bin (e1, op, e2) -> expand_ep (fun (e1,e2) -> eBin (e1, op, e2)) (e1, e2) | MBin (e1, ops, e2) -> let e1s, e2s = Misc.map_pair expand_e (e1, e2) in crunchExpr eBin e1s ops e2s | Fld (s, e) -> expand_e e |> List.map (fun e -> eFld (s,e)) | Cst (e, t) -> expand_e e |> List.map (fun e -> eCst (e,t)) | Ite (p,e1,e2) -> let e1s, e2s = Misc.map_pair expand_e (e1, e2) in- let ps = expand_p p in + let ps = expand_p p in List.map begin fun e1 -> List.map begin fun e2 -> List.map begin fun p ->@@ -171,7 +171,7 @@ and expand_ep x = expand_with_pair expand_e x (* API *)-let expand_qual q = +let expand_qual q = expand_p q.pred |> List.map (fun p -> {q with pred = p}) @@ -179,51 +179,51 @@ (*************** Expanding Away Sets of Ops and Rels **********************) (**************************************************************************) -let make_def_deps qnames q = +let make_def_deps qnames q = let res = ref [] in- let p' : pred = P.map begin function - | Bexp (App (f, args),_), _ - when SS.mem f qnames -> res := (f, args) :: !res; pTrue - | p -> p - end id q.pred - in (q.name, !res) + let p' : pred = P.map begin function+ | Bexp (App (f, args),_), _+ when SS.mem f qnames -> res := (f, args) :: !res; pTrue+ | p -> p+ end id q.pred+ in (q.name, !res) (* >> (fun (n, xs) -> F.printf "qdep %a = %a \n" Sy.print n (Misc.pprint_many false ", " Sy.print) (List.map fst xs) ) *) -let check_def_deps qm = +let check_def_deps qm = List.iter begin fun (n, fargs) -> List.iter begin fun (f, args) -> match SM.finds f qm with- | [q] -> asserts (List.length args = 1 + List.length q.params) + | [q] -> asserts (List.length args = 1 + List.length q.params) "Malformed Qualifier: %s with incorrect application of %s" (Sy.to_string n) (Sy.to_string f)- | _::_::_ -> assertf "Malformed Qualifier: %s refers to multiply defined %s" + | _::_::_ -> assertf "Malformed Qualifier: %s refers to multiply defined %s" (Sy.to_string n) (Sy.to_string f)- | _ -> () -(* | [] -> assertf "Malformed Qualifier: %s refers to unknown %s" + | _ -> ()+(* | [] -> assertf "Malformed Qualifier: %s refers to unknown %s" (Sy.to_string n) (Sy.to_string f) *)- + end fargs end -let order_by_defs qm qs = +let order_by_defs qm qs = let is = Misc.range 0 (List.length qs) in let qis = List.combine qs is in let i2q = qis |>: Misc.swap |> IM.of_list |> Misc.flip IM.find in- let i2s = i2q <+> name_of_t <+> Sy.to_string in - let n2i = qis |>: Misc.app_fst name_of_t |> SM.of_list + let i2s = i2q <+> name_of_t <+> Sy.to_string in+ let n2i = qis |>: Misc.app_fst name_of_t |> SM.of_list |> (fun m n -> SM.safeFind n m "order_by_defs") in- + let qnams= qs |>: name_of_t |> SS.of_list in let deps = qs |>: make_def_deps qnams >> check_def_deps qm in- let ijs = deps |> Misc.flap (fun (n, fargs) -> fargs |>: (fun (f,_) -> (n, f))) + let ijs = deps |> Misc.flap (fun (n, fargs) -> fargs |>: (fun (f,_) -> (n, f))) |> List.map (Misc.map_pair n2i) in- let irs = Fcommon.scc_rank "qualifier-deps" i2s is ijs in - Misc.fsort snd irs + let irs = Fcommon.scc_rank "qualifier-deps" i2s is ijs in+ Misc.fsort snd irs |>: (fst <+> i2q) (* >> (F.printf "ORDERED QUALS:\n%a\n" (Misc.pprint_many true "\n" print)) *) -let expand_def qm p = match p with +let expand_def qm p = match p with | Bexp (App (f, args),_), _ -> begin match SM.finds f qm with | _::_::_ -> assertf "Ambiguous Qualifier: %s" (Sy.to_string f)@@ -235,12 +235,12 @@ | [] -> p (* assertf "Unknown Qualifier: %s" (Sy.to_string f) *) end | _ -> p- + (* this MUST precede any renaming as renaming can screw up name resolution *)-let compile_definitions qs = +let compile_definitions qs = let qm = List.fold_left (fun qm q -> SM.adds q.name [q] qm) SM.empty qs in- let qs' = order_by_defs qm qs in - List.fold_left begin fun qm q -> + let qs' = order_by_defs qm qs in+ List.fold_left begin fun qm q -> let q' = {q with pred = P.map (expand_def qm) id q.pred } in SM.adds q.name [q'] qm end SM.empty qs'@@ -250,11 +250,11 @@ (************************* Normalize Qualifier Sets ***********************) (**************************************************************************) -let remove_duplicates qs = +let remove_duplicates qs = qs |> Misc.kgroupby (all_params_of_t <*> pred_of_t) |> List.map (fun (_,x::_) -> x) -let rename_qual q i = +let rename_qual q i = {q with name = Sy.suffix q.name (string_of_int i)} let uniquely_rename qs =@@ -262,26 +262,26 @@ if SM.mem q.name m then let i = SM.safeFind q.name m "uniquelyRename" in (SM.add q.name (i+1) m, rename_qual q i)- else + else (SM.add q.name 0 m, q)- end SM.empty qs + end SM.empty qs |> snd -let check_dup t q = - try +let check_dup t q =+ try let q' = Hashtbl.find t q.name in if (pred_of_t q' = pred_of_t q) then () else Format.printf "WARNING: duplicate qualifiers after normalization! (q = %a) (q' = %a)"- print q + print q print q' with Not_found -> () -let qualifMap_set, qualifMap_get = +let qualifMap_set, qualifMap_get = let t = Hashtbl.create 37 in ( (fun qs -> Hashtbl.clear t; List.iter (fun q -> check_dup t q; Hashtbl.replace t q.name q) qs)- , (fun n -> try Some (Hashtbl.find t n) - with Not_found -> (Format.printf "qualifMap_get fails on %a" Sy.print n; assert false) + , (fun n -> try Some (Hashtbl.find t n)+ with Not_found -> (Format.printf "qualifMap_get fails on %a" Sy.print n; assert false) ) ) @@ -294,16 +294,16 @@ |> remove_duplicates |> uniquely_rename >> qualifMap_set-(* >> (fun qs -> ticker += 1; Co.logPrintf "normalize (%d):\n%a" (!ticker) +(* >> (fun qs -> ticker += 1; Co.logPrintf "normalize (%d):\n%a" (!ticker) (Misc.pprint_many true "\n" print) qs; flush stdout) *) (* API *)-let expandPred n es = +let expandPred n es = n |> qualifMap_get |> Misc.maybe_map begin fun q -> let xs = List.map fst <| args_of_t q in- Misc.combine "expandPred" xs es - |> Ast.Subst.of_list + Misc.combine "expandPred" xs es+ |> Ast.Subst.of_list |> Ast.substs_pred (pred_of_t q) end @@ -311,7 +311,7 @@ (***************************** Create ********************************) (*********************************************************************) -let generalize_sorts vts = +let generalize_sorts vts = let vs, ts = List.split vts in let ts' = So.generalize ts in List.combine vs ts'@@ -320,7 +320,7 @@ let close_params vts p = p |> P.support- |> List.filter (Sy.is_wild <&&> is_free vts) + |> List.filter (Sy.is_wild <&&> is_free vts) |> List.map (fun x -> (x, So.t_int (* t_generic 0 causes blowup? *))) |> (@) vts (* Sy.SMap.of_list *) @@ -330,26 +330,26 @@ let vts = close_params vts p in let (v,t)::vts = generalize_sorts ((v,t)::vts) in let _ = asserts (Misc.distinct vts) "Error: Q.create duplicate params %s \n" (Sy.to_string n)- in { name = n + in { name = n ; vvar = v ; vsort = t ; pred = p- ; params = vts + ; params = vts ; args = None } (* DEBUG ONLY *) let printb ppf (x, e) =- F.fprintf ppf "%a:%a" Sy.print x E.print e + F.fprintf ppf "%a:%a" Sy.print x E.print e let printbs ppf args = F.fprintf ppf "%a" (Misc.pprint_many false ", " printb) args (* API *) let inst q args =- let _ = if mydebug then F.printf "\nQ.inst with <<%a>>\n" printbs args in - let xes = try q |> all_params_of_t |> List.map (fun (x,_) -> (x, List.assoc x args)) - with Not_found -> - let _ = F.printf "Error: Q.inst with bad args %a <<%a>>" print q printbs args - in assertf "Error: Q.inst with bad args \n" + let _ = if mydebug then F.printf "\nQ.inst with <<%a>>\n" printbs args in+ let xes = try q |> all_params_of_t |> List.map (fun (x,_) -> (x, List.assoc x args))+ with Not_found ->+ let _ = F.printf "Error: Q.inst with bad args %a <<%a>>" print q printbs args+ in assertf "Error: Q.inst with bad args \n" in let v = match xes with (_, (Var v, _)) :: _ -> v | _ -> assertf "Error: Q.inst with non-vvar arg" in let p = xes |> Su.of_list |> Ast.substs_pred q.pred in@@ -358,9 +358,8 @@ module QSet = Misc.ESet (struct type t = q- let compare q1 q2 = - if (q1.name = q2.name) - then compare q1.args q2.args - else compare q1.name q2.name + let compare q1 q2 =+ if (q1.name = q2.name)+ then compare q1.args q2.args+ else compare q1.name q2.name end)-
external/fixpoint/smtLIB2.ml view
@@ -45,7 +45,7 @@ let spr = Printf.sprintf -let mydebug = false +let mydebug = false let nb_unsat = ref 0 let nb_pop = ref 0@@ -57,8 +57,8 @@ type symbol = string (* Sy.t *) type sort = string (* So.t *)-type ast = string (* E of A.expr | P of A.pred *) -type fun_decl = symbol +type ast = string (* E of A.expr | P of A.pred *)+type fun_decl = symbol type cmd = Push | Pop@@ -67,13 +67,13 @@ | AssertCnstr of ast | Distinct of ast list (* {v: ast list | (len v) >= 2} *) -type resp = Ok - | Sat - | Unsat +type resp = Ok+ | Sat+ | Unsat | Unknown | Error of string -type solver = Z3 | Mathsat | Cvc4 +type solver = Z3 | Mathsat | Cvc4 type context = { cin : in_channel ; cout : out_channel@@ -110,7 +110,7 @@ let sel = "smt_map_sel" let sto = "smt_map_sto" -(* +(* (define-fun smt_set_emp () Set ((as const Set) false)) (define-fun smt_set_mem ((x Elt) (s Set)) Bool (select s x)) (define-fun smt_set_add ((s Set) (x Elt)) Set (store s x true))@@ -124,19 +124,19 @@ let (++) = List.append (* array preamble *)-let array_preamble _ = +let array_preamble _ = if not !Co.map_theory then [] else- [ spr "(define-sort %s () (Array %s %s))" - map elt elt + [ spr "(define-sort %s () (Array %s %s))"+ map elt elt ; spr "(define-fun %s ((m %s) (k %s)) %s (select m k))"- sel map elt elt + sel map elt elt ; spr "(define-fun %s ((m %s) (k %s) (v %s)) %s (store m k v))" sto map elt elt map ] (* z3 specific *)-let z3_preamble _ +let z3_preamble _ = [ "(set-option :auto-config false)" ; "(set-option :model true)" ; "(set-option :model.partial false)"@@ -144,10 +144,10 @@ ] ++ if not !Co.set_theory then [] else [ spr "(define-sort %s () Int)" elt- ; spr "(define-sort %s () (Array %s Bool))" + ; spr "(define-sort %s () (Array %s Bool))" set elt- ; spr "(define-fun %s () %s ((as const %s) false))" - emp set set + ; spr "(define-fun %s () %s ((as const %s) false))"+ emp set set ; spr "(define-fun %s ((x %s) (s %s)) Bool (select s x))" mem elt set ; spr "(define-fun %s ((s %s) (x %s)) %s (store s x true))"@@ -161,17 +161,17 @@ ; spr "(define-fun %s ((s1 %s) (s2 %s)) %s (%s s1 (%s s2)))" dif set set set cap com ; spr "(define-fun %s ((s1 %s) (s2 %s)) Bool (= %s (%s s1 s2)))"- sub set set emp dif + sub set set emp dif ] ++ array_preamble () (* cvc4 specific *)-let cvc4_preamble _ +let cvc4_preamble _ = if not !Co.set_theory then [] else [ spr "(set-logic QF_AUFNIRAFS)" ; spr "(define-sort %s () Int)" elt- ; spr "(define-sort %s () (Set %s))" + ; spr "(define-sort %s () (Set %s))" set elt ; spr "(define-fun %s () %s (as emptyset (Set %s)))" emp set elt@@ -191,54 +191,54 @@ sub set set ] ++ array_preamble () -let smtlib_preamble +let smtlib_preamble = [ spr "(set-logic QF_UFLIA)" ; spr "(define-sort %s () Int)" elt- ; spr "(define-sort %s () Int)" set + ; spr "(define-sort %s () Int)" set ; spr "(declare-fun %s () %s)" emp set ; spr "(declare-fun %s (%s %s) %s)" add set elt set ; spr "(declare-fun %s (%s %s) %s)" cup set set set ; spr "(declare-fun %s (%s %s) %s)" cap set set set ; spr "(declare-fun %s (%s %s) %s)" dif set set set- ; spr "(declare-fun %s (%s %s) Bool)" sub set set - ; spr "(declare-fun %s (%s %s) Bool)" mem elt set - ; spr "(declare-fun %s (%s %s) %s)" sel map elt elt - ; spr "(declare-fun %s (%s %s %s) %s)" sto map elt elt map - - (* HIDE? - ; spr "(assert (forall ((x %s)) (not (%s x %s))))" + ; spr "(declare-fun %s (%s %s) Bool)" sub set set+ ; spr "(declare-fun %s (%s %s) Bool)" mem elt set+ ; spr "(declare-fun %s (%s %s) %s)" sel map elt elt+ ; spr "(declare-fun %s (%s %s %s) %s)" sto map elt elt map++ (* HIDE?+ ; spr "(assert (forall ((x %s)) (not (%s x %s))))" elt mem emp- ; spr "(assert (forall ((x %s) (s1 %s) (s2 %s)) + ; spr "(assert (forall ((x %s) (s1 %s) (s2 %s)) (= (%s x (%s s1 s2)) (or (%s x s1) (%s x s2)))))" elt set set mem cup mem mem- ; spr "(assert (forall ((x %s) (s1 %s) (s2 %s)) + ; spr "(assert (forall ((x %s) (s1 %s) (s2 %s)) (= (%s x (%s s1 s2)) (and (%s x s1) (%s x s2)))))" elt set set mem cap mem mem- ; spr "(assert (forall ((x %s) (s1 %s) (s2 %s)) + ; spr "(assert (forall ((x %s) (s1 %s) (s2 %s)) (= (%s x (%s s1 s2)) (and (%s x s1) (not (%s x s2))))))" elt set set mem dif mem mem- ; spr "(assert (forall ((x %s) (s %s) (y %s)) + ; spr "(assert (forall ((x %s) (s %s) (y %s)) (= (%s x (%s s y)) (or (%s x s) (= x y)))))"- elt set elt mem add mem + elt set elt mem add mem *)- ] + ] let mkSetSort _ _ = set let mkEmptySet _ _ = emp let mkSetAdd _ s x = spr "(%s %s %s)" add s x-let mkSetMem _ x s = spr "(%s %s %s)" mem x s +let mkSetMem _ x s = spr "(%s %s %s)" mem x s let mkSetCup _ s t = spr "(%s %s %s)" cup s t let mkSetCap _ s t = spr "(%s %s %s)" cap s t let mkSetDif _ s t = spr "(%s %s %s)" dif s t let mkSetSub _ s t = spr "(%s %s %s)" sub s t -let mkMapSort c k v = map -let mkMapSelect c m k = spr "(%s %s %s)" sel m k +let mkMapSort c k v = map+let mkMapSelect c m k = spr "(%s %s %s)" sel m k let mkMapStore c m k v = spr "(%s %s %s %s)" sto m k v -let mkSizeSort _ n = spr "%d" n -let mkBitSort _ s = spr "(_ BitVec %s)" s +let mkSizeSort _ n = spr "%d" n+let mkBitSort _ s = spr "(_ BitVec %s)" s let mkBitAnd _ x y = spr "(bvand %s %s)" x y let mkBitOr _ x y = spr "(bvor %s %s)" x y @@ -247,7 +247,7 @@ (**************** SMT IO ******************************************) (** https://raw.github.com/ravichugh/djs/master/src/zzz.ml ********) (******************************************************************)- + (* "z3 -smt2 -in" *) (* "z3 -smtc SOFT_TIMEOUT=1000 -in" *) (* "z3 -smtc -in MBQI=false" *)@@ -260,11 +260,11 @@ let smt_preamble = function | Z3 -> z3_preamble () | Cvc4 -> cvc4_preamble ()- | _ -> smtlib_preamble + | _ -> smtlib_preamble -let smt_write_raw me s = - output_now me.clog s; +let smt_write_raw me s =+ output_now me.clog s; output_now me.cout s (* copied from String.trim in ocaml-4.0 since mingw-ocaml uses 3.x *)@@ -289,7 +289,7 @@ "" (* strip off trailing whitespace, e.g. \r on windows.. *)-let smt_read_raw me = +let smt_read_raw me = trim (input_line me.cin) let smt_write me ?nl:(nl=true) ?tab:(tab=false) s =@@ -301,61 +301,61 @@ = match smt_read_raw me with | "sat" -> Sat | "unsat" -> Unsat- | "success" -> smt_read me + | "success" -> smt_read me | "unknown" -> Unknown | s -> Error s (* val interact : context -> cmd -> resp *)-let interact me = function - | Declare (x, ts, t) -> +let interact me = function+ | Declare (x, ts, t) -> let _ = smt_write me <| spr "(declare-fun %s (%s) %s)" x (String.concat " " ts) t in- Ok - | Push -> + Ok+ | Push -> let _ = smt_write me <| "(push 1)" in Ok- | Pop -> + | Pop -> let _ = smt_write me <| "(pop 1)" in Ok- | CheckSat -> + | CheckSat -> let _ = smt_write me <| "(check-sat)" in- smt_read me - | AssertCnstr a -> + smt_read me+ | AssertCnstr a -> let _ = smt_write me <| spr "(assert %s)" a in Ok- | Distinct az -> + | Distinct az -> let _ = smt_write me <| spr "(assert (distinct %s))" (String.concat " " az) in Ok (* API *)-let smt_decl me x ts t +let smt_decl me x ts t = match interact me (Declare (x, ts, t)) with | Ok -> () | _ -> assertf "crash: SMTLIB2 smt_decl" (* API *)-let smt_push me +let smt_push me = match interact me Push with- | Ok -> incr nb_push; () + | Ok -> incr nb_push; () | _ -> assertf "crash: SMTLIB2 smt_push" (* API *)-let smt_pop me +let smt_pop me = match interact me Pop with- | Ok -> incr nb_pop; () + | Ok -> incr nb_pop; () | _ -> assertf "crash: SMTLIB2 smt_pop" (* API *)-let smt_check_unsat me +let smt_check_unsat me = match interact me CheckSat with | Unsat -> true | Sat -> false- | Unknown -> false + | Unknown -> false | e -> assertf "crash: SMTLIB2 smt_check_unsat %s" (respString e) (* API *)-let smt_assert_cnstr me p +let smt_assert_cnstr me p = match interact me (AssertCnstr p) with | Ok -> () | _ -> assertf "crash: SMTLIB2 smt_assert_cnstr"@@ -388,22 +388,22 @@ (***********************************************************************) let stringSymbol _ s = s-let astString _ a = a -let sortString _ s = s +let astString _ a = a+let sortString _ s = s let isBool c a = failwith "TODO:SMTLib2.isBool" let boundVar me i t = failwith "TODO:SMTLib2.boundVar" let var me x t =- let _ = smt_decl me x [] t in - x + let _ = smt_decl me x [] t in+ x let funcDecl me s ta t = let _ = smt_decl me s (Array.to_list ta) t in s -let mkIntSort _ = "Int" -let mkRealSort _ = "Real" -let mkBoolSort _ = "Bool" +let mkIntSort _ = "Int"+let mkRealSort _ = "Real"+let mkBoolSort _ = "Bool" let mkInt _ i _ = if i >= 0 then string_of_int i else spr "(- %d)" (abs i)@@ -411,27 +411,27 @@ else spr "(- %s)" (string_of_float (i *. -1.0) ^ "0") let mkLit _ l _ = l- + let mkTrue _ = "true"-let mkFalse _ = "false" +let mkFalse _ = "false" let mkAll _ _ _ _ = failwith "TODO:SMTLib2.mkAll" -let mkRel _ r a1 a2 - = match r with - | A.Eq - | A.Ueq -> spr "(= %s %s)" a1 a2 - | A.Ne - | A.Une -> spr "(not (= %s %s))" a1 a2 - | A.Gt -> spr "(> %s %s)" a1 a2 - | A.Ge -> spr "(>= %s %s)" a1 a2 - | A.Lt -> spr "(< %s %s)" a1 a2 - | A.Le -> spr "(<= %s %s)" a1 a2 +let mkRel _ r a1 a2+ = match r with+ | A.Eq+ | A.Ueq -> spr "(= %s %s)" a1 a2+ | A.Ne+ | A.Une -> spr "(not (= %s %s))" a1 a2+ | A.Gt -> spr "(> %s %s)" a1 a2+ | A.Ge -> spr "(>= %s %s)" a1 a2+ | A.Lt -> spr "(< %s %s)" a1 a2+ | A.Le -> spr "(<= %s %s)" a1 a2 let mkApp _ f = function- | [] -> f + | [] -> f | az -> spr "(%s %s)" f (String.concat " " az) let opStr = function@@ -443,30 +443,30 @@ let mkOp op a1 a2 = spr "(%s %s %s)" (opStr op) a1 a2- -let mkMul _ = mkOp A.Times ++let mkMul _ = mkOp A.Times let mkDiv _ = mkOp A.Div let mkAdd _ = mkOp A.Plus let mkSub _ = mkOp A.Minus let mkMod _ = mkOp A.Mod -let mkIte _ a1 a2 a3 +let mkIte _ a1 a2 a3 = spr "(ite %s %s %s)" a1 a2 a3 -let mkNot _ a - = spr "(not %s)" a +let mkNot _ a+ = spr "(not %s)" a -let mkAnd _ az - = spr "(and %s)" (String.concat " " az) +let mkAnd _ az+ = spr "(and %s)" (String.concat " " az) -let mkOr _ az - = spr "(or %s)" (String.concat " " az) +let mkOr _ az+ = spr "(or %s)" (String.concat " " az) -let mkImp _ a1 a2 - = spr "(=> %s %s)" a1 a2 +let mkImp _ a1 a2+ = spr "(=> %s %s)" a1 a2 -let mkIff _ a1 a2 - = spr "(= %s %s)" a1 a2 +let mkIff _ a1 a2+ = spr "(= %s %s)" a1 a2 (*******************************************************************) (*********************** Queries ***********************************)@@ -475,15 +475,15 @@ let us_ref = ref 0 (* API *)-let unsat me = - let _ = if mydebug then begin +let unsat me =+ let _ = if mydebug then begin Printf.printf "[%d] UNSAT 1 " (us_ref += 1); flush stdout- end + end in let rv = BS.time "SMT.check_unsat" smt_check_unsat me in let _ = if mydebug then (Printf.printf "UNSAT 2 \n"; flush stdout) in- let _ = if rv then ignore (nb_unsat += 1) in + let _ = if rv then ignore (nb_unsat += 1) in rv (* API *)@@ -493,21 +493,21 @@ asserts (not (unsat me)) "ERROR: Axiom makes background theory inconsistent!" (* API *)-let assertDistinct me = function +let assertDistinct me = function | ((x1::x2::_) as az) -> smt_assert_distinct me az | _ -> () (* API *)-let bracket me f +let bracket me f = Misc.bracket (fun _ -> smt_push me) (fun _ -> smt_pop me) f (* API *)-let assertPreds me ps +let assertPreds me ps = List.iter (fun p -> BS.time "assertPreds" (smt_assert_cnstr me) p) ps (* API *) let print_stats ppf () =- F.fprintf ppf "SMT stats: pushes=%d, pops=%d, unsats=%d \n" + F.fprintf ppf "SMT stats: pushes=%d, pops=%d, unsats=%d \n" !nb_push !nb_pop !nb_unsat end
external/fixpoint/smtZ3.ml view
@@ -30,12 +30,12 @@ module SMTZ3 : ProverArch.SMTSOLVER = struct type context = ()-type symbol = () -type sort = () -type ast = () -type fun_decl = () +type symbol = ()+type sort = ()+type ast = ()+type fun_decl = () -let var _ = failwith msg +let var _ = failwith msg let boundVar _ = failwith msg let stringSymbol _ = failwith msg let funcDecl _ = failwith msg@@ -43,22 +43,22 @@ let isInt _ = failwith msg let mkAll _ = failwith msg let mkRel _ = failwith msg-let mkApp _ = failwith msg +let mkApp _ = failwith msg let mkMul _ = failwith msg let mkDiv _ = failwith msg let mkAdd _ = failwith msg let mkSub _ = failwith msg let mkMod _ = failwith msg let mkIte _ = failwith msg-let mkInt _ = failwith msg -let mkLit _ = failwith msg -let mkReal _ = failwith msg +let mkInt _ = failwith msg+let mkLit _ = failwith msg+let mkReal _ = failwith msg let mkTrue _ = failwith msg let mkFalse _ = failwith msg let mkNot _ = failwith msg-let mkAnd _ = failwith msg -let mkOr _ = failwith msg -let mkImp _ = failwith msg +let mkAnd _ = failwith msg+let mkOr _ = failwith msg+let mkImp _ = failwith msg let mkIff _ = failwith msg let astString _ = failwith msg let sortString _ = failwith msg@@ -81,12 +81,12 @@ let mkBitAnd _ = failwith msg let mkBitOr _ = failwith msg let mkContext _ = failwith msg-let unsat _ = failwith msg +let unsat _ = failwith msg let assertAxiom _ = failwith msg let assertDistinct _ = failwith msg let bracket _ = failwith msg let assertPreds _ = failwith msg-let valid _ = failwith msg +let valid _ = failwith msg let contra _ = failwith msg let print_stats _ = failwith msg
external/fixpoint/smtZ3.nomem.ml view
@@ -30,12 +30,12 @@ module SMTZ3 : ProverArch.SMTSOLVER = struct type context = ()-type symbol = () -type sort = () -type ast = () -type fun_decl = () +type symbol = ()+type sort = ()+type ast = ()+type fun_decl = () -let var _ = failwith msg +let var _ = failwith msg let boundVar _ = failwith msg let stringSymbol _ = failwith msg let funcDecl _ = failwith msg@@ -43,22 +43,22 @@ let isInt _ = failwith msg let mkAll _ = failwith msg let mkRel _ = failwith msg-let mkApp _ = failwith msg +let mkApp _ = failwith msg let mkMul _ = failwith msg let mkDiv _ = failwith msg let mkAdd _ = failwith msg let mkSub _ = failwith msg let mkMod _ = failwith msg let mkIte _ = failwith msg-let mkInt _ = failwith msg -let mkLit _ = failwith msg -let mkReal _ = failwith msg +let mkInt _ = failwith msg+let mkLit _ = failwith msg+let mkReal _ = failwith msg let mkTrue _ = failwith msg let mkFalse _ = failwith msg let mkNot _ = failwith msg-let mkAnd _ = failwith msg -let mkOr _ = failwith msg -let mkImp _ = failwith msg +let mkAnd _ = failwith msg+let mkOr _ = failwith msg+let mkImp _ = failwith msg let mkIff _ = failwith msg let astString _ = failwith msg let sortString _ = failwith msg@@ -81,12 +81,12 @@ let mkBitAnd _ = failwith msg let mkBitOr _ = failwith msg let mkContext _ = failwith msg-let unsat _ = failwith msg +let unsat _ = failwith msg let assertAxiom _ = failwith msg let assertDistinct _ = failwith msg let bracket _ = failwith msg let assertPreds _ = failwith msg-let valid _ = failwith msg +let valid _ = failwith msg let contra _ = failwith msg let print_stats _ = failwith msg
external/fixpoint/tpGen.ml view
@@ -32,18 +32,18 @@ module SM = Sy.SMap module P = A.Predicate module E = A.Expression-module Misc = FixMisc +module Misc = FixMisc module SSM = Misc.StringMap module SMT = SmtZ3.SMTZ3 open Misc.Ops open ProverArch -let mydebug = false +let mydebug = false module MakeProver(SMT : SMTSOLVER) : PROVER = struct - module Th = Theories.MakeTheory(SMT) + module Th = Theories.MakeTheory(SMT) (*************************************************************************) (*************************** Type Definitions ****************************)@@ -53,7 +53,7 @@ type var_ast = Const of SMT.ast | Bound of int * So.t -type t = { +type t = { c : SMT.context; tint : SMT.sort; treal : SMT.sort;@@ -72,12 +72,12 @@ (*************************************************************************) let pprint_decl ppf = function- | Vbl (x, t) -> F.fprintf ppf "%a:%a" Sy.print x So.print t - | Barrier -> F.fprintf ppf "----@." + | Vbl (x, t) -> F.fprintf ppf "%a:%a" Sy.print x So.print t+ | Barrier -> F.fprintf ppf "----@." | Fun (s, i) -> F.fprintf ppf "%a[%i]" Sy.print s i let dump_decls me =- F.printf "Vars: %a" (Misc.pprint_many true "," pprint_decl) me.vars + F.printf "Vars: %a" (Misc.pprint_many true "," pprint_decl) me.vars (************************************************************************) (***************************** Stats Counters **************************)@@ -97,11 +97,11 @@ let axioms = [] (* TBD these are related to ML and should be in DSOLVE, not here *)-let builtins = - SM.empty +let builtins =+ SM.empty |> SM.add tag_n (So.t_func 0 [So.t_obj; So.t_int])- |> SM.add div_n (So.t_func 0 [So.t_int; So.t_int; So.t_int]) - |> SM.add mul_n (So.t_func 0 [So.t_int; So.t_int; So.t_int]) + |> SM.add div_n (So.t_func 0 [So.t_int; So.t_int; So.t_int])+ |> SM.add mul_n (So.t_func 0 [So.t_int; So.t_int; So.t_int]) let select_t = So.t_func 0 [So.t_int; So.t_int] @@ -110,7 +110,7 @@ (fun f -> Sy.to_string f |> (^) (ss ^ "_") |> Sy.of_string), (fun s -> Sy.to_string s |> Misc.is_prefix ss) -let fresh = +let fresh = let x = ref 0 in fun v -> incr x; (v^(string_of_int !x)) @@ -119,35 +119,35 @@ (*************************************************************************) let varSort env s =- try SM.find s env with Not_found -> - failure "ERROR: varSort cannot type %s in TPZ3 \n" (Sy.to_string s) + try SM.find s env with Not_found ->+ failure "ERROR: varSort cannot type %s in TPZ3 \n" (Sy.to_string s) let funSort env s =- try SM.find s builtins with Not_found -> - try SM.find s env with Not_found -> - if is_select s then select_t else - failure "ERROR: could not type function %s in TPZ3 \n" (Sy.to_string s) + try SM.find s builtins with Not_found ->+ try SM.find s env with Not_found ->+ if is_select s then select_t else+ failure "ERROR: could not type function %s in TPZ3 \n" (Sy.to_string s) let rec z3Type me t =- Misc.do_memo me.tydt begin fun t -> + Misc.do_memo me.tydt begin fun t -> if So.is_bool t then me.tbool else if So.is_int t then me.tint else if So.is_real t then me.treal else Misc.maybe_default (z3TypeThy me t) me.tint- (* match z3TypeThy me t with + (* match z3TypeThy me t with | Some t' -> t'- | None -> me.tint *) + | None -> me.tint *) end t t and z3TypeThy me t = match So.app_of_t t with- | Some (c, ts) when H.mem me.thy_sortm c -> + | Some (c, ts) when H.mem me.thy_sortm c -> let def = H.find me.thy_sortm c in let zts = List.map (z3Type me) ts in Some (Th.mk_thy_sort def me.c zts) | _ ->- None - + None+ (***********************************************************************) (********************** Identifiers ************************************) (***********************************************************************)@@ -157,14 +157,14 @@ let z3Var_memo me env x = let vx = getVbl env x in Misc.do_memo me.vart- (fun () -> + (fun () -> let t = x |> varSort env |> z3Type me in- let sym = fresh "z3v" + let sym = fresh "z3v" (* >> F.printf "z3Var_memo: %a :-> %s\n" Sy.print x *)- |> SMT.stringSymbol me.c in + |> SMT.stringSymbol me.c in let rv = Const (SMT.var me.c sym t) in- let _ = me.vars <- vx :: me.vars in - rv) + let _ = me.vars <- vx :: me.vars in+ rv) () vx let z3Var me env x =@@ -173,10 +173,10 @@ | Bound (b, t) -> SMT.boundVar me.c (me.bnd - b) (z3Type me t) -let z3Fun me env p t k = - Misc.do_memo me.funt begin fun _ -> +let z3Fun me env p t k =+ Misc.do_memo me.funt begin fun _ -> match So.func_of_t t with- | None -> assertf "MATCH ERROR: z3ArgTypes" + | None -> assertf "MATCH ERROR: z3ArgTypes" | Some (_, ts, rt) -> let ts = List.map (z3Type me) ts in let rt = z3Type me rt in@@ -193,38 +193,46 @@ let opt_to_string p = function | None -> "none" | Some x -> p x- + exception Z3RelTypeError -let pred_sort env p = - A.sortcheck_pred Theories.is_interp (Misc.flip SM.maybe_find env) p +let pred_sort env p =+ A.sortcheck_pred Theories.is_interp (Misc.flip SM.maybe_find env) p let app_sort env tyo f es = A.sortcheck_app Theories.is_interp (Misc.flip SM.maybe_find env) tyo f es+(* >> (fun so -> let _ = F.printf "app_sort [f = %a es = %a] = %a\n"+ Sy.print f+ (Misc.pprint_many false ", " E.print) es+ (Misc.pprint_maybe So.print) (Misc.maybe_map snd so)+ in+ ()+ )+ *) let expr_sort env = function- | A.App (f, es), _ -> Misc.maybe_map snd <| app_sort env None f es + | A.App (f, es), _ -> Misc.maybe_map snd <| app_sort env None f es | e -> A.sortcheck_expr Theories.is_interp (Misc.flip SM.maybe_find env) e let z3Bind me env x t = let vx = Vbl (x, varSort env x) in- me.bnd <- me.bnd + 1; - H.replace me.vart vx (Bound (me.bnd, t)); + me.bnd <- me.bnd + 1;+ H.replace me.vart vx (Bound (me.bnd, t)); me.vars <- vx :: me.vars; SMT.stringSymbol me.c (fresh "z3b") let rec z3Rel me env (e1, r, e2) = let p = A.pAtom (e1, r, e2) in- let ok = pred_sort env p in + let ok = pred_sort env p in (* let _ = F.printf "z3Rel: e = %a, res = %b \n" P.print p ok in let _ = F.print_flush () in *) - if ok then + if ok then z3Rel_cast me env (e1, r, e2) (* z3Rel_real me env (e1, r, e2) *) (* SMT.mkRel me.c r (z3Exp me env e1) (z3Exp me env e2) *)- else begin + else begin SM.iter (fun s t -> F.printf "@[%a :: %a@]@." Sy.print s So.print t) env; F.printf "@[%a@]@.@." P.print (A.pAtom (e1, r, e2)); F.print_flush ();@@ -236,17 +244,19 @@ and z3Rel_cast me env = function | (e1, A.Eq, e2) -> begin- let (t1o, t2o) = (expr_sort env e1, expr_sort env e2) in - (* let _ = F.printf "z3Rel_cast: t1o = %s, t2o = %s \n" - (opt_to_string So.to_string t1o) (opt_to_string So.to_string t2o) in+ let (t1o, t2o) = (expr_sort env e1, expr_sort env e2) in+ (*+ let _ = F.printf "z3Rel_cast: t1o = %s, t2o = %s \n"+ (opt_to_string So.to_string t1o)+ (opt_to_string So.to_string t2o) in *) match (t1o, t2o) with- | (Some t , None ) -> z3Rel_real me env (e1, A.Eq, A.eCst (e2, t)) + | (Some t , None ) -> z3Rel_real me env (e1, A.Eq, A.eCst (e2, t)) | (None , Some t) -> z3Rel_real me env (A.eCst (e1, t), A.Eq, e2)- | (_ , _ ) -> z3Rel_real me env (e1, A.Eq, e2) + | (_ , _ ) -> z3Rel_real me env (e1, A.Eq, e2) end- | (e1, r, e2) -> - z3Rel_real me env (e1, r, e2) + | (e1, r, e2) ->+ z3Rel_real me env (e1, r, e2) and z3Rel_real me env (e1, r, e2) = (* let _ = F.printf "z3Rel_real: e1 = %s, e2 = %s \n"@@ -260,9 +270,9 @@ let cf = z3Fun me env p t (List.length zes) in SMT.mkApp me.c cf zes -and z3AppThy me env def tyo f es = +and z3AppThy me env def tyo f es = (* match A.sortcheck_app Theories.is_interp (Misc.flip SM.maybe_find env) tyo f es with *)- match app_sort env tyo f es with + match app_sort env tyo f es with | Some (s, t) -> let zts = So.sub_args s |> List.map (snd <+> z3Type me) in let zes = es |> List.map (z3Exp me env) in@@ -273,38 +283,38 @@ |> assertf "z3AppThy: sort error %s" and z3Div me env = function- | (e1, e2) when !Co.uif_divide -> + | (e1, e2) when !Co.uif_divide -> z3App me env div_n (List.map (z3Exp me env) [e1; e2])- | (e1, e2) -> + | (e1, e2) -> SMT.mkDiv me.c (z3Exp me env e1) (z3Exp me env e2) and z3Mul me env = function- | ((A.Con (A.Constant.Int i), _), e) + | ((A.Con (A.Constant.Int i), _), e) | (e, (A.Con (A.Constant.Int i), _)) ->- SMT.mkMul me.c (SMT.mkInt me.c i me.tint) (z3Exp me env e) - | (e1, e2) when !Co.uif_multiply -> + SMT.mkMul me.c (SMT.mkInt me.c i me.tint) (z3Exp me env e)+ | (e1, e2) when !Co.uif_multiply -> z3App me env mul_n (List.map (z3Exp me env) [e1; e2])- | (e1, e2) -> + | (e1, e2) -> SMT.mkMul me.c (z3Exp me env e1) (z3Exp me env e2) and z3Con me env = function- | A.Constant.Int i -> - SMT.mkInt me.c i me.tint - | A.Constant.Real i -> + | A.Constant.Int i ->+ SMT.mkInt me.c i me.tint+ | A.Constant.Real i -> SMT.mkReal me.c i me.treal | A.Constant.Lit (l, t) -> SMT.mkLit me.c l (z3Type me t)- + and z3Exp me env = function | A.Con c, _ -> z3Con me env c- | A.Var s, _ -> + | A.Var s, _ -> z3Var me env s- | A.Cst ((A.App (f, es), _), t), _ when (H.mem me.thy_symm f) -> + | A.Cst ((A.App (f, es), _), t), _ when (H.mem me.thy_symm f) -> z3AppThy me env (H.find me.thy_symm f) (Some t) f es- | A.App (f, es), _ when (H.mem me.thy_symm f) -> + | A.App (f, es), _ when (H.mem me.thy_symm f) -> z3AppThy me env (H.find me.thy_symm f) None f es- | A.App (f, es), _ -> + | A.App (f, es), _ -> z3App me env f (List.map (z3Exp me env) es) | A.Bin (e1, A.Plus, e2), _ -> SMT.mkAdd me.c (z3Exp me env e1) (z3Exp me env e2)@@ -320,86 +330,87 @@ SMT.mkMod me.c (z3Exp me env e) (SMT.mkInt me.c i me.tint) | A.Bin (e1, A.Mod, e2), _ -> SMT.mkMod me.c (z3Exp me env e1) (z3Exp me env e2)- | A.Ite (e1, e2, e3), _ -> + | A.Ite (e1, e2, e3), _ -> SMT.mkIte me.c (z3Pred me env e1) (z3Exp me env e2) (z3Exp me env e3) - | A.Fld (f, e), _ -> + | A.Fld (f, e), _ -> z3App me env (mk_select f) [z3Exp me env e] (** REQUIRES: disjoint field names *)- | A.Cst (e, _), _ -> + | A.Cst (e, _), _ -> z3Exp me env e- | e -> - assertf "z3Exp: Cannot Convert %s!" (E.to_string e) + | e ->+ assertf "z3Exp: Cannot Convert %s!" (E.to_string e) and z3Pred me env = function- | A.True, _ -> + | A.True, _ -> SMT.mkTrue me.c | A.False, _ -> SMT.mkFalse me.c- | A.Not p, _ -> + | A.Not p, _ -> SMT.mkNot me.c (z3Pred me env p)- | A.And ps, _ -> + | A.And ps, _ -> SMT.mkAnd me.c (List.map (z3Pred me env) ps)- | A.Or ps, _ -> + | A.Or ps, _ -> SMT.mkOr me.c (List.map (z3Pred me env) ps)- | A.Imp (p1, p2), _ -> + | A.Imp (p1, p2), _ -> SMT.mkImp me.c (z3Pred me env p1) (z3Pred me env p2) | A.Iff (p1, p2), _ -> SMT.mkIff me.c (z3Pred me env p1) (z3Pred me env p2) | A.Atom (e1, r, e2), _ -> z3Rel me env (e1, r, e2)- | A.Bexp e, _ -> + | A.Bexp e, _ -> let a = z3Exp me env e in let s2 = E.to_string e in- let so = match expr_sort env e with Some so -> so- | _ -> F.printf "No type for %s" (E.to_string e);- assert false in+ let so = match expr_sort env e with+ | Some so -> so+ | _ -> let _ = F.printf "No type for %s" (E.to_string e) in assert false+ in let sos = So.to_string so in (* let s1 = SMT.astString me.c a in- let _ = asserts (SMT.isBool me.c a) - "Bexp is not bool (e = %s)! z3=%s, fix=%s, sort=%s" - (E.to_string e) s1 s2 sos - in *) + let _ = asserts (SMT.isBool me.c a)+ "Bexp is not bool (e = %s)! z3=%s, fix=%s, sort=%s"+ (E.to_string e) s1 s2 sos+ in *) a - | A.Forall (xts, p), _ -> + | A.Forall (xts, p), _ -> let (xs, ts) = List.split xts in let zargs = Array.of_list (List.map2 (z3Bind me env) xs ts) in- let zts = Array.of_list (List.map (z3Type me) ts) in + let zts = Array.of_list (List.map (z3Type me) ts) in let rv = SMT.mkAll me.c zts zargs (z3Pred me env p) in let _ = me.bnd <- me.bnd - (List.length xs) in rv- | p -> - assertf "z3Pred: Cannot Convert %s!" (P.to_string p) + | p ->+ assertf "z3Pred: Cannot Convert %s!" (P.to_string p) - -let z3Pred me env p = - try ++let z3Pred me env p =+ try let p = p in (*BS.time "fixdiv" A.fixdiv p in *) BS.time "z3Pred" (z3Pred me env) p- with ex -> (F.printf "z3Pred: error converting %a\n" P.print p) ; raise ex + with ex -> (F.printf "z3Pred: error converting %a\n" P.print p) ; raise ex (***************************************************************************) (***************** Binder/Stack Management *********************************) (***************************************************************************) let rec vpop (cs,s) =- match s with + match s with | [] -> (cs,s) | Barrier :: t -> (cs,t)- | h :: t -> vpop (h::cs,t) + | h :: t -> vpop (h::cs,t) let clean_decls me = let cs, vars' = vpop ([],me.vars) in- let _ = me.vars <- vars' in - List.iter begin function - | Barrier -> failure "ERROR: TPZ3-cleanDecls" - | Vbl _ as d -> H.remove me.vart d + let _ = me.vars <- vars' in+ List.iter begin function+ | Barrier -> failure "ERROR: TPZ3-cleanDecls"+ | Vbl _ as d -> H.remove me.vart d | Fun _ as d -> H.remove me.funt d end cs -let handle_vv me env vv = - H.remove me.vart (getVbl env vv) (* RJ: why are we removing this? *) +let handle_vv me env vv =+ H.remove me.vart (getVbl env vv) (* RJ: why are we removing this? *) (************************************************************************)@@ -407,14 +418,14 @@ (************************************************************************) let create_theories () =- Th.theories () + Th.theories () |> (Misc.hashtbl_of_list_with Th.sort_name <**> Misc.hashtbl_of_list_with Th.sym_name) -let assert_distinct_constants me env = function [] -> () | cs -> - cs |> Misc.kgroupby (varSort env) +let assert_distinct_constants me env = function [] -> () | cs ->+ cs |> Misc.kgroupby (varSort env) |> List.iter begin fun (_, xs) -> xs >> Co.bprintf mydebug "Distinct Constants: %a \n" (Misc.pprint_many false ", " Sy.print)- |> List.map (z3Var me env) + |> List.map (z3Var me env) |> SMT.assertDistinct me.c end @@ -423,10 +434,10 @@ let _ = me.vars <- Barrier :: me.vars in ps -let valid me p = +let valid me p = SMT.bracket me begin fun _ -> SMT.assertPreds me [SMT.mkNot me p];- BS.time "unsat" SMT.unsat me + BS.time "unsat" SMT.unsat me end (* API *)@@ -438,7 +449,7 @@ let _ = SMT.assertPreds me.c zps in let tqs, fqs = List.partition (snd <+> P.is_tauto) qs in let fqs = fqs |> List.rev_map (Misc.app_snd (z3Pred me env))- |> Misc.filter (snd <+> valid me.c) in + |> Misc.filter (snd <+> valid me.c) in let _ = clean_decls me in (List.map fst tqs) ++ (List.map fst fqs) end@@ -446,8 +457,8 @@ (* API *) let print_stats ppf me = SMT.print_stats ppf ();- F.fprintf ppf "TP stats: sets=%d, queries=%d, count=%d\n" - !nb_set !nb_query (List.length me.vars) + F.fprintf ppf "TP stats: sets=%d, queries=%d, count=%d\n"+ !nb_set !nb_query (List.length me.vars) (*************************************************************************) (****************** Unsat Core for CEX generation ************************)@@ -456,30 +467,30 @@ let mk_prop_var me pfx i : SMT.ast = i |> string_of_int |> (^) pfx- |> SMT.stringSymbol me.c - |> Misc.flip (SMT.var me.c) me.tbool + |> SMT.stringSymbol me.c+ |> Misc.flip (SMT.var me.c) me.tbool let mk_prop_var_idx me ipa : (SMT.ast array * (SMT.ast -> 'a option)) = let va = Array.mapi (fun i _ -> mk_prop_var me "uc_p_" i) ipa in- let vm = va + let vm = va |> Array.map (SMT.astString me.c)- |> Misc.array_to_index_list - |> List .map Misc.swap - |> SSM.of_list in + |> Misc.array_to_index_list+ |> List .map Misc.swap+ |> SSM.of_list in let f z = SSM.maybe_find (SMT.astString me.c z) vm |> Misc.maybe_map (fst <.> Array.get ipa) in (va, f) let mk_pa me p2z pfx ics =- ics |> List.map (Misc.app_snd p2z) - |> Array.of_list + ics |> List.map (Misc.app_snd p2z)+ |> Array.of_list |> Array.mapi (fun i (x, p) -> (x, p, mk_prop_var me pfx i)) (* API *) let unsat_core me env bgp ips =- let _ = H.clear me.vart in + let _ = H.clear me.vart in let p2z = (*A.fixdiv <+>*) z3Pred me env in- let ipa = ips |> List.map (Misc.app_snd p2z) |> Array.of_list in + let ipa = ips |> List.map (Misc.app_snd p2z) |> Array.of_list in let va, f = mk_prop_var_idx me ipa in let zp = ipa |> Array.mapi (fun i (_, p) -> SMT.mkIff me.c va.(i) p) |> Array.to_list@@ -492,29 +503,29 @@ failwith "SMT-UNSAT-CORE-TODO" (************************************ match SMT.check_assumptions me.c va n va' with- | (Z3.L_FALSE, m,_, n, ucore) - -> Array.map f ucore |> Array.to_list |> Misc.map_partial id + | (Z3.L_FALSE, m,_, n, ucore)+ -> Array.map f ucore |> Array.to_list |> Misc.map_partial id | _ -> [] ************************************) end -let contra me p = +let contra me p = SMT.bracket me begin fun _ -> SMT.assertPreds me [p];- BS.time "unsat" SMT.unsat me + BS.time "unsat" SMT.unsat me end (* API *)-let is_contra me env = z3Pred me env <+> contra me.c +let is_contra me env = z3Pred me env <+> contra me.c (* API *) let unsat_suffix me env p ps = let _ = if SMT.unsat me.c then assertf "ERROR: unsat_suffix" in SMT.bracket me.c begin fun _ ->- let rec loop j = function [] -> None | zp' :: zps' -> - SMT.assertPreds me.c [zp']; + let rec loop j = function [] -> None | zp' :: zps' ->+ SMT.assertPreds me.c [zp']; if SMT.unsat me.c then Some j else loop (j-1) zps'- in loop (List.length ps) (List.map (z3Pred me env) (p :: List.rev ps)) + in loop (List.length ps) (List.map (z3Pred me env) (p :: List.rev ps)) end (***********************************************************************)@@ -525,36 +536,36 @@ let create ts env ps consts = let _ = asserts (ts = []) "ERROR: TPGEN-create non-empty sorts!" in let c = SMT.mkContext [|("MODEL", "false"); ("MODEL_PARTIAL", "true")|] in- let som, sym = create_theories () in - let me = { c = c; - tint = SMT.mkIntSort c; - treal = SMT.mkRealSort c; - tbool = SMT.mkBoolSort c; - tydt = H.create 37; - vart = H.create 37; - funt = H.create 37; - vars = []; + let som, sym = create_theories () in+ let me = { c = c;+ tint = SMT.mkIntSort c;+ treal = SMT.mkRealSort c;+ tbool = SMT.mkBoolSort c;+ tydt = H.create 37;+ vart = H.create 37;+ funt = H.create 37;+ vars = []; bnd = 0;- thy_sortm = som; - thy_symm = sym - } + thy_sortm = som;+ thy_symm = sym+ } in let _ = List.iter (z3Pred me env <+> SMT.assertAxiom me.c) (axioms ++ ps) in let _ = assert_distinct_constants me env consts in me -class tprover ts env ps consts : prover = +class tprover ts env ps consts : prover = object (self)- val me = create ts env ps consts - method interp_syms = Theories.interp_syms - method set_filter : 'a. Ast.Sort.t Ast.Symbol.SMap.t - -> Ast.Symbol.t - -> Ast.pred list - -> ('a * Ast.pred) list + val me = create ts env ps consts+ method interp_syms = Theories.interp_syms+ method set_filter : 'a. Ast.Sort.t Ast.Symbol.SMap.t+ -> Ast.Symbol.t+ -> Ast.pred list+ -> ('a * Ast.pred) list -> 'a list- = set_filter me - method print_stats = fun ppf -> print_stats ppf me - method is_contra = is_contra me + = set_filter me+ method print_stats = fun ppf -> print_stats ppf me+ method is_contra = is_contra me method unsat_suffix = unsat_suffix me end
external/ocamlgraph/src/version.ml view
@@ -1,2 +1,2 @@ let version = "0.99b"-let date = "Fri Mar 27 20:20:48 UTC 2015"+let date = "Tue May 19 21:41:16 UTC 2015"
liquid-fixpoint.cabal view
@@ -1,5 +1,5 @@ name: liquid-fixpoint-version: 0.2.3.2+version: 0.3.0.0 Copyright: 2010-15 Ranjit Jhala, University of California, San Diego. synopsis: Predicate Abstraction-based Horn-Clause/Implication Constraint Solver homepage: https://github.com/ucsd-progsys/liquid-fixpoint@@ -102,7 +102,6 @@ , containers , deepseq , directory- -- , filemanip , filepath , mtl , parsec@@ -155,8 +154,15 @@ Language.Fixpoint.Parse, Language.Fixpoint.PrettyPrint, Language.Fixpoint.SmtLib2,- Language.Fixpoint.Misc- + Language.Fixpoint.Misc,+ Language.Fixpoint.Solver.Solution,+ Language.Fixpoint.Solver.Worklist,+ Language.Fixpoint.Solver.Monad,+ Language.Fixpoint.Solver.Deps,+ Language.Fixpoint.Solver.Eliminate,+ Language.Fixpoint.Solver.Validate,+ Language.Fixpoint.Solver.Solve+ Build-Depends: base >= 4.7 && < 5 , array , attoparsec@@ -183,21 +189,21 @@ , unordered-containers , text-format --- test-suite test--- default-language: Haskell98--- type: exitcode-stdio-1.0--- hs-source-dirs: tests--- ghc-options: -O2 -threaded--- main-is: test.hs--- build-depends: base,--- -- directory,--- -- filepath,--- -- process,--- -- tagged,--- liquid-fixpoint,--- -- optparse-applicative == 0.11.*,--- QuickCheck,--- tasty >= 0.10,--- tasty-quickcheck,--- tasty-rerun >= 1.1,--- text+test-suite test+ default-language: Haskell98+ type: exitcode-stdio-1.0+ hs-source-dirs: tests+ ghc-options: -O2 -threaded+ main-is: test.hs+ build-depends: base,+ directory,+ filepath,+ process,+ -- tagged,+ liquid-fixpoint,+ -- optparse-applicative == 0.11.*,+ tasty >= 0.10,+ -- tasty-quickcheck,+ tasty-hunit,+ tasty-rerun >= 1.1,+ text
src/Language/Fixpoint/Config.hs view
@@ -7,6 +7,7 @@ module Language.Fixpoint.Config ( Config (..)+ , getOpts , Command (..) , SMTSolver (..) , GenQualifierSort (..)@@ -15,6 +16,8 @@ , withUEqAllSorts ) where +import System.Console.CmdArgs+import System.Console.CmdArgs.Verbosity (whenLoud) import Data.Generics (Data) import Data.Typeable (Typeable) import Language.Fixpoint.Files@@ -34,18 +37,20 @@ data Config = Config {- inFile :: FilePath -- target fq-file- , outFile :: FilePath -- output file- , solver :: SMTSolver -- which SMT solver to use- , genSorts :: GenQualifierSort -- generalize qualifier sorts- , ueqAllSorts :: UeqAllSorts -- use UEq on all sorts- , native :: Bool -- use haskell solver- , real :: Bool -- interpret div and mul in SMT+ inFile :: FilePath -- ^ target fq-file+ , outFile :: FilePath -- ^ output file+ , srcFile :: FilePath -- ^ src file (*.hs, *.ts, *.c)+ , solver :: SMTSolver -- ^ which SMT solver to use+ , genSorts :: GenQualifierSort -- ^ generalize qualifier sorts+ , ueqAllSorts :: UeqAllSorts -- ^ use UEq on all sorts+ , native :: Bool -- ^ use haskell solver+ , real :: Bool -- ^ interpret div and mul in SMT+ , eliminate :: Bool -- ^ eliminate non-cut KVars } deriving (Eq,Data,Typeable,Show) instance Default Config where- def = Config "" def def def def def def-+ def = Config "" def def def def def def def def+ instance Command Config where command c = command (genSorts c) ++ command (ueqAllSorts c)@@ -110,3 +115,34 @@ -- defaultSolver :: Maybe SMTSolver -> SMTSolver -- defaultSolver = fromMaybe Z3+++config = Config {+ inFile = def &= typ "TARGET" &= args &= typFile+ , outFile = "out" &= help "Output file"+ , srcFile = def &= help "Source File from which FQ is generated"+ , solver = def &= help "Name of SMT Solver"+ , genSorts = def &= help "Generalize qualifier sorts"+ , ueqAllSorts = def &= help "use UEq on all sorts"+ , native = False &= help "(alpha) Haskell Solver"+ , real = False &= help "(alpha) Theory of real numbers"+ , eliminate = False &= help "(alpha) Eliminate non-cut KVars"+ }+ &= verbosity+ &= program "fixpoint"+ &= help "Predicate Abstraction Based Horn-Clause Solver"+ &= summary "fixpoint Copyright 2009-13 Regents of the University of California."+ &= details [ "Predicate Abstraction Based Horn-Clause Solver"+ , ""+ , "To check a file foo.fq type:"+ , " fixpoint foo.fq"+ ]++getOpts :: IO Config+getOpts = do md <- cmdArgs config+ putStrLn $ banner md+ return md++banner args = "Liquid-Fixpoint Copyright 2009-13 Regents of the University of California.\n"+ ++ "All Rights Reserved.\n"+
src/Language/Fixpoint/Errors.hs view
@@ -2,7 +2,7 @@ {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE NoMonomorphismRestriction #-}-+{-# LANGUAGE ScopedTypeVariables #-} module Language.Fixpoint.Errors ( -- * Concrete Location Type SrcSpan (..)@@ -18,7 +18,6 @@ -- * Accessors , errLoc , errMsg- -- , errorInfo -- * Adding Insult to Injury , catMessage@@ -26,6 +25,7 @@ -- * Fatal Exit , die+ , exit ) where @@ -41,6 +41,7 @@ import Text.Parsec.Pos import Text.PrettyPrint.HughesPJ import Text.Printf+import Control.Exception (catch) ----------------------------------------------------------------------- -- | A Reusable SrcSpan Type ------------------------------------------@@ -111,15 +112,13 @@ --------------------------------------------------------------------- catMessage :: Error -> String -> Error ----------------------------------------------------------------------catMessage err msg = err {errMsg = msg ++ errMsg err}+catMessage e msg = e {errMsg = msg ++ errMsg e} --------------------------------------------------------------------- catError :: Error -> Error -> Error --------------------------------------------------------------------- catError e1 e2 = catMessage e1 $ show e2 -- --------------------------------------------------------------------- err :: SrcSpan -> String -> Error ---------------------------------------------------------------------@@ -129,3 +128,10 @@ die :: Error -> a --------------------------------------------------------------------- die = throw++---------------------------------------------------------------------+exit :: a -> IO a -> IO a+---------------------------------------------------------------------+exit def act = catch act $ \(e :: Error) -> do+ putStrLn $ "Unexpected Error: " ++ showpp e+ return def
src/Language/Fixpoint/Files.hs view
@@ -19,12 +19,11 @@ , isExtFile -- * Hardwired paths- , getFixpointPath, getZ3LibPath+ , getFixpointPath+ , getZ3LibPath -- * Various generic utility functions for finding and removing files- -- , getHsTargets , getFileInDirs- -- , findFileInDirs , copyFiles ) where@@ -47,8 +46,11 @@ getFixpointPath = fromMaybe msg . msum <$> sequence [ findExecutable "fixpoint.native" , findExecutable "fixpoint.native.exe"+ -- fallback for developing in-tree...+ , findFile ["external/fixpoint"] "fixpoint.native" ]- where msg = errorstar "Cannot find fixpoint binary [fixpoint.native]"+ where+ msg = errorstar "Cannot find fixpoint binary [fixpoint.native]" getZ3LibPath = dropFileName <$> getFixpointPath
src/Language/Fixpoint/Interface.hs view
@@ -1,133 +1,199 @@+-- | This module implements the top-level API for interfacing with Fixpoint+-- In particular it exports the functions that solve constraints supplied+-- either as .fq files or as FInfo.+ module Language.Fixpoint.Interface ( -- * Containing Constraints FInfo (..) - -- * Invoke Solver on Set of Constraints+ -- * Invoke Solver on an FInfo , solve- , solveFile + -- * Invoke Solver on a .fq file+ , solveFQ+ -- * Function to determine outcome , resultExit - -- * Validity Query- , checkValid-+ -- * Parse Qualifiers from File+ , parseFInfo ) where -{- Interfacing with Fixpoint Binary -}- import Data.Functor-import Data.Hashable+-- import Data.Hashable import qualified Data.HashMap.Strict as M import Data.List-import Data.Monoid-import System.Directory (getTemporaryDirectory)+import Data.Monoid (mconcat, mempty)+-- import System.Directory (getTemporaryDirectory) import System.Exit-import System.FilePath ((</>))+-- import System.FilePath ((</>)) import System.IO (IOMode (..), hPutStr, withFile) import Text.Printf +import Language.Fixpoint.Solver.Eliminate (eliminateAll)+import qualified Language.Fixpoint.Solver.Solve as S import Language.Fixpoint.Config import Language.Fixpoint.Files import Language.Fixpoint.Misc-import Language.Fixpoint.Parse (rr)+import Language.Fixpoint.Parse (rr, rr') import Language.Fixpoint.Types hiding (kuts, lits)-import System.Console.CmdArgs.Default+import Language.Fixpoint.Errors (exit)+import Language.Fixpoint.PrettyPrint (showpp)+-- import System.Console.CmdArgs.Default import System.Console.CmdArgs.Verbosity import Text.PrettyPrint.HughesPJ + ------------------------------------------------------------------------------ | One Shot validity query ----------------------------------------------+-- | Solve FInfo system of horn-clause constraints ------------------------ ---------------------------------------------------------------------------+solve :: Config -> FInfo a -> IO (Result a)+solve cfg+ | native cfg = S.solve cfg+ | otherwise = solveExt cfg ----------------------------------------------------------------------------checkValid :: (Hashable a) => a -> [(Symbol, Sort)] -> Pred -> IO (FixResult a)+-- | Solve .fq File ------------------------------------------------------- ----------------------------------------------------------------------------checkValid n xts p- = do file <- (</> show (hash n)) <$> getTemporaryDirectory- (r, _) <- solve def file [] $ validFInfo n xts p- return (sinfo <$> r)+solveFQ :: Config -> IO ExitCode+---------------------------------------------------------------------------+solveFQ cfg+ | native cfg = solveNative' cfg+ | otherwise = solveFile cfg -validFInfo :: a -> [(Symbol, Sort)] -> Pred -> FInfo a-validFInfo l xts p = FI constrm [] benv emptySEnv [] ksEmpty []- where- constrm = M.singleton 0 $ validSubc l ibenv p- binds = [(x, trueSortedReft t) | (x, t) <- xts]- ibenv = insertsIBindEnv bids emptyIBindEnv- (bids, benv) = foldlMap (\e (x,t) -> insertBindEnv x t e) emptyBindEnv binds -validSubc :: a -> IBindEnv -> Pred -> SubC a-validSubc l env p = safeHead "Interface.validSubC" $ subC env PTrue lhs rhs i t l- where- lhs = mempty- rhs = RR mempty (predReft p)- i = Just 0- t = []--result :: a -> Bool -> FixResult a-result _ True = Safe-result x False = Unsafe [x]-+---------------------------------------------------------------------------+-- | Fake Dependencies Harness Solver+---------------------------------------------------------------------------+solveNative :: Config -> IO ExitCode+solveNative cfg+ = do let file = inFile cfg+ str <- readFile file+ let fi = rr' file str :: FInfo ()+ let res = eliminateAll fi+ putStrLn $ "Result: \n" ++ (render $ toFixpoint res)+ error "TODO: solveNative" ------------------------------------------------------------------------------ | Solve a system of horn-clause constraints ----------------------------+-- | Native Haskell Solver ---------------------------------------------------------------------------+solveNative' :: Config -> IO ExitCode+solveNative' cfg = exit (ExitFailure 2) $ do+ let file = inFile cfg+ str <- readFile file+ let fi = rr' file str :: FInfo ()+ let fi' = if eliminate cfg then eliminateAll fi else fi+ (res, s) <- S.solve cfg fi'+ let res' = sid <$> res+ putStrLn $ "Solution:\n" ++ showpp s+ putStrLn $ "Result: " ++ show res'+ return $ resultExit res' ----------------------------------------------------------------------------solve :: Config -> FilePath -> [FilePath] -> FInfo a- -> IO (FixResult (SubC a), M.HashMap Symbol Pred)+-- | External Ocaml Solver ----------------------------------------------------------------------------solve cfg fn hqs fi- = {-# SCC "Solve" #-} execFq cfg fn hqs fi- >>= {-# SCC "exitFq" #-} exitFq fn (cm fi)+solveExt :: Config -> FInfo a -> IO (Result a)+solveExt cfg fi = {-# SCC "Solve" #-} execFq cfg fn fi+ >>= {-# SCC "exitFq" #-} exitFq fn (cm fi)+ where+ fn = srcFile cfg -execFq cfg fn hqs fi- = do copyFiles hqs fq- appendFile fq qstr+execFq cfg fn fi+ = do writeFile fq qstr withFile fq AppendMode (\h -> {-# SCC "HPrintDump" #-} hPutStr h (render d)) solveFile $ cfg `withTarget` fq where fq = extFileName Fq fn d = {-# SCC "FixPointify" #-} toFixpoint fi- qstr = render ((vcat $ toFix <$> (quals fi)) $$ text "\n")+ qstr = render ((vcat $ toFix <$> quals fi) $$ text "\n") ---------------------------------------------------------------------------- solveFile :: Config -> IO ExitCode---------------------------------------------------------------------------- solveFile cfg = do fp <- getFixpointPath z3 <- getZ3LibPath v <- (\b -> if b then "-v 1" else "") <$> isLoud- ec <- {-# SCC "sysCall:Fixpoint" #-} executeShellCommand "fixpoint" $ fixCommand cfg fp z3 v rf- return ec- where realFlags = "-no-uif-multiply "- ++ "-no-uif-divide "- rf = if (real cfg) then realFlags else ""+ {-# SCC "sysCall:Fixpoint" #-} executeShellCommand "fixpoint" $ fixCommand cfg fp z3 v -fixCommand cfg fp z3 verbosity realFlags+fixCommand cfg fp z3 verbosity = printf "LD_LIBRARY_PATH=%s %s %s %s -notruekvars -refinesort -nosimple -strictsortcheck -sortedquals %s"- z3 fp verbosity realFlags (command cfg)+ z3 fp verbosity rf (command cfg)+ where+ rf = if real cfg then realFlags else "" -exitFq _ _ (ExitFailure n) | (n /= 1)+realFlags = "-no-uif-multiply "+ ++ "-no-uif-divide "++exitFq _ _ (ExitFailure n) | n /= 1 = return (Crash [] "Unknown Error", M.empty) exitFq fn cm _ = do str <- {-# SCC "readOut" #-} readFile (extFileName Out fn) let (x, y) = parseFixpointOutput str -- {-# SCC "parseFixOut" #-} rr ({-# SCC "sanitizeFixpointOutput" #-} sanitizeFixpointOutput str) return $ (plugC cm x, y)+ where+ plugC = fmap . mlookup parseFixpointOutput :: String -> (FixResult Integer, FixSolution) parseFixpointOutput str = {-# SCC "parseFixOut" #-} rr ({-# SCC "sanitizeFixpointOutput" #-} sanitizeFixpointOutput str) -plugC = fmap . mlookup- sanitizeFixpointOutput = unlines . filter (not . ("//" `isPrefixOf`)) . chopAfter ("//QUALIFIERS" `isPrefixOf`) . lines +---------------------------------------------------------------------------+resultExit :: FixResult a -> ExitCode+--------------------------------------------------------------------------- resultExit Safe = ExitSuccess resultExit (Unsafe _) = ExitFailure 1 resultExit _ = ExitFailure 2+++---------------------------------------------------------------------------+-- | Parse External Qualifiers --------------------------------------------+---------------------------------------------------------------------------+parseFInfo :: [FilePath] -> IO (FInfo a) -- [Qualifier]+---------------------------------------------------------------------------+parseFInfo fs = mconcat <$> mapM parseFI fs++parseFI :: FilePath -> IO (FInfo a) --[Qualifier]+parseFI f = do+ str <- readFile f+ let fi = rr' f str :: FInfo ()+ return $ mempty { quals = quals fi+ , gs = gs fi }++-- OLD CUT USE NEW SMTLIB INTERFACE ---------------------------------------------------------------------------+-- OLD CUT USE NEW SMTLIB INTERFACE -- | One Shot validity query ----------------------------------------------+-- OLD CUT USE NEW SMTLIB INTERFACE ---------------------------------------------------------------------------+-- OLD CUT USE NEW SMTLIB INTERFACE +-- OLD CUT USE NEW SMTLIB INTERFACE ---------------------------------------------------------------------------+-- OLD CUT USE NEW SMTLIB INTERFACE checkValid :: (Hashable a) => a -> [(Symbol, Sort)] -> Pred -> IO (FixResult a)+-- OLD CUT USE NEW SMTLIB INTERFACE ---------------------------------------------------------------------------+-- OLD CUT USE NEW SMTLIB INTERFACE checkValid n xts p+-- OLD CUT USE NEW SMTLIB INTERFACE = do file <- (</> show (hash n)) <$> getTemporaryDirectory+-- OLD CUT USE NEW SMTLIB INTERFACE (r, _) <- solve def file [] $ validFInfo n xts p+-- OLD CUT USE NEW SMTLIB INTERFACE return (sinfo <$> r)+-- OLD CUT USE NEW SMTLIB INTERFACE +-- OLD CUT USE NEW SMTLIB INTERFACE validFInfo :: a -> [(Symbol, Sort)] -> Pred -> FInfo a+-- OLD CUT USE NEW SMTLIB INTERFACE validFInfo l xts p = FI constrm [] benv emptySEnv [] ksEmpty []+-- OLD CUT USE NEW SMTLIB INTERFACE where+-- OLD CUT USE NEW SMTLIB INTERFACE constrm = M.singleton 0 $ validSubc l ibenv p+-- OLD CUT USE NEW SMTLIB INTERFACE binds = [(x, trueSortedReft t) | (x, t) <- xts]+-- OLD CUT USE NEW SMTLIB INTERFACE ibenv = insertsIBindEnv bids emptyIBindEnv+-- OLD CUT USE NEW SMTLIB INTERFACE (bids, benv) = foldlMap (\e (x,t) -> insertBindEnv x t e) emptyBindEnv binds+-- OLD CUT USE NEW SMTLIB INTERFACE +-- OLD CUT USE NEW SMTLIB INTERFACE validSubc :: a -> IBindEnv -> Pred -> SubC a+-- OLD CUT USE NEW SMTLIB INTERFACE validSubc l env p = safeHead "Interface.validSubC" $ subC env PTrue lhs rhs i t l+-- OLD CUT USE NEW SMTLIB INTERFACE where+-- OLD CUT USE NEW SMTLIB INTERFACE lhs = mempty+-- OLD CUT USE NEW SMTLIB INTERFACE rhs = RR mempty (predReft p)+-- OLD CUT USE NEW SMTLIB INTERFACE i = Just 0+-- OLD CUT USE NEW SMTLIB INTERFACE t = []+-- OLD CUT USE NEW SMTLIB INTERFACE +-- OLD CUT USE NEW SMTLIB INTERFACE result :: a -> Bool -> FixResult a+-- OLD CUT USE NEW SMTLIB INTERFACE result _ True = Safe+-- OLD CUT USE NEW SMTLIB INTERFACE result x False = Unsafe [x]+-- OLD CUT USE NEW SMTLIB INTERFACE
src/Language/Fixpoint/Misc.hs view
@@ -9,13 +9,14 @@ import qualified Control.Exception as Ex import Data.Hashable import Data.Traversable (traverse)--- import qualified Data.HashSet as S+import qualified Data.HashSet as S import Control.Applicative ((<$>)) import Control.Monad (forM_, (>=>)) import qualified Data.ByteString as B import Data.ByteString.Char8 (pack, unpack) import qualified Data.HashMap.Strict as M import qualified Data.List as L+import Data.Tuple (swap) import Data.Maybe (fromJust) import Data.Maybe (catMaybes, fromMaybe) import qualified Data.Text as T@@ -29,6 +30,7 @@ import Text.PrettyPrint.HughesPJ + ----------------------------------------------------------------------------------- ------------ Support for Colored Logging ------------------------------------------ -----------------------------------------------------------------------------------@@ -132,6 +134,7 @@ Just v -> v Nothing -> errorstar $ "mlookup: unknown key " ++ show k +safeLookup msg k m = fromMaybe (errorstar msg) (M.lookup k m) mfromJust :: String -> Maybe a -> a mfromJust _ (Just x) = x@@ -158,10 +161,15 @@ concatMaps = fmap sortNub . L.foldl' (M.unionWith (++)) M.empty -- group :: Hashable k => [(k, v)] -> M.HashMap k [v]-group = L.foldl' (\m (k, v) -> inserts k v m) M.empty+group = groupBase M.empty+groupBase = L.foldl' (\m (k, v) -> inserts k v m) groupList = M.toList . group +mkGraph :: (Eq a, Eq b, Hashable a, Hashable b) => [(a, b)] -> M.HashMap a (S.HashSet b)+mkGraph = fmap S.fromList . group++ -- groupMap :: Hashable k => (a -> k) -> [a] -> M.HashMap k [a] groupMap f xs = L.foldl' (\m x -> inserts (f x) x m) M.empty xs @@ -174,17 +182,26 @@ sortDiff :: (Ord a) => [a] -> [a] -> [a]-sortDiff x1s x2s = go (sortNub x1s) (sortNub x2s)- where go xs@(x:xs') ys@(y:ys')- | x < y = x : go xs' ys- | x == y = go xs' ys'- | otherwise = go xs ys'- go xs [] = xs- go [] _ = []+sortDiff x1s x2s = go (sortNub x1s) (sortNub x2s)+ where+ go xs@(x:xs') ys@(y:ys')+ | x < y = x : go xs' ys+ | x == y = go xs' ys'+ | otherwise = go xs ys'+ go xs [] = xs+ go [] _ = [] +folds :: (a -> b -> (c, a)) -> a -> [b] -> ([c], a)+folds f b = L.foldl' step ([], b)+ where+ step (cs, acc) x = (c:cs, x')+ where+ (c, x') = f acc x ++ distinct :: Ord a => [a] -> Bool distinct xs = length xs == length (sortNub xs) @@ -236,14 +253,29 @@ Just k -> errorstar $ "safeUnion with common key = " ++ show k ++ " " ++ msg Nothing -> M.union m1 m2 +{-@ type ListNE a = {v:[a] | 0 < len v} @-}+type ListNE a = [a]++safeHead :: String -> ListNE a -> a safeHead _ (x:_) = x safeHead msg _ = errorstar $ "safeHead with empty list " ++ msg +safeLast :: String -> ListNE a -> a safeLast _ xs@(_:_) = last xs safeLast msg _ = errorstar $ "safeLast with empty list " ++ msg ++safeInit :: String -> ListNE a -> [a] safeInit _ xs@(_:_) = init xs safeInit msg _ = errorstar $ "safeInit with empty list " ++ msg++safeUncons :: String -> ListNE a -> (a, [a])+safeUncons _ (x:xs) = (x, xs)+safeUncons msg _ = errorstar $ "safeUncons with empty list " ++ msg++safeUnsnoc :: String -> ListNE a -> ([a], a)+safeUnsnoc msg = swap . mapSnd reverse . safeUncons msg . reverse+ -- memoIndex :: (Hashable b) => (a -> Maybe b) -> [a] -> [Maybe Int]
src/Language/Fixpoint/Names.hs view
@@ -18,17 +18,18 @@ -- * Symbols Symbol , Symbolic (..)- , anfPrefix, tempPrefix, vv, intKvar, isPrefixOfSym, isSuffixOfSym, stripParensSym+ , anfPrefix, tempPrefix, vv, isPrefixOfSym, isSuffixOfSym, stripParensSym , consSym, unconsSym, dropSym, singletonSym, headSym, takeWhileSym, lengthSym , symChars, isNonSymbol, nonSymbol , isNontrivialVV , symbolText, symbolString , encode, vvCon , dropModuleNames+ , dropModuleUnique , takeModuleNames -- * Creating Symbols- , dummySymbol, intSymbol, tempSymbol+ , dummySymbol, intSymbol, tempSymbol, existSymbol , qualifySymbol , suffixSymbol @@ -42,6 +43,8 @@ , propConName , hpropConName , strConName+ , nilName+ , consName , vvName , symSepName , size32Name, size64Name, bitVecName, bvAndName, bvOrName@@ -200,22 +203,23 @@ dummySymbol = dummyName++intSymbol :: (Show a) => Symbol -> a -> Symbol intSymbol x i = x `mappend` symbol (show i) -tempSymbol :: Symbol -> Integer -> Symbol-tempSymbol prefix n = intSymbol (tempPrefix `mappend` prefix) n+tempSymbol, existSymbol :: Symbol -> Integer -> Symbol+tempSymbol prefix n = intSymbol (tempPrefix `mappend` prefix) n+existSymbol prefix n = intSymbol (existPrefix `mappend` prefix) n -tempPrefix, anfPrefix :: Symbol+tempPrefix, anfPrefix, existPrefix :: Symbol tempPrefix = "lq_tmp_" anfPrefix = "lq_anf_"+existPrefix = "lq_ext_" nonSymbol :: Symbol nonSymbol = "" isNonSymbol = (== nonSymbol) -intKvar :: Integer -> Symbol-intKvar = intSymbol "k_"- -- | Values that can be viewed as Symbols class Symbolic a where@@ -251,6 +255,9 @@ vvName = "VV" symSepName = '#' +nilName = "nil" :: Symbol+consName = "cons" :: Symbol+ size32Name = "Size32" :: Symbol size64Name = "Size64" :: Symbol bitVecName = "BitVec" :: Symbol@@ -281,6 +288,8 @@ , bvOrName , bvAndName , "FAppTy"+ , nilName+ , consName ] -- dropModuleNames [] = []@@ -292,9 +301,18 @@ -- dotWhite '.' = ' ' -- dotWhite c = c -dropModuleNames = mungeModuleNames safeLast "dropModuleNames: "-takeModuleNames = mungeModuleNames safeInit "takeModuleNames: "+sepModNames = "."+sepUnique = "#" +dropModuleNames = mungeNames safeLast sepModNames "dropModuleNames: "+takeModuleNames = mungeNames safeInit sepModNames "takeModuleNames: "++dropModuleUnique = mungeNames safeHead sepUnique "dropModuleUnique: "++safeHead :: String -> [T.Text] -> Symbol+safeHead msg [] = errorstar $ "safeHead with empty list" ++ msg+safeHead _ (x:_) = symbol x+ safeInit :: String -> [T.Text] -> Symbol safeInit _ xs@(_:_) = symbol $ T.intercalate "." $ init xs safeInit msg _ = errorstar $ "safeInit with empty list " ++ msg@@ -303,9 +321,9 @@ safeLast _ xs@(_:_) = symbol $ last xs safeLast msg _ = errorstar $ "safeLast with empty list " ++ msg -mungeModuleNames :: (String -> [T.Text] -> Symbol) -> String -> Symbol -> Symbol-mungeModuleNames _ _ "" = ""-mungeModuleNames f msg s'@(symbolText -> s)+mungeNames :: (String -> [T.Text] -> Symbol) -> T.Text -> String -> Symbol -> Symbol+mungeNames _ _ _ "" = ""+mungeNames f d msg s'@(symbolText -> s) | s' == tupConName = tupConName- | otherwise = f (msg ++ T.unpack s) $ T.splitOn "." $ stripParens s+ | otherwise = f (msg ++ T.unpack s) $ T.splitOn d $ stripParens s
src/Language/Fixpoint/Parse.hs view
@@ -59,11 +59,11 @@ , remainderP ) where -import Control.Applicative ((<$>), (<*), (<*>))-import Control.Monad+import Control.Applicative ((<$>), (<*), (*>), (<*>))+-- import Control.Monad import qualified Data.HashMap.Strict as M import qualified Data.HashSet as S-import Data.Text (Text)+-- import Data.Text (Text) import qualified Data.Text as T import Text.Parsec import Text.Parsec.Expr@@ -79,10 +79,12 @@ import Language.Fixpoint.Misc hiding (dcolon) import Language.Fixpoint.SmtLib2 import Language.Fixpoint.Types+import Language.Fixpoint.Names (vv, nilName, consName)+import Language.Fixpoint.Visitor (foldSort, mapSort) import Data.Maybe (fromJust, maybe) -import Data.Monoid (mempty)+import Data.Monoid (mempty,mconcat) type Parser = Parsec String Integer @@ -91,7 +93,7 @@ languageDef = emptyDef { Token.commentStart = "/* " , Token.commentEnd = " */"- , Token.commentLine = "--"+ , Token.commentLine = "//" , Token.identStart = satisfy (\_ -> False) , Token.identLetter = satisfy (\_ -> False) , Token.reservedNames = [ "SAT"@@ -115,7 +117,7 @@ , "|" , "if", "then", "else" ]- , Token.reservedOpNames = [ "+", "-", "*", "/", "\\"+ , Token.reservedOpNames = [ "+", "-", "*", "/", "\\", ":" , "<", ">", "<=", ">=", "=", "!=" , "/=" , "mod", "and", "or" --, "is"@@ -163,7 +165,10 @@ ---------------------------------------------------------------- locParserP :: Parser a -> Parser (Located a)-locParserP p = liftM2 Loc getPosition p+locParserP p = do l1 <- getPosition+ x <- p+ l2 <- getPosition+ return $ Loc l1 l2 x -- FIXME: we (LH) rely on this parser being dumb and *not* consuming trailing -- whitespace, in order to avoid some parsers spanning multiple lines..@@ -180,6 +185,9 @@ lowerIdP :: Parser Symbol lowerIdP = condIdP symChars (isLower . head) +symCharsP :: Parser Symbol+symCharsP = condIdP symChars (`notElem` keyWordSyms)+ locLowerIdP = locParserP lowerIdP locUpperIdP = locParserP upperIdP @@ -187,14 +195,16 @@ symbolP = symbol <$> symCharsP constantP :: Parser Constant-constantP = try (liftM R double) <|> liftM I integer+constantP = try (R <$> double)+ <|> I <$>integer symconstP :: Parser SymConst symconstP = SL . T.pack <$> stringLiteral expr0P :: Parser Expr expr0P- = (fastIfP EIte exprP)+ = (brackets whiteSpace >> return eNil) + <|> (fastIfP EIte exprP) <|> (ESym <$> symconstP) <|> (ECon <$> constantP) <|> (reserved "_|_" >> return EBot)@@ -228,21 +238,17 @@ funAppP = (try litP) <|> (try exprFunSpacesP) <|> (try exprFunSemisP) <|> exprFunCommasP where- exprFunSpacesP = liftM2 EApp funSymbolP (sepBy1 expr0P blanks)- exprFunCommasP = liftM2 EApp funSymbolP (parens $ sepBy exprP comma)- exprFunSemisP = liftM2 EApp funSymbolP (parenBrackets $ sepBy exprP semi)+ exprFunSpacesP = EApp <$> funSymbolP <*> sepBy1 expr0P blanks+ exprFunCommasP = EApp <$> funSymbolP <*> parens (sepBy exprP comma)+ exprFunSemisP = EApp <$> funSymbolP <*> parenBrackets (sepBy exprP semi) funSymbolP = locParserP symbolP -- | BitVector literal: lit "#x00000001" (BitVec (Size32 obj)) litP = do reserved "lit" l <- stringLiteral- s <- try (bvSortP "Size32" S32) <|> bvSortP "Size64" S64- return $ ECon $ L (T.pack l) (mkSort s)- where- bvSortP ss s = do parens (reserved "BitVec" >> parens (reserved ss >> reserved "obj"))- return s-+ t <- sortP+ return $ ECon $ L (T.pack l) t -- ORIG exprP :: Parser Expr -- ORIG exprP = expr2P <|> lexprP@@ -278,10 +284,12 @@ , Infix (reservedOp "+" >> return (EBin Plus )) AssocLeft ] , [ Infix (reservedOp "mod" >> return (EBin Mod )) AssocLeft]+ , [ Infix (reservedOp ":" >> return (eCons )) AssocLeft] ] -eMinus = EBin Minus (expr (0 :: Integer))-+eMinus = EBin Minus (expr (0 :: Integer))+eCons x xs = EApp (dummyLoc consName) [x,xs]+eNil = EVar nilName exprCastP = do e <- exprP@@ -291,41 +299,71 @@ dcolon = string "::" <* spaces +varSortP = FVar <$> parens intP+funcSortP = parens $ FFunc <$> intP <* comma <*> sortsP++sortsP = brackets $ sepBy sortP semi+ sortP- = try (string "Integer" >> return FInt)- <|> try (string "Int" >> return FInt)- <|> try (string "int" >> return FInt)- <|> try (FObj . symbol <$> lowerIdP)- <|> (fApp <$> (Left <$> fTyConP) <*> many sortP)+ = try (parens $ sortP)+ <|> try (string "@" >> varSortP)+ <|> try (string "func" >> funcSortP)+ <|> try (fApp (Left listFTyCon) . single <$> brackets sortP)+ <|> try bvSortP+ <|> try (fApp <$> (Left <$> fTyConP) <*> sepBy sortP blanks)+ <|> (FObj . symbol <$> lowerIdP) -symCharsP = condIdP symChars (`notElem` keyWordSyms)+bvSortP+ = mkSort <$> (bvSizeP "Size32" S32 <|> bvSizeP "Size64" S64) +bvSizeP ss s = do+ parens (reserved "BitVec" >> parens (reserved ss >> reserved "obj"))+ return s+++ keyWordSyms = ["if", "then", "else", "mod"] --------------------------------------------------------------------- -------------------------- Predicates ------------------------------- --------------------------------------------------------------------- -trueP = reserved "true" >> return PTrue-falseP = reserved "false" >> return PFalse pred0P :: Parser Pred pred0P = trueP <|> falseP+ <|> try kvarPredP <|> try (fastIfP pIte predP) <|> try predrP <|> try (parens predP)- <|> try (liftM PBexp funAppP)- <|> try (reservedOp "&&" >> liftM PAnd predsP)- <|> try (reservedOp "||" >> liftM POr predsP)+ <|> try (PBexp <$> (reserved "?" *> exprP))+ <|> try (PBexp <$> funAppP)+ <|> try (reservedOp "&&" >> PAnd <$> predsP)+ <|> try (reservedOp "||" >> POr <$> predsP) +-- qmP = reserved "?" <|> reserved "Bexp"++trueP, falseP :: Parser Pred+trueP = reserved "true" >> return PTrue+falseP = reserved "false" >> return PFalse++kvarPredP :: Parser Pred+kvarPredP = PKVar <$> kvarP <*> substP++kvarP :: Parser KVar+kvarP = KV <$> (char '$' *> symbolP)++substP :: Parser Subst+substP = mkSubst <$> many (brackets $ pairP symbolP aP exprP)+ where+ aP = reserved ":="+ predP :: Parser Pred predP = buildExpressionParser lops pred0P predsP = brackets $ sepBy predP semi -qmP = reserved "?" <|> reserved "Bexp" lops = [ [Prefix (reservedOp "~" >> return PNot)] , [Prefix (reservedOp "not " >> return PNot)]@@ -381,36 +419,38 @@ ---------------------------------------------------------------------------------- fTyConP- = (reserved "int" >> return intFTyCon)- <|> (reserved "bool" >> return boolFTyCon)- <|> (reserved "real" >> return realFTyCon)- <|> (symbolFTycon <$> locUpperIdP)+ = (reserved "int" >> return intFTyCon)+ <|> (reserved "Integer" >> return intFTyCon)+ <|> (reserved "Int" >> return intFTyCon)+ <|> (reserved "int" >> return intFTyCon)+ <|> (reserved "real" >> return realFTyCon)+ <|> (reserved "bool" >> return boolFTyCon)+ <|> (symbolFTycon <$> locUpperIdP) -refasP :: Parser [Refa]-refasP = (try (brackets $ sepBy (RConc <$> predP) semi))- <|> liftM ((:[]) . RConc) predP+refaP :: Parser Refa+refaP = try (refa <$> brackets (sepBy predP semi))+ <|> (Refa <$> predP) -refBindP :: Parser Symbol -> Parser [Refa] -> Parser (Reft -> a) -> Parser a+refBindP :: Parser Symbol -> Parser Refa -> Parser (Reft -> a) -> Parser a refBindP bp rp kindP = braces $ do- vv <- bp- t <- kindP+ x <- bp+ t <- kindP reserved "|"- ras <- rp <* spaces- return $ t (Reft (vv, ras))+ ra <- rp <* spaces+ return $ t (Reft (x, ra)) -bindP = liftM symbol (lowerIdP <* colon)-optBindP vv = try bindP <|> return vv+-- bindP = symbol <$> (lowerIdP <* colon)+bindP = symbolP <* colon+optBindP x = try bindP <|> return x -refP = refBindP bindP refasP-refDefP vv = refBindP (optBindP vv)+refP = refBindP bindP refaP+refDefP x = refBindP (optBindP x) --------------------------------------------------------------------- -- | Parsing Qualifiers --------------------------------------------- --------------------------------------------------------------------- --- qualifierP = mkQual <$> upperIdP <*> parens $ sepBy1 sortBindP comma <*> predP- qualifierP = do pos <- getPosition n <- upperIdP params <- parens $ sepBy1 sortBindP comma@@ -418,14 +458,37 @@ body <- predP return $ mkQual n params body pos -sortBindP = (,) <$> symbolP <* colon <*> sortP+sortBindP = (,) <$> symbolP <* colon <*> sortP -mkQual n xts p pos = Q n ((vv, t) : yts) (subst su p) pos+pairP :: Parser a -> Parser z -> Parser b -> Parser (a, b)+pairP xP sepP yP = (,) <$> xP <* sepP <*> yP+++mkQual n xts p = Q n ((vv, t) : yts) (subst su p) where- (vv,t):zts = xts- yts = mapFst mkParam <$> zts- su = mkSubst $ zipWith (\(z,_) (y,_) -> (z, eVar y)) zts yts+ (vv,t):zts = gSorts xts+ yts = mapFst mkParam <$> zts+ su = mkSubst $ zipWith (\(z,_) (y,_) -> (z, eVar y)) zts yts +gSorts :: [(a, Sort)] -> [(a, Sort)]+gSorts xts = [(x, substVars su t) | (x, t) <- xts]+ where+ su = (`zip` [0..]) . sortNub . concatMap sortVars . map snd $ xts++substVars :: [(Symbol, Int)] -> Sort -> Sort+substVars su = mapSort tx+ where+ tx (FObj x)+ | Just i <- lookup x su = FVar i+ tx t = t++sortVars :: Sort -> [Symbol]+sortVars = foldSort go []+ where+ go b (FObj x) = x : b+ go b _ = b++ mkParam s = symbol ('~' `T.cons` toUpper c `T.cons` cs) where Just (c,cs)= T.uncons $ symbolText s@@ -438,14 +501,14 @@ fInfoP = defsFInfo <$> many defP defP :: Parser (Def ())-defP = Srt <$> (reserved "sort" >> colon >> sortP)- <|> Axm <$> (reserved "axiom" >> colon >> predP)- <|> Cst <$> (reserved "constraint" >> colon >> subCP)- <|> Wfc <$> (reserved "wf" >> colon >> wfCP)- <|> Con <$> (reserved "constant" >> symbolP) <*> (colon >> sortP)- <|> Qul <$> (reserved "qualifier" >> qualifierP)- <|> Kut <$> (reserved "cut" >> symbolP)- <|> IBind <$> (reserved "bind" >> intP) <*> symbolP <*> (colon >> sortedReftP)+defP = Srt <$> (reserved "sort" >> colon >> sortP)+ <|> Axm <$> (reserved "axiom" >> colon >> predP)+ <|> Cst <$> (reserved "constraint" >> colon >> subCP)+ <|> Wfc <$> (reserved "wf" >> colon >> wfCP)+ <|> Con <$> (reserved "constant" >> symbolP) <*> (colon >> sortP)+ <|> Qul <$> (reserved "qualif" >> qualifierP)+ <|> Kut <$> (reserved "cut" >> kvarP)+ <|> IBind <$> (reserved "bind" >> intP) <*> symbolP <*> (colon >> sortedReftP) sortedReftP :: Parser SortedReft sortedReftP = refP (RR <$> (sortP <* spaces))@@ -467,10 +530,18 @@ reserved "rhs" rhs <- sortedReftP reserved "id"- i <- (integer <* spaces)+ i <- integer <* spaces tag <- tagP return $ safeHead "subCP" $ subC env grd lhs rhs (Just i) tag () +-- idVV :: Integer -> SortedReft -> SortedReft+-- idVV i sr = sr {sr_reft = ri }+-- where+-- ri = shiftVV r vvi+-- r = sr_reft sr+-- vvi = vv $ Just i++ tagP :: Parser [Int] tagP = try (reserved "tag" >> spaces >> (brackets $ sepBy intP semi)) <|> (return [])@@ -487,7 +558,7 @@ where cm = M.fromList [(cid c, c) | Cst c <- defs] ws = [w | Wfc w <- defs]- bs = rawBindEnv [(n, x, r) | IBind n x r <- defs]+ bs = bindEnvFromList [(n, x, r) | IBind n x r <- defs] gs = fromListSEnv [(x, RR t mempty) | Con x t <- defs] lts = [(x, t) | Con x t <- defs, notFun t] kts = KS $ S.fromList [k | Kut k <- defs]@@ -518,17 +589,19 @@ solution1P = do reserved "solution:"- k <- symbolP+ k <- kvP reserved ":=" ps <- brackets $ sepBy predSolP semi return (k, simplify $ PAnd ps)--solutionP :: Parser (M.HashMap Symbol Pred)+ where+ kvP = try kvarP <|> (KV <$> symbolP)+ +solutionP :: Parser (M.HashMap KVar Pred) solutionP = M.fromList <$> sepBy solution1P whiteSpace solutionFileP- = liftM2 (,) (fixResultP integer) solutionP+ = (,) <$> fixResultP integer <*> solutionP ------------------------------------------------------------------------ @@ -542,7 +615,8 @@ = case runParser (remainderP (whiteSpace >> parser)) 0 f s of Left e -> die $ err (errorSpan e) $ printf "parseError %s\n when parsing from %s\n" (show e) f Right (r, "", _) -> r- Right (_, rem, l) -> die $ err (SS l l) $ printf "doParse has leftover when parsing: %s\nfrom file %s\n" rem f+ Right (_, rem, l) -> die $ err (SS l l)+ $ printf "doParse has leftover when parsing: %s\nfrom file %s\n" rem f errorSpan e = SS l l where l = errorPos e @@ -581,8 +655,8 @@ class Inputable a where rr :: String -> a rr' :: String -> String -> a- rr' = \_ -> rr- rr = rr' ""+ rr' _ = rr+ rr = rr' "" instance Inputable Symbol where rr' = doParse' symbolP@@ -596,8 +670,8 @@ instance Inputable Expr where rr' = doParse' exprP -instance Inputable [Refa] where- rr' = doParse' refasP+instance Inputable Refa where+ rr' = doParse' refaP instance Inputable (FixResult Integer) where rr' = doParse' $ fixResultP integer
src/Language/Fixpoint/PrettyPrint.hs view
@@ -4,12 +4,14 @@ module Language.Fixpoint.PrettyPrint where +import Debug.Trace (trace) import Control.Applicative ((<$>)) import qualified Data.Text as T import Language.Fixpoint.Misc import Language.Fixpoint.Types import Text.Parsec import Text.PrettyPrint.HughesPJ+import qualified Data.HashMap.Strict as M class PPrint a where pprint :: a -> Doc@@ -22,22 +24,34 @@ showpp :: (PPrint a) => a -> String showpp = render . pprint +tracepp :: (PPrint a) => String -> a -> a+tracepp s x = trace ("\nTrace: [" ++ s ++ "] : " ++ showpp x) x+ instance PPrint a => PPrint (Maybe a) where pprint = maybe (text "Nothing") ((text "Just" <+>) . pprint) instance PPrint a => PPrint [a] where pprint = brackets . intersperse comma . map pprint +instance (PPrint a, PPrint b) => PPrint (M.HashMap a b) where+ pprint = vcat . punctuate (text "\n") . map pp1 . M.toList+ where+ pp1 (x, y) = pprint x <+> text ":=" <+> pprint y++ instance (PPrint a, PPrint b, PPrint c) => PPrint (a, b, c) where- pprint (x, y, z) = parens $ (pprint x) <> text "," <> (pprint y) <> text "," <> (pprint z)+ pprint (x, y, z) = parens $ pprint x <> text "," <> pprint y <> text "," <> pprint z instance (PPrint a, PPrint b) => PPrint (a,b) where- pprint (x, y) = (pprint x) <+> text ":" <+> (pprint y)+ pprint (x, y) = pprint x <+> text ":" <+> pprint y instance PPrint SourcePos where pprint = text . show +instance PPrint Bool where+ pprint = text . show+ instance PPrint () where pprint = text . show @@ -67,9 +81,11 @@ instance PPrint Symbol where pprint = text . symbolString -instance PPrint SymConst where- pprint (SL x) = doubleQuotes $ text $ T.unpack x+instance PPrint KVar where+ pprint (KV x) = text "$" <> pprint x +instance PPrint SymConst where+ pprint (SL x) = doubleQuotes $ text $ T.unpack x -- | Wrap the enclosed 'Doc' in parentheses only if the condition holds. parensIf True = parens@@ -111,7 +127,7 @@ where zn = 2 pprintPrec z (EApp f es) = parensIf (z > za) $ intersperse empty $- (pprint f) : (pprintPrec (za+1) <$> es)+ pprint f : (pprintPrec (za+1) <$> es) where za = 8 pprintPrec z (EBin o e1 e2) = parensIf (z > zo) $ pprintPrec (zo+1) e1 <+>@@ -155,6 +171,7 @@ pprintPrec (za+1) e2 where za = 4 pprintPrec _ (PAll xts p) = text "forall" <+> toFix xts <+> text "." <+> pprint p+ pprintPrec _ p@(PKVar {}) = toFix p trueD = text "true" falseD = text "false"@@ -165,15 +182,15 @@ pprintBin z _ o xs = intersperse o $ pprintPrec z <$> xs instance PPrint Refa where- pprintPrec z (RConc p) = pprintPrec z p- pprintPrec _ k = toFix k+ pprintPrec z (Refa p) = pprintPrec z p+ pprintPrec _ k = toFix k instance PPrint Reft where- pprint r@(Reft (_,ras))+ pprint r@(Reft (_,ra)) | isTauto r = text "true" | otherwise = {- intersperse comma -} pprintBin z trueD andD flat where- flat = flattenRefas ras+ flat = flattenRefas [ra] z = if length flat > 1 then 3 else 0 instance PPrint SortedReft where@@ -182,4 +199,4 @@ $ (pprint v) <+> (text ":") <+> (toFix so) <+> (text "|") <+> pprint ras instance PPrint a => PPrint (Located a) where- pprint (Loc _ x) = pprint x+ pprint (Loc _ _ x) = pprint x
src/Language/Fixpoint/SmtLib2.hs view
@@ -1,6 +1,4 @@ {-# LANGUAGE BangPatterns #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE NoMonomorphismRestriction #-} {-# LANGUAGE OverloadedStrings #-}@@ -37,10 +35,20 @@ , command , smtWrite + -- * Query API+ , smtDecl+ , smtAssert+ , smtCheckUnsat+ , smtBracket+ , smtDistinct++ -- * Theory Symbols , smt_set_funs+ ) where import Language.Fixpoint.Config (SMTSolver (..))+import Language.Fixpoint.Errors import Language.Fixpoint.Files import Language.Fixpoint.Types @@ -55,13 +63,14 @@ import qualified Data.Text.IO as TIO import qualified Data.Text.Lazy as LT import qualified Data.Text.Lazy.IO as LTIO+import Data.IORef import System.Directory-import System.Exit+import System.Exit hiding (die) import System.FilePath import System.IO (Handle, IOMode (..), hClose, hFlush, openFile) import System.Process-+import Debug.Trace (trace) import qualified Data.Attoparsec.Text as A {- Usage:@@ -91,7 +100,7 @@ | Declare Symbol [Sort] Sort | Define Sort | Assert (Maybe Int) Pred- | Distinct [Expr] -- {v:[Expr] | (len v) >= 2}+ | Distinct [Expr] -- {v:[Expr] | 2 <= len v} | GetValue [Symbol] deriving (Eq, Show) @@ -133,8 +142,8 @@ -smtWrite :: Context -> LT.Text -> IO ()-smtWrite me !s = smtWriteRaw me s+smtWrite :: Context -> LT.Text -> IO ()+smtWrite me !s = smtWriteRaw me s smtRead :: Context -> IO Response smtRead me = {-# SCC "smtRead" #-}@@ -199,9 +208,9 @@ -------------------------------------------------------------------------- ---------------------------------------------------------------------------makeContext :: SMTSolver -> IO Context+makeContext :: SMTSolver -> FilePath -> IO Context ---------------------------------------------------------------------------makeContext s+makeContext s f = do me <- makeProcess s pre <- smtPreamble s me createDirectoryIfMissing True $ takeDirectory smtFile@@ -209,9 +218,12 @@ let me' = me { cLog = Just hLog } mapM_ (smtWrite me') pre return me'+ where+ smtFile = extFileName Smt2 f + makeContextNoLog s- = do me <- makeProcess s+ = do me <- makeProcess s pre <- smtPreamble s me mapM_ (smtWrite me) pre return me@@ -245,29 +257,49 @@ r <- (!!1) . T.splitOn "\"" <$> smtReadRaw me case T.words r of "4.3.2" : _ -> return $ z3_432_options ++ z3Preamble- _ -> return $ z3_options ++ z3Preamble+ _ -> return $ z3_options ++ z3Preamble smtPreamble _ _ = return smtlibPreamble -smtFile :: FilePath-smtFile = extFileName Smt2 "out"- ----------------------------------------------------------------------------- -- | SMT Commands ----------------------------------------------------------- ----------------------------------------------------------------------------- -smtDecl me x ts t = interact' me (Declare x ts t)-smtPush me = interact' me (Push)-smtPop me = interact' me (Pop)+smtPush, smtPop :: Context -> IO ()+smtPush me = interact' me Push+smtPop me = interact' me Pop+++smtDecl :: Context -> Symbol -> Sort -> IO ()+smtDecl me x t = interact' me (Declare x ins out)+ where+ (ins, out) = deconSort t++deconSort :: Sort -> ([Sort], Sort)+deconSort t = case functionSort t of+ Just (_, ins, out) -> (ins, out)+ Nothing -> ([] , t )++smtAssert :: Context -> Pred -> IO () smtAssert me p = interact' me (Assert Nothing p)++smtDistinct :: Context -> [Expr] -> IO () smtDistinct me az = interact' me (Distinct az)++smtCheckUnsat :: Context -> IO Bool smtCheckUnsat me = respSat <$> command me CheckSat -respSat Unsat = True-respSat Sat = False-respSat Unknown = False-respSat r = error "crash: SMTLIB2 respSat"+smtBracket :: Context -> IO a -> IO a+smtBracket me a = do smtPush me+ r <- a+ smtPop me+ return r +respSat Unsat = True+respSat Sat = False+respSat Unknown = False+respSat r = die $ err dummySpan $ "crash: SMTLIB2 respSat = " ++ show r+ interact' me cmd = command me cmd >> return () @@ -296,10 +328,20 @@ sel = "smt_map_sel" sto = "smt_map_sto" +setEmp = "Set_emp" :: Symbol+setCap = "Set_cap" :: Symbol+setSub = "Set_sub" :: Symbol+setAdd = "Set_add" :: Symbol+setMem = "Set_mem" :: Symbol+setCom = "Set_com" :: Symbol+setCup = "Set_cup" :: Symbol+setDif = "Set_dif" :: Symbol+setSng = "Set_sng" :: Symbol+ smt_set_funs :: M.HashMap Symbol Raw-smt_set_funs = M.fromList [ ("Set_emp",emp),("Set_add",add),("Set_cup",cup)- , ("Set_cap",cap),("Set_mem",mem),("Set_dif",dif)- , ("Set_sub",sub),("Set_com",com)]+smt_set_funs = M.fromList [ (setEmp, emp), (setAdd, add), (setCup, cup)+ , (setCap, cap), (setMem, mem), (setDif, dif)+ , (setSub, sub), (setCom, com)] -- DON'T REMOVE THIS! z3 changed the names of options between 4.3.1 and 4.3.2... z3_432_options@@ -372,8 +414,8 @@ smt2 (FApp t []) | t == intFTyCon = "Int" smt2 (FApp t []) | t == boolFTyCon = "Bool" smt2 (FApp t [FApp ts _,_]) | t == appFTyCon && fTyconSymbol ts == "Set_Set" = "Set"- smt2 (FObj s) = smt2 s- smt2 (FFunc _ _) = error "smt2 FFunc"+ -- smt2 (FObj s) = smt2 s+ smt2 s@(FFunc _ _) = error $ "smt2 FFunc: " ++ show s smt2 _ = "Int" instance SMTLIB2 Symbol where@@ -419,21 +461,27 @@ smt2 (ECon c) = smt2 c smt2 (EVar x) = smt2 x smt2 (ELit x _) = smt2 x- smt2 (EApp f []) = smt2 f- smt2 (EApp f [e]) | val f == "Set_emp"- = format "(= {} {})" (emp, smt2 e)- smt2 (EApp f [e]) | val f == "Set_sng"- = format "({} {} {})" (add, emp, smt2 e)- smt2 (EApp f es) = format "({} {})" (smt2 f, smt2s es)+ smt2 (EApp f es) = smt2App f es smt2 (ENeg e) = format "(- {})" (Only $ smt2 e) smt2 (EBin o e1 e2) = format "({} {} {})" (smt2 o, smt2 e1, smt2 e2) smt2 (EIte e1 e2 e3) = format "(ite {} {} {})" (smt2 e1, smt2 e2, smt2 e3)- smt2 _ = error "TODO: SMTLIB2 Expr"+ smt2 (ECst e _) = smt2 e+ smt2 e = error $ "TODO: SMTLIB2 Expr: " ++ show e +smt2App :: LocSymbol -> [Expr] -> LT.Text+smt2App f [] = smt2 f+smt2App f [e]+ | val f == setEmp = format "(= {} {})" (emp, smt2 e)+ | val f == setSng = format "({} {} {})" (add, emp, smt2 e)+smt2App f es = format "({} {})" (smt2 f, smt2s es)++ instance SMTLIB2 Pred where smt2 (PTrue) = "true" smt2 (PFalse) = "false"+ smt2 (PAnd []) = "true" smt2 (PAnd ps) = format "(and {})" (Only $ smt2s ps)+ smt2 (POr []) = "false" smt2 (POr ps) = format "(or {})" (Only $ smt2s ps) smt2 (PNot p) = format "(not {})" (Only $ smt2 p) smt2 (PImp p q) = format "(=> {} {})" (smt2 p, smt2 q)@@ -476,3 +524,6 @@ (check-sat) (pop 1) -}++-------------------------------------------------------------------+
+ src/Language/Fixpoint/Solver/Deps.hs view
@@ -0,0 +1,96 @@+module Language.Fixpoint.Solver.Deps+ ( -- * Dummy Solver for Debugging Kuts+ solve++ -- * KV-Dependencies+ , deps+ , Deps (..)++ -- * Reads and Writes of Constraints+ , lhsKVars+ , rhsKVars+ ) where++import Language.Fixpoint.Config+import Language.Fixpoint.Misc (groupList)+import Language.Fixpoint.Names (nonSymbol)+import qualified Language.Fixpoint.Types as F++import qualified Language.Fixpoint.Visitor as V+import qualified Data.HashMap.Strict as M+import qualified Data.HashSet as S+import qualified Data.Graph as G++import Control.Monad.State++data Deps = Deps { depCuts :: ![F.KVar]+ , depNonCuts :: ![F.KVar]+ }+ deriving (Eq, Ord, Show)+++--------------------------------------------------------------+-- | Dummy just for debugging --------------------------------+--------------------------------------------------------------+solve :: Config -> F.FInfo a -> IO (F.FixResult a)+--------------------------------------------------------------+solve _ fi = do+ let d = deps fi+ print "(begin cuts debug)"+ print "Cuts:"+ print (depCuts d)+ print "Non-cuts:"+ print (depNonCuts d)+ print "(end cuts debug)"+ return F.Safe+++--------------------------------------------------------------+-- | Compute Dependencies and Cuts ---------------------------+--------------------------------------------------------------++deps :: F.FInfo a -> Deps+deps finfo = sccsToDeps sccs (F.kuts finfo)+ where+ bs = F.bs finfo+ subCs = M.elems (F.cm finfo)+ edges = concatMap (subcEdges bs) subCs+ graph = [(k,k,ks) | (k, ks) <- groupList edges]+ sccs = G.stronglyConnCompR graph++sccsToDeps :: [G.SCC (F.KVar, F.KVar,[F.KVar])] -> F.Kuts -> Deps+sccsToDeps xs ks = execState (mapM_ (bar ks) xs) (Deps [] [])++bar :: F.Kuts -> G.SCC (F.KVar, F.KVar,[F.KVar]) -> State Deps ()+bar _ (G.AcyclicSCC (v,_,_)) = do ds <- get+ put ds {depNonCuts = v : depNonCuts ds}+bar ks (G.CyclicSCC vs) = do let (v,vs') = chooseCut vs ks+ ds <- get+ put ds {depCuts = v : depCuts ds}+ mapM_ (bar ks) (G.stronglyConnCompR vs')++chooseCut :: [(F.KVar, F.KVar, [F.KVar])] -> F.Kuts -> (F.KVar, [(F.KVar, F.KVar,[F.KVar])])+chooseCut vs (F.KS ks) = (v, [x | x@(u,_,_) <- vs, u /= v])+ where+ vs' = [x | (x,_,_) <- vs]+ is = S.intersection (S.fromList vs') ks+ v = head $ if S.null is then vs' else S.toList is++subcEdges :: F.BindEnv -> F.SubC a -> [(F.KVar, F.KVar)]+subcEdges bs c = [(k1, k2) | k1 <- lhsKVars bs c+ , k2 <- rhsKVars c ]+ ++ [(k2, F.KV nonSymbol) | k2 <- rhsKVars c]+-- this nonSymbol hack is one way to prevent nodes with potential+-- outdegree 0 from getting pruned by stronglyConnCompR++lhsKVars :: F.BindEnv -> F.SubC a -> [F.KVar]+lhsKVars bs c = envKVs ++ lhsKVs+ where+ envKVs = V.envKVars bs c+ lhsKVs = V.kvars $ F.lhsCs c++rhsKVars :: F.SubC a -> [F.KVar]+rhsKVars = V.kvars . F.rhsCs+++---------------------------------------------------------------
+ src/Language/Fixpoint/Solver/Eliminate.hs view
@@ -0,0 +1,126 @@+{-# LANGUAGE FlexibleContexts #-}+module Language.Fixpoint.Solver.Eliminate+ (eliminateAll) where++import Language.Fixpoint.Types+import qualified Language.Fixpoint.Solver.Deps as D+import Language.Fixpoint.Visitor (kvars, mapKVars)+import Language.Fixpoint.Names (existSymbol)+import Language.Fixpoint.Misc (errorstar)++import qualified Data.HashMap.Strict as M+import Data.List (partition, (\\))+import Data.Foldable (foldlM)+import Control.Monad.State (get, put, runState, evalState, State)+++--------------------------------------------------------------+eliminateAll :: FInfo a -> FInfo a+eliminateAll fi = evalState (foldlM eliminate fi (D.depNonCuts ds)) 0+ where+ ds = D.deps fi+--------------------------------------------------------------+++class Elimable a where+ elimKVar :: KVar -> Pred -> a -> a++instance Elimable (SubC a) where+ -- we don't bother editing srhs since if kv is on the rhs then the entire constraint should get eliminated+ elimKVar kv pr x = x { slhs = elimKVar kv pr (slhs x) }++instance Elimable SortedReft where+ elimKVar kv pr x = x { sr_reft = elimKVar kv pr (sr_reft x) }++instance Elimable Reft where+ elimKVar kv pr = mapKVars go+ where+ go k = if kv == k then Just pr else Nothing++instance Elimable (FInfo a) where+ elimKVar kv pr x = x { cm = M.map (elimKVar kv pr) (cm x)+ , bs = elimKVar kv pr (bs x)+ }++instance Elimable BindEnv where+ elimKVar kv pr = mapBindEnv (\(sym, sr) -> (sym, elimKVar kv pr sr))+++eliminate :: FInfo a -> KVar -> State Integer (FInfo a)+eliminate fInfo kv = do+ n <- get+ let relevantSubCs = M.filter ( elem kv . D.rhsKVars) (cm fInfo)+ let remainingSubCs = M.filter (notElem kv . D.rhsKVars) (cm fInfo)+ let (kvWfC, remainingWs) = findWfC kv (ws fInfo)+ let (bindingsList, (n', orPred)) = runState (mapM (extractPred kvWfC (bs fInfo)) (M.elems relevantSubCs)) (n, POr [])+ let bindings = concat bindingsList++ let be = bs fInfo+ let (ids, be') = insertsBindEnv [(sym, trueSortedReft srt) | (sym, srt) <- bindings] be+ let newSubCs = M.map (\s -> s { senv = insertsIBindEnv ids (senv s)}) remainingSubCs+ put n'+ return $ elimKVar kv orPred (fInfo { cm = newSubCs , ws = remainingWs , bs = be' })++insertsBindEnv :: [(Symbol, SortedReft)] -> BindEnv -> ([BindId], BindEnv)+insertsBindEnv bs = runState (mapM go bs)+ where+ go (sym, srft) = do be <- get+ let (id, be') = insertBindEnv sym srft be+ put be'+ return id++findWfC :: KVar -> [WfC a] -> (WfC a, [WfC a])+findWfC kv ws = (w', ws')+ where+ (w, ws') = partition (elem kv . kvars . sr_reft . wrft) ws+ w' | [x] <- w = x+ | otherwise = errorstar $ (show kv) ++ " needs exactly one wf constraint"++extractPred :: WfC a -> BindEnv -> SubC a -> State (Integer, Pred) [(Symbol, Sort)]+extractPred wfc be subC = do (n, (POr preds)) <- get+ let (bs, (n', pr')) = runState (mapM renameVar vars) (n, PAnd $ pr : [(blah (kVarVV, slhs subC))] ++ suPreds')+ put (n', POr $ pr' : preds)+ return bs+ where+ wfcIBinds = elemsIBindEnv $ wenv wfc+ subcIBinds = elemsIBindEnv $ senv subC+ unmatchedIBinds | wfcIBinds `subset` subcIBinds = subcIBinds \\ wfcIBinds+ | otherwise = errorstar $ "kVar is not well formed (missing bindings)" ++ "kVar: " ++ (showFix wfc) ++ "constraint: " ++ (showFix subC)+ unmatchedIBindEnv = insertsIBindEnv unmatchedIBinds emptyIBindEnv+ unmatchedBindings = envCs be unmatchedIBindEnv++ kvSreft = wrft wfc+ kVarVV = reftBind $ sr_reft kvSreft++ (vars, pr) = baz unmatchedBindings++ reft = sr_reft $ srhs subC+ suPreds = substPreds $ reftPred reft+ sub = ((reftBind reft), (eVar kVarVV))+ suPreds' = [subst1 p sub | p <- suPreds]++-- on rhs, k0[v:=z] -> [v = z]+substPreds :: Pred -> [Pred]+substPreds (PKVar _ (Su subs)) = map (\(sym, expr) -> PAtom Eq (eVar sym) expr) subs++renameVar :: (Symbol, Sort) -> State (Integer, Pred) (Symbol, Sort)+renameVar (sym, srt) = do (n, pr) <- get+ let sym' = existSymbol sym n+ put ((n+1), subst1 pr (sym, eVar sym'))+ return (sym', srt)++subset :: (Eq a) => [a] -> [a] -> Bool+subset xs ys = (xs \\ ys) == []++-- [ x:{v:int|v=10} , y:{v:int|v=20} ] -> [x:int, y:int], (x=10) /\ (y=20)+baz :: [(Symbol, SortedReft)] -> ([(Symbol,Sort)],Pred)+baz bindings = (bs, PAnd $ map blah bindings)+ where+ bs = map (\(sym, sreft) -> (sym, sr_sort sreft)) bindings++-- [ x:{v:int|v=10} ] -> (x=10)+blah :: (Symbol, SortedReft) -> Pred+blah (sym, sr) = subst1 (reftPred reft) sub+ where+ reft = sr_reft sr+ sub = ((reftBind reft), (eVar sym))
+ src/Language/Fixpoint/Solver/Monad.hs view
@@ -0,0 +1,103 @@+-- | This is a wrapper around IO that permits SMT queries++module Language.Fixpoint.Solver.Monad+ ( -- * Type+ SolveM++ -- * Execution+ , runSolverM++ -- * Get Binds+ , getBinds++ -- * SMT Query+ , filterValid++ -- * Debug+ , tickIter++ )+ where++import Language.Fixpoint.Config (Config, inFile, solver)+import qualified Language.Fixpoint.Types as F+import qualified Language.Fixpoint.Errors as E+import Language.Fixpoint.SmtLib2+import Language.Fixpoint.Solver.Validate+import Language.Fixpoint.Solver.Solution+import Data.Maybe (catMaybes)+import Control.Applicative ((<$>))+import Control.Monad.State.Strict++---------------------------------------------------------------------------+-- | Solver Monadic API ---------------------------------------------------+---------------------------------------------------------------------------++type SolveM = StateT SolverState IO++data SolverState = SS { ssCtx :: !Context+ , ssBinds :: !F.BindEnv+ , ssIter :: !Int+ }++---------------------------------------------------------------------------+runSolverM :: Config -> F.FInfo b -> SolveM a -> IO a+---------------------------------------------------------------------------+runSolverM cfg fi act = do+ ctx <- makeContext (solver cfg) (inFile cfg)+ fst <$> runStateT (declare fi >> act) (SS ctx be 0)+ where+ be = F.bs fi++---------------------------------------------------------------------------+getBinds :: SolveM F.BindEnv+---------------------------------------------------------------------------+getBinds = ssBinds <$> get++---------------------------------------------------------------------------+getIter :: SolveM Int+---------------------------------------------------------------------------+getIter = ssIter <$> get++---------------------------------------------------------------------------+incIter :: SolveM ()+---------------------------------------------------------------------------+incIter = modify $ \s -> s {ssIter = 1 + ssIter s}++---------------------------------------------------------------------------+tickIter :: SolveM Int+---------------------------------------------------------------------------+tickIter = incIter >> getIter++withContext :: (Context -> IO a) -> SolveM a+withContext k = (lift . k) =<< getContext++getContext :: SolveM Context+getContext = ssCtx <$> get+++---------------------------------------------------------------------------+-- | SMT Interface --------------------------------------------------------+---------------------------------------------------------------------------+filterValid :: F.Pred -> Cand a -> SolveM [a]+---------------------------------------------------------------------------+filterValid p qs =+ withContext $ \me ->+ smtBracket me $+ filterValid_ p qs me++filterValid_ :: F.Pred -> Cand a -> Context -> IO [a]+filterValid_ p qs me = catMaybes <$> do+ smtAssert me p+ forM qs $ \(q, x) ->+ smtBracket me $ do+ smtAssert me (F.PNot q)+ valid <- smtCheckUnsat me+ return $ if valid then Just x else Nothing++---------------------------------------------------------------------------+declare :: F.FInfo a -> SolveM ()+---------------------------------------------------------------------------+declare fi = withContext $ \me -> do+ xts <- either E.die return $ symbolSorts fi+ forM_ xts $ uncurry $ smtDecl me
+ src/Language/Fixpoint/Solver/Solution.hs view
@@ -0,0 +1,229 @@+{-# LANGUAGE PatternGuards #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TupleSections #-}++module Language.Fixpoint.Solver.Solution+ ( -- * Solutions and Results+ Solution, Cand, EQual (..)++ -- * Types with Template/KVars+ , Solvable (..)++ -- * Initial Solution+ , init++ -- * Update Solution+ , update++ -- * Lookup Solution+ , lookup+ )+where++import Control.Applicative ((<$>))+import qualified Data.HashMap.Strict as M+import qualified Data.List as L+import Data.Maybe (maybeToList, isNothing) -- , fromMaybe)+import Language.Fixpoint.PrettyPrint+import Language.Fixpoint.Config+import Language.Fixpoint.Visitor as V+import qualified Language.Fixpoint.Sort as So+import Language.Fixpoint.Misc+import qualified Language.Fixpoint.Types as F+import Prelude hiding (init, lookup)+-- import Text.Printf (printf)++---------------------------------------------------------------------+-- | Types ----------------------------------------------------------+---------------------------------------------------------------------++type Solution = Sol KBind+type Sol a = M.HashMap F.KVar a+type KBind = [EQual]+type Cand a = [(F.Pred, a)]++lookup :: Solution -> F.KVar -> KBind+lookup s k = M.lookupDefault [] k s++---------------------------------------------------------------------+-- | Expanded or Instantiated Qualifier -----------------------------+---------------------------------------------------------------------++data EQual = EQL { eqQual :: !F.Qualifier+ , eqPred :: !F.Pred+ , eqArgs :: ![F.Expr]+ }+ deriving (Eq, Ord, Show)++instance PPrint EQual where+ pprint = pprint . eqPred++{-@ EQL :: q:_ -> p:_ -> ListX F.Expr {q_params q} -> _ @-}++eQual :: F.Qualifier -> [F.Symbol] -> EQual+eQual q xs = EQL q p es+ where+ p = F.subst su $ F.q_body q+ su = F.mkSubst $ safeZip "eQual" qxs es+ es = F.eVar <$> xs+ qxs = fst <$> F.q_params q++------------------------------------------------------------------------+-- | Update Solution ---------------------------------------------------+------------------------------------------------------------------------+update :: Solution -> [F.KVar] -> [(F.KVar, EQual)] -> (Bool, Solution)+-------------------------------------------------------------------------+update s ks kqs = {- tracepp msg -} (or bs, s')+ where+ kqss = groupKs ks kqs+ (bs, s') = folds update1 s kqss+ -- msg = printf "ks = %s, s = %s" (showpp ks) (showpp s)+++groupKs :: [F.KVar] -> [(F.KVar, EQual)] -> [(F.KVar, [EQual])]+groupKs ks kqs = M.toList $ groupBase m0 kqs+ where+ m0 = M.fromList $ (,[]) <$> ks++update1 :: Solution -> (F.KVar, KBind) -> (Bool, Solution)+update1 s (k, qs) = (change, M.insert k qs s)+ where+ oldQs = lookup s k+ change = length oldQs /= length qs+++--------------------------------------------------------------------+-- | Initial Solution (from Qualifiers and WF constraints) ---------+--------------------------------------------------------------------+init :: Config -> F.FInfo a -> Solution+--------------------------------------------------------------------+init _ fi = {- tracepp "init solution" -} s+ where+ s = L.foldl' (refine fi qs) s0 ws+ s0 = M.empty+ qs = F.quals fi+ ws = F.ws fi++--------------------------------------------------------------------+refine :: F.FInfo a+ -> [F.Qualifier]+ -> Solution+ -> F.WfC a+ -> Solution+--------------------------------------------------------------------+refine fi qs s w = refineK env qs s (wfKvar w)+ where+ env = F.fromListSEnv $ F.envCs (F.bs fi) (F.wenv w)+++refineK :: F.SEnv F.SortedReft+ -> [F.Qualifier]+ -> Solution+ -> (F.Symbol, F.Sort, F.KVar)+ -> Solution+refineK env qs s (v, t, k) = M.insert k eqs' s+ where+ eqs' = case M.lookup k s of+ Nothing -> instK env v t qs+ Just eqs -> [eq | eq <- eqs, okInst env v t eq]++--------------------------------------------------------------------+instK :: F.SEnv F.SortedReft+ -> F.Symbol+ -> F.Sort+ -> [F.Qualifier]+ -> [EQual]+--------------------------------------------------------------------+instK env v t = unique . concatMap (instKQ env v t)+ where+ unique qs = M.elems $ M.fromList [(eqPred q, q) | q <- qs ]++instKQ :: F.SEnv F.SortedReft+ -> F.Symbol+ -> F.Sort+ -> F.Qualifier+ -> [EQual]+instKQ env v t q+ = do (su0, v0) <- candidates [(v, t)] qt+ xs <- match xts [v0] (So.apply su0 <$> qts)+ return $ eQual q (reverse xs)+ where+ qt : qts = snd <$> F.q_params q+ xts = instCands env++instCands :: F.SEnv F.SortedReft -> [(F.Symbol, F.Sort)]+instCands = filter isOk . F.toListSEnv . fmap F.sr_sort+ where+ isOk = isNothing . F.functionSort . snd++match :: [(F.Symbol, F.Sort)] -> [F.Symbol] -> [F.Sort] -> [[F.Symbol]]+match xts xs (t : ts)+ = do (su, x) <- candidates xts t+ match xts (x : xs) (So.apply su <$> ts)+match _ xs []+ = return xs+++-----------------------------------------------------------------------+candidates :: [(F.Symbol, F.Sort)] -> F.Sort -> [(So.TVSubst, F.Symbol)]+-----------------------------------------------------------------------+candidates xts t'+ = [(su, x) | (x, t) <- xts, su <- maybeToList $ So.unify t' t]++-----------------------------------------------------------------------+wfKvar :: F.WfC a -> (F.Symbol, F.Sort, F.KVar)+-----------------------------------------------------------------------+wfKvar w@(F.WfC {F.wrft = sr})+ | F.Reft (v, F.Refa (F.PKVar k su)) <- F.sr_reft sr+ , F.isEmptySubst su = (v, F.sr_sort sr, k)+ | otherwise = errorstar $ "wfKvar: malformed wfC " ++ show w++-----------------------------------------------------------------------+okInst :: F.SEnv F.SortedReft -> F.Symbol -> F.Sort -> EQual -> Bool+-----------------------------------------------------------------------+okInst env v t eq = isNothing $ So.checkSortedReftFull env sr+ where+ sr = F.RR t (F.Reft (v, F.Refa (eqPred eq)))++---------------------------------------------------------------------+-- | Apply Solution -------------------------------------------------+---------------------------------------------------------------------++class Solvable a where+ apply :: Solution -> a -> F.Pred++instance Solvable EQual where+ apply _ = eqPred++instance Solvable F.KVar where+ apply s k = apply s $ safeLookup err k s+ where+ err = "apply: Unknown KVar " ++ show k++instance Solvable (F.KVar, F.Subst) where+ apply s (k, su) = F.subst su (apply s k)++instance Solvable F.Pred where+ apply s = V.trans (V.defaultVisitor {V.txPred = tx}) () ()+ where+ tx _ (F.PKVar k su) = apply s (k, su)+ tx _ p = p++instance Solvable F.Refa where+ apply s = apply s . F.raPred++instance Solvable F.Reft where+ apply s = apply s . F.reftPred++instance Solvable F.SortedReft where+ apply s = apply s . F.sr_reft++instance Solvable (F.Symbol, F.SortedReft) where+ apply s (x, sr) = p `F.subst1` (v, F.eVar x)+ where+ p = apply s r+ F.Reft (v, r) = F.sr_reft sr++instance Solvable a => Solvable [a] where+ apply s = F.pAnd . fmap (apply s)+
+ src/Language/Fixpoint/Solver/Solve.hs view
@@ -0,0 +1,114 @@+{-# LANGUAGE PatternGuards #-}+{-# LANGUAGE TupleSections #-}++-- | Solve a system of horn-clause constraints ----------------------------++module Language.Fixpoint.Solver.Solve (solve) where++import Control.Monad (filterM)+import Control.Applicative ((<$>))+import qualified Data.HashMap.Strict as M+import qualified Language.Fixpoint.Types as F+import Language.Fixpoint.Config+import Language.Fixpoint.PrettyPrint+import Language.Fixpoint.Solver.Validate+import qualified Language.Fixpoint.Solver.Solution as S+import qualified Language.Fixpoint.Solver.Worklist as W+import Language.Fixpoint.Solver.Monad+import qualified Data.List as L+import Debug.Trace (trace)+import Text.Printf (printf)+---------------------------------------------------------------------------+solve :: Config -> F.FInfo a -> IO (F.Result a)+---------------------------------------------------------------------------+solve cfg fi = runSolverM cfg fi' $ solve_ cfg fi'+ where+ Right fi' = validate cfg fi++---------------------------------------------------------------------------+solve_ :: Config -> F.FInfo a -> SolveM (F.Result a)+---------------------------------------------------------------------------+solve_ cfg fi = refine s0 wkl >>= result fi+ where+ s0 = S.init cfg fi+ wkl = W.init cfg fi++---------------------------------------------------------------------------+refine :: S.Solution -> W.Worklist a -> SolveM S.Solution+---------------------------------------------------------------------------+refine s w+ | Just (c, w') <- W.pop w = do i <- tickIter+ (b, s') <- refineC i s c+ let w'' = if b then W.push c w' else w'+ refine s' w''+ -- $ trace (refineMsg i c b w'') w''+ | otherwise = return s++-- DEBUG+-- refineMsg i c b w = printf "REFINE: iter = %d cid = %s change = %s wkl = %s"+-- i (show $ F.sid c) (show b) (showpp w)++---------------------------------------------------------------------------+-- | Single Step Refinement -----------------------------------------------+---------------------------------------------------------------------------+refineC :: Int -> S.Solution -> F.SubC a -> SolveM (Bool, S.Solution)+---------------------------------------------------------------------------+refineC i s c+ | null rhs = return (False, s)+ | otherwise = do lhs <- lhsPred s c <$> getBinds+ kqs <- filterValid lhs rhs+ return $ S.update s ks {- $ tracepp (msg ks rhs kqs) -} kqs+ where+ (ks, rhs) = rhsCands s c+ -- msg ks xs ys = printf "refineC: iter = %d, ks = %s, rhs = %d, rhs' = %d \n" i (showpp ks) (length xs) (length ys)++lhsPred :: S.Solution -> F.SubC a -> F.BindEnv -> F.Pred+lhsPred s c be = F.pAnd $ pGrd : pLhs : pBinds+ where+ pGrd = F.sgrd c+ pLhs = S.apply s $ F.lhsCs c+ pBinds = S.apply s <$> xts+ xts = F.envCs be $ F.senv c++rhsCands :: S.Solution -> F.SubC a -> ([F.KVar], S.Cand (F.KVar, S.EQual))+rhsCands s c = (fst <$> ks, kqs)+ where+ kqs = [ cnd k su q | (k, su) <- ks, q <- S.lookup s k]+ ks = predKs . F.reftPred . F.rhsCs $ c+ cnd k su q = (F.subst su (S.eqPred q), (k, q))++predKs :: F.Pred -> [(F.KVar, F.Subst)]+predKs (F.PAnd ps) = concatMap predKs ps+predKs (F.PKVar k su) = [(k, su)]+predKs _ = []++---------------------------------------------------------------------------+-- | Convert Solution into Result -----------------------------------------+---------------------------------------------------------------------------+result :: F.FInfo a -> S.Solution -> SolveM (F.Result a)+---------------------------------------------------------------------------+result fi s = (, sol) <$> result_ fi s+ where+ sol = M.map (F.pAnd . fmap S.eqPred) s++result_ :: F.FInfo a -> S.Solution -> SolveM (F.FixResult (F.SubC a))+result_ fi s = res <$> filterM (isUnsat s) cs+ where+ cs = M.elems $ F.cm fi+ res [] = F.Safe+ res cs' = F.Unsafe cs'++---------------------------------------------------------------------------+isUnsat :: S.Solution -> F.SubC a -> SolveM Bool+---------------------------------------------------------------------------+isUnsat s c = do+ lp <- lhsPred s c <$> getBinds+ let rp = rhsPred s c+ not <$> isValid lp rp++isValid :: F.Pred -> F.Pred -> SolveM Bool+isValid p q = (not . null) <$> filterValid p [(q, ())]++rhsPred :: S.Solution -> F.SubC a -> F.Pred+rhsPred s c = S.apply s $ F.rhsCs c+
+ src/Language/Fixpoint/Solver/Validate.hs view
@@ -0,0 +1,100 @@+-- | Validate and Transform Constraints to Ensure various Invariants -------------------------+-- 1. Each binder must be unique++module Language.Fixpoint.Solver.Validate+ ( -- * Validate and Transform FInfo to enforce invariants+ validate++ -- * Sorts for each Symbol+ , symbolSorts+ )+ where++import Language.Fixpoint.Config+import Language.Fixpoint.PrettyPrint+import qualified Language.Fixpoint.Misc as Misc+import qualified Language.Fixpoint.Types as F+import qualified Language.Fixpoint.Errors as E+import qualified Data.HashMap.Strict as M+import qualified Data.List as L+-- import Control.Monad (filterM)+-- import Control.Applicative ((<$>))+-- import Debug.Trace (trace)+import Text.Printf++---------------------------------------------------------------------------+validate :: Config -> F.FInfo a -> Either E.Error (F.FInfo a)+---------------------------------------------------------------------------+validate _ = Right . renameVV++---------------------------------------------------------------------------+-- | symbol |-> sort for EVERY variable in the FInfo+---------------------------------------------------------------------------+symbolSorts :: F.FInfo a -> Either E.Error [(F.Symbol, F.Sort)]+---------------------------------------------------------------------------+symbolSorts fi = compact . (\z -> lits ++ consts ++ z) =<< bindSorts fi+ where+ lits = F.lits fi+ consts = [(x, t) | (x, F.RR t _) <- F.toListSEnv $ F.gs fi]++compact :: [(F.Symbol, F.Sort)] -> Either E.Error [(F.Symbol, F.Sort)]+compact xts+ | null bad = Right [(x, t) | (x, [t]) <- ok ]+ | otherwise = Left $ dupBindErrors bad+ where+ (bad, ok) = L.partition multiSorted . binds $ xts+ binds = M.toList . M.map Misc.sortNub . Misc.group++---------------------------------------------------------------------------+bindSorts :: F.FInfo a -> Either E.Error [(F.Symbol, F.Sort)]+---------------------------------------------------------------------------+bindSorts fi+ | null bad = Right [ (x, t) | (x, [(t, _)]) <- ok ]+ | otherwise = Left $ dupBindErrors [ (x, map fst ts) | (x, ts) <- bad]+ where+ (bad, ok) = L.partition multiSorted . binds $ fi+ binds = symBinds . F.bs++multiSorted :: (x, [t]) -> Bool+multiSorted = (1 <) . length . snd++dupBindErrors :: [(F.Symbol, [F.Sort])] -> E.Error+dupBindErrors = foldr1 E.catError . map dbe+ where+ dbe (x, y) = E.err E.dummySpan $ printf "Multiple sorts for %s : %s \n" (showpp x) (showpp y)++---------------------------------------------------------------------------+symBinds :: F.BindEnv -> [SymBinds]+---------------------------------------------------------------------------+symBinds = M.toList+ . M.map Misc.groupList+ . Misc.group+ . binders++type SymBinds = (F.Symbol, [(F.Sort, [F.BindId])])++binders :: F.BindEnv -> [(F.Symbol, (F.Sort, F.BindId))]+binders be = [(x, (F.sr_sort t, i)) | (i, x, t) <- F.bindEnvToList be]++---------------------------------------------------------------------------+-- | Alpha Rename bindings to ensure each var appears in unique binder+---------------------------------------------------------------------------+renameVV :: F.FInfo a -> F.FInfo a+---------------------------------------------------------------------------+renameVV fi = fi {F.bs = be'}+ where+ vts = map subcVV $ M.elems $ F.cm fi+ be' = L.foldl' addVV be vts+ be = F.bs fi++addVV :: F.BindEnv -> (F.Symbol, F.SortedReft) -> F.BindEnv+addVV b (x, t) = snd $ F.insertBindEnv x t b++subcVV :: F.SubC a -> (F.Symbol, F.SortedReft)+subcVV c = (x, sr)+ where+ sr = F.slhs c+ x = F.reftBind $ F.sr_reft sr+++
+ src/Language/Fixpoint/Solver/Worklist.hs view
@@ -0,0 +1,128 @@+module Language.Fixpoint.Solver.Worklist+ ( -- * Worklist type is opaque+ Worklist++ -- * Initialize+ , init++ -- * Pop off a constraint+ , pop++ -- * Add a constraint and all its dependencies+ , push++ )+ where++import Prelude hiding (init)+import Language.Fixpoint.Solver.Deps+import Language.Fixpoint.PrettyPrint+import Language.Fixpoint.Misc+import Language.Fixpoint.Config+import qualified Language.Fixpoint.Types as F+import qualified Data.HashMap.Strict as M+import qualified Data.Set as S+import qualified Data.List as L+import Data.Maybe (fromMaybe)++---------------------------------------------------------------------------+-- | Worklist -------------------------------------------------------------+---------------------------------------------------------------------------++---------------------------------------------------------------------------+init :: Config -> F.FInfo a -> Worklist a+---------------------------------------------------------------------------+init _ fi = WL roots (cSucc cd) (F.cm fi)+ where+ cd = cDeps fi+ roots = S.fromList $ cRoots cd++---------------------------------------------------------------------------+pop :: Worklist a -> Maybe (F.SubC a, Worklist a)+---------------------------------------------------------------------------+pop w = do+ (i, is) <- sPop $ wCs w+ Just (getC (wCm w) i, w {wCs = is})++getC :: M.HashMap CId a -> CId -> a+getC cm i = fromMaybe err $ M.lookup i cm+ where+ err = errorstar "getC: bad CId i"++---------------------------------------------------------------------------+push :: F.SubC a -> Worklist a -> Worklist a+---------------------------------------------------------------------------+push c w = w {wCs = sAdds (wCs w) js}+ where+ i = sid' c+ js = {- tracepp ("PUSH: id = " ++ show i) $ -} wDeps w i++sid' :: F.SubC a -> Integer+sid' c = fromMaybe err $ F.sid c+ where+ err = errorstar "sid': SubC without id"++---------------------------------------------------------------------------+-- | Worklist -------------------------------------------------------------+---------------------------------------------------------------------------++type CId = Integer+type CSucc = CId -> [CId]+type KVRead = M.HashMap F.KVar [CId]++data Worklist a = WL { wCs :: S.Set CId+ , wDeps :: CSucc+ , wCm :: M.HashMap CId (F.SubC a)+ }++instance PPrint (Worklist a) where+ pprint = pprint . S.toList . wCs++---------------------------------------------------------------------------+-- | Constraint Dependencies ----------------------------------------------+---------------------------------------------------------------------------++data CDeps = CDs { cRoots :: ![CId]+ , cSucc :: CId -> [CId]+ }++cDeps :: F.FInfo a -> CDeps+cDeps fi = CDs rs next+ where+ next = kvSucc fi+ is = M.keys $ F.cm fi+ is' = concatMap next is+ rs = sortDiff is is'++kvSucc :: F.FInfo a -> CSucc+kvSucc fi = succs cm rdBy+ where+ rdBy = kvReadBy fi+ cm = F.cm fi++succs :: M.HashMap CId (F.SubC a) -> KVRead -> CSucc+succs cm rdBy i = sortNub $ concatMap kvReads iKs+ where+ ci = getC cm i+ iKs = rhsKVars ci+ kvReads k = M.lookupDefault [] k rdBy++kvReadBy :: F.FInfo a -> KVRead+kvReadBy fi = group [ (k, i) | (i, ci) <- M.toList cm+ , k <- {- tracepp ("lhsKVS: " ++ show i) $ -}+ lhsKVars bs ci]+ where+ cm = F.cm fi+ bs = F.bs fi+++---------------------------------------------------------------------------+-- | Set API --------------------------------------------------------------+---------------------------------------------------------------------------++sAdds :: (Ord a) => S.Set a -> [a] -> S.Set a+sAdds = L.foldl' (flip S.insert)++sPop :: S.Set a -> Maybe (a, S.Set a)+sPop = S.minView+
src/Language/Fixpoint/Sort.hs view
@@ -4,16 +4,24 @@ -- operations on Fixpoint expressions and predicates. module Language.Fixpoint.Sort (+ -- * Sort Substitutions+ TVSubst+ -- * Checking Well-Formedness- checkSorted+ , checkSorted , checkSortedReft , checkSortedReftFull , checkSortFull , pruneUnsortedReft- ) where + -- * Unify+ , unify + -- * Apply Substitution+ , apply+ ) where + import Control.Applicative import Control.Monad import Control.Monad.Error (catchError, throwError)@@ -30,9 +38,10 @@ type CheckM a = Either String a type Env = Symbol -> SESearch Sort-fProp = FApp boolFTyCon []--- fProp = FApp propFTyCon [] +fProp :: Sort+fProp = FApp boolFTyCon []+ ------------------------------------------------------------------------- -- | Checking Refinements ----------------------------------------------- -------------------------------------------------------------------------@@ -41,7 +50,7 @@ checkSortedReft env xs sr = applyNonNull Nothing error unknowns where error = Just . (text "Unknown symbols:" <+>) . toFix- unknowns = [ x | x <- syms sr, not (x `elem` v : xs), not (x `memberSEnv` env)]+ unknowns = [ x | x <- syms sr, x `notElem` v : xs, not (x `memberSEnv` env)] Reft (v,_) = sr_reft sr checkSortedReftFull :: Checkable a => SEnv SortedReft -> a -> Maybe Doc@@ -50,7 +59,7 @@ Left err -> Just (text err) Right _ -> Nothing where- γ' = mapSEnv sr_sort γ+ γ' = sr_sort <$> γ checkSortFull :: Checkable a => SEnv SortedReft -> Sort -> a -> Maybe Doc checkSortFull γ s t@@ -58,7 +67,7 @@ Left err -> Just (text err) Right _ -> Nothing where- γ' = mapSEnv sr_sort γ+ γ' = sr_sort <$> γ checkSorted :: Checkable a => SEnv Sort -> a -> Maybe Doc checkSorted γ t@@ -67,21 +76,19 @@ Right _ -> Nothing pruneUnsortedReft :: SEnv Sort -> SortedReft -> SortedReft-pruneUnsortedReft γ (RR s (Reft (v, ras)))- = RR s (Reft (v, catMaybes (go <$> ras)))+pruneUnsortedReft γ (RR s (Reft (v, Refa p))) = RR s (Reft (v, tx p)) where- go r = case checkRefa f r of- Left war -> trace (wmsg war r) $ Nothing- Right _ -> Just r- γ' = insertSEnv v s γ- f = (`lookupSEnvWithDistance` γ')-- wmsg t r = "WARNING: prune unsorted reft:\n" ++ showFix r ++ "\n" ++ t--checkRefa f (RConc p) = checkPred f p-checkRefa f _ = return ()-+ tx = refa . catMaybes . map (checkPred' f) . conjuncts+ f = (`lookupSEnvWithDistance` γ')+ γ' = insertSEnv v s γ+ -- wmsg t r = "WARNING: prune unsorted reft:\n" ++ showFix r ++ "\n" ++ t +checkPred' f p = res -- traceFix ("checkPred: p = " ++ showFix p) $ res+ where+ res = case checkPred f p of+ Left war -> {- trace (wmsg war p) -} Nothing+ Right _ -> Just p+ class Checkable a where check :: SEnv Sort -> a -> CheckM () checkSort :: SEnv Sort -> Sort -> a -> CheckM ()@@ -91,18 +98,16 @@ instance Checkable Refa where check γ = checkRefa (`lookupSEnvWithDistance` γ) +checkRefa f (Refa p) = checkPred f p+ instance Checkable Expr where check γ e = do {checkExpr f e; return ()} where f = (`lookupSEnvWithDistance` γ) - checkSort γ s e = checkExpr f (ECst e s) >> return ()+ checkSort γ s e = void $ checkExpr f (ECst e s) where f = (`lookupSEnvWithDistance` γ) - -- ORIG checkSort γ s e = do {t <- checkExpr f e; checkEqSort s t}- -- ORIG where f = (`lookupSEnvWithDistance` γ)-- checkEqSort s t | s == t = return () | otherwise = throwError $ "Couldn't match expected type '"@@ -115,8 +120,9 @@ where f = (`lookupSEnvWithDistance` γ) instance Checkable SortedReft where- check γ (RR s (Reft (v, ras))) = mapM_ (check γ') ras- where γ' = insertSEnv v s γ+ check γ (RR s (Reft (v, ra))) = check γ' ra+ where+ γ' = insertSEnv v s γ ------------------------------------------------------------------------- -- | Checking Expressions -----------------------------------------------@@ -125,8 +131,10 @@ checkExpr :: Env -> Expr -> CheckM Sort checkExpr _ EBot = throwError "Type Error: Bot"-checkExpr _ (ECon (I _)) = return FInt-checkExpr _ (ECon (R _)) = return FReal+checkExpr _ (ESym _) = return strSort+checkExpr _ (ECon (I _)) = return FInt +checkExpr _ (ECon (R _)) = return FReal +checkExpr _ (ECon (L _ s)) = return s checkExpr f (EVar x) = checkSym f x checkExpr f (ENeg e) = checkNeg f e checkExpr f (EBin o e1 e2) = checkOp f e1 o e2@@ -151,7 +159,7 @@ = do tp <- checkPred f p t1 <- checkExpr f e1 t2 <- checkExpr f e2- ((`apply` t1) <$> unify [t1] [t2]) `catchError` (\_ -> throwError $ errIte e1 e2 t1 t2)+ ((`apply` t1) <$> unifys [t1] [t2]) `catchError` (\_ -> throwError $ errIte e1 e2 t1 t2) -- | Helper for checking cast expressions @@ -159,7 +167,7 @@ = checkApp f (Just t) g es checkCst f t e = do t' <- checkExpr f e- ((`apply` t) <$> unify [t] [t']) `catchError` (\_ -> throwError $ errCast e t' t)+ ((`apply` t) <$> unifys [t] [t']) `catchError` (\_ -> throwError $ errCast e t' t) checkApp f to g es = snd <$> checkApp' f to g es@@ -170,7 +178,7 @@ (n, its, ot) <- sortFunction gt unless (length its == length es) $ throwError (errArgArity g its es) ets <- mapM (checkExpr f) es- θ <- unify its ets+ θ <- unifys its ets let t = apply θ ot case to of Nothing -> return (θ, t)@@ -222,9 +230,8 @@ ------------------------------------------------------------------------- checkPred :: Env -> Pred -> CheckM ()--checkPred f PTrue = return ()-checkPred f PFalse = return ()+checkPred _ PTrue = return ()+checkPred _ PFalse = return () checkPred f (PBexp e) = checkPredBExp f e checkPred f (PNot p) = checkPred f p checkPred f (PImp p p') = mapM_ (checkPred f) [p, p']@@ -232,15 +239,17 @@ checkPred f (PAnd ps) = mapM_ (checkPred f) ps checkPred f (POr ps) = mapM_ (checkPred f) ps checkPred f (PAtom r e e') = checkRel f r e e'-checkPred f p = throwError $ errUnexpectedPred p+checkPred _ (PKVar {}) = return ()+checkPred _ p = throwError $ errUnexpectedPred p +checkPredBExp :: Env -> Expr -> CheckM () checkPredBExp f e = do t <- checkExpr f e unless (t == fProp) (throwError $ errBExp e t) return () -- | Checking Relations-+checkRel :: (Symbol -> SESearch Sort) -> Brel -> Expr -> Expr -> CheckM () checkRel f Eq (EVar x) (EApp g es) = checkRelEqVar f x g es checkRel f Eq (EApp g es) (EVar x) = checkRelEqVar f x g es checkRel f r e1 e2 = do t1 <- checkExpr f e1@@ -250,26 +259,21 @@ checkRelTy :: (Fixpoint a) => Env -> a -> Brel -> Sort -> Sort -> CheckM () checkRelTy f _ _ (FObj l) (FObj l') | l /= l' = (checkNumeric f l >> checkNumeric f l') `catchError` (\_ -> throwError $ errNonNumerics l l')-checkRelTy f _ _ FInt (FObj l) = (checkNumeric f l) `catchError` (\_ -> throwError $ errNonNumeric l)-checkRelTy f _ _ (FObj l) FInt = (checkNumeric f l) `catchError` (\_ -> throwError $ errNonNumeric l)-checkRelTy f _ _ FReal FReal = return ()-checkRelTy f _ _ FReal (FObj l) = (checkFractional f l) `catchError` (\_ -> throwError $ errNonFractional l)-checkRelTy f _ _ (FObj l) FReal = (checkFractional f l) `catchError` (\_ -> throwError $ errNonFractional l)+checkRelTy f _ _ FInt (FObj l) = checkNumeric f l `catchError` (\_ -> throwError $ errNonNumeric l)+checkRelTy f _ _ (FObj l) FInt = checkNumeric f l `catchError` (\_ -> throwError $ errNonNumeric l)+checkRelTy _ _ _ FReal FReal = return ()+checkRelTy f _ _ FReal (FObj l) = checkFractional f l `catchError` (\_ -> throwError $ errNonFractional l)+checkRelTy f _ _ (FObj l) FReal = checkFractional f l `catchError` (\_ -> throwError $ errNonFractional l) checkRelTy _ e Eq t1 t2 | t1 == fProp || t2 == fProp = throwError $ errRel e t1 t2 checkRelTy _ e Ne t1 t2 | t1 == fProp || t2 == fProp = throwError $ errRel e t1 t2-checkRelTy _ e Eq t1 t2 = unify [t1] [t2] >> return ()-checkRelTy _ e Ne t1 t2 = unify [t1] [t2] >> return ()---- ORIG checkRelTy _ e Eq t1 t2 = unless (t1 == t2 && t1 /= fProp) (throwError $ errRel e t1 t2)--- ORIG checkRelTy _ e Ne t1 t2 = unless (t1 == t2 && t1 /= fProp) (throwError $ errRel e t1 t2)--+checkRelTy _ e Eq t1 t2 = unifys [t1] [t2] >> return ()+checkRelTy _ e Ne t1 t2 = unifys [t1] [t2] >> return () -checkRelTy _ e Ueq t1 t2 = unless (isAppTy t1 && isAppTy t2) (throwError $ errRel e t1 t2)-checkRelTy _ e Une t1 t2 = unless (isAppTy t1 && isAppTy t2) (throwError $ errRel e t1 t2)+checkRelTy _ e Ueq t1 t2 = return ()+checkRelTy _ e Une t1 t2 = return () checkRelTy _ e _ t1 t2 = unless (t1 == t2) (throwError $ errRel e t1 t2) @@ -285,8 +289,8 @@ isAppTy _ = False -isPoly :: Sort -> Bool-isPoly = not . null . fVars+-- isPoly :: Sort -> Bool+-- isPoly = not . null . fVars fVars (FVar i) = [i] fVars (FFunc _ ts) = concatMap fVars ts@@ -295,90 +299,58 @@ ---------------------------------------------------------------------------- | Error messages -----------------------------------------------------+-- | Unification of Sorts ---------------------------------------------------------------------------errUnify t1 t2 = printf "Cannot unify %s with %s" (showFix t1) (showFix t2)--errUnifyMany ts ts' = printf "Cannot unify types with different cardinalities %s and %s"- (showFix ts) (showFix ts')--errRel e t1 t2 = printf "Invalid Relation %s with operand types %s and %s"- (showFix e) (showFix t1) (showFix t2)--errBExp e t = printf "BExp %s with non-propositional type %s" (showFix e) (showFix t)--errOp e t t'- | t == t' = printf "Operands have non-numeric types %s in %s"- (showFix t) (showFix e)- | otherwise = printf "Operands have different types %s and %s in %s"- (showFix t) (showFix t') (showFix e)--errArgArity g its es = printf "Measure %s expects %d args but gets %d in %s"- (showFix g) (length its) (length es) (showFix (EApp g es))--errIte e1 e2 t1 t2 = printf "Mismatched branches in Ite: then %s : %s, else %s : %s"- (showFix e1) (showFix t1) (showFix e2) (showFix t2)--errCast e t' t = printf "Cannot cast %s of sort %s to incompatible sort %s"- (showFix e) (showFix t') (showFix t)--errUnbound x = printf "Unbound Symbol %s" (showFix x)-errUnboundAlts x xs = printf "Unbound Symbol %s\n Perhaps you meant: %s"- (showFix x)- (foldr1 (\w s -> w ++ ", " ++ s) (showFix <$> xs))--errNonFunction t = printf "Sort %s is not a function" (showFix t)--errNonNumeric l = printf "FObj sort %s is not numeric" (showFix l)-errNonNumerics l l' = printf "FObj sort %s and %s are different and not numeric" (showFix l) (showFix l')--errNonFractional l = printf "FObj sort %s is not fractional" (showFix l)--errUnexpectedPred p = printf "Sort Checking: Unexpected Predicate %s" (showFix p)+unify :: Sort -> Sort -> Maybe TVSubst+-------------------------------------------------------------------------+unify t1 t2 = case unify1 emptySubst t1 t2 of+ Left _ -> Nothing+ Right su -> Just su ---------------------------------------------------------------------------- | Utilities for working with sorts -----------------------------------+unifys :: [Sort] -> [Sort] -> CheckM TVSubst ----------------------------------------------------------------------------- | Unification of Sorts--unify = unifyMany (Th M.empty)+unifys = unifyMany emptySubst +unifyMany :: TVSubst -> [Sort] -> [Sort] -> CheckM TVSubst unifyMany θ ts ts'- | length ts == length ts' = foldM (uncurry . unify1) θ $ zip ts ts'- | otherwise = throwError $ errUnifyMany ts ts'+ | length ts == length ts' = foldM (uncurry . unify1) θ $ zip ts ts'+ | otherwise = throwError $ errUnifyMany ts ts' --- unify1 _ FNum _ = Nothing-unify1 θ (FVar i) t = unifyVar θ i t-unify1 θ t (FVar i) = unifyVar θ i t+unify1 :: TVSubst -> Sort -> Sort -> CheckM TVSubst+unify1 θ (FVar i) t = unifyVar θ i t+unify1 θ t (FVar i) = unifyVar θ i t unify1 θ (FApp c ts) (FApp c' ts')- | c == c' = unifyMany θ ts ts'+ | c == c' = unifyMany θ ts ts' unify1 θ t1 t2- | t1 == t2 = return θ- | otherwise = throwError $ errUnify t1 t2+ | t1 == t2 = return θ+ | otherwise = throwError $ errUnify t1 t2+-- unify1 _ FNum _ = Nothing -unifyVar θ i t+unifyVar :: TVSubst -> Int -> Sort -> CheckM TVSubst+unifyVar θ i t@(FVar j) = case lookupVar i θ of- Just t' -> if t == t' then return θ else throwError (errUnify t t')- Nothing -> return $ updateVar i t θ---- | Sort Substitutions-newtype TVSubst = Th (M.HashMap Int Sort)+ Just t' -> if t == t' then return θ else return $ updateVar j t' θ+ Nothing -> return $ updateVar i t θ --- | API for manipulating substitutions-lookupVar i (Th m) = M.lookup i m-updateVar i t (Th m) = Th (M.insert i t m)+unifyVar θ i t+ = case lookupVar i θ of+ Just t' -> if t == t' then return θ else throwError (errUnify t t')+ Nothing -> return $ updateVar i t θ ------------------------------------------------------------------------- -- | Applying a Type Substitution --------------------------------------- --------------------------------------------------------------------------+apply :: TVSubst -> Sort -> Sort+------------------------------------------------------------------------- apply θ = sortMap f where f t@(FVar i) = fromMaybe t (lookupVar i θ) f t = t +-------------------------------------------------------------------------+sortMap :: (Sort -> Sort) -> Sort -> Sort+------------------------------------------------------------------------- sortMap f (FFunc n ts) = FFunc n (sortMap f <$> ts) sortMap f (FApp c ts) = FApp c (sortMap f <$> ts) sortMap f t = f t@@ -387,6 +359,7 @@ -- | Deconstruct a function-sort --------------------------------------- ------------------------------------------------------------------------ +sortFunction :: Sort -> CheckM (Int, [Sort], Sort) sortFunction (FFunc n ts') = return (n, ts, t) where ts = take numArgs ts'@@ -394,3 +367,52 @@ numArgs = length ts' - 1 sortFunction t = throwError $ errNonFunction t+++------------------------------------------------------------------------+-- | API for manipulating Sort Substitutions ---------------------------+------------------------------------------------------------------------++newtype TVSubst = Th (M.HashMap Int Sort)++lookupVar :: Int -> TVSubst -> Maybe Sort+lookupVar i (Th m) = M.lookup i m++updateVar :: Int -> Sort -> TVSubst -> TVSubst+updateVar i t (Th m) = Th (M.insert i t m)++emptySubst :: TVSubst+emptySubst = Th M.empty++-------------------------------------------------------------------------+-- | Error messages -----------------------------------------------------+-------------------------------------------------------------------------++errUnify t1 t2 = printf "Cannot unify %s with %s" (showFix t1) (showFix t2)++errUnifyMany ts ts' = printf "Cannot unify types with different cardinalities %s and %s"+ (showFix ts) (showFix ts')+errRel e t1 t2 = printf "Invalid Relation %s with operand types %s and %s"+ (showFix e) (showFix t1) (showFix t2)+errBExp e t = printf "BExp %s with non-propositional type %s" (showFix e) (showFix t)+errOp e t t'+ | t == t' = printf "Operands have non-numeric types %s in %s"+ (showFix t) (showFix e)+ | otherwise = printf "Operands have different types %s and %s in %s"+ (showFix t) (showFix t') (showFix e)+errArgArity g its es = printf "Measure %s expects %d args but gets %d in %s"+ (showFix g) (length its) (length es) (showFix (EApp g es))+errIte e1 e2 t1 t2 = printf "Mismatched branches in Ite: then %s : %s, else %s : %s"+ (showFix e1) (showFix t1) (showFix e2) (showFix t2)+errCast e t' t = printf "Cannot cast %s of sort %s to incompatible sort %s"+ (showFix e) (showFix t') (showFix t)+errUnbound x = printf "Unbound Symbol %s" (showFix x)+errUnboundAlts x xs = printf "Unbound Symbol %s\n Perhaps you meant: %s"+ (showFix x)+ (foldr1 (\w s -> w ++ ", " ++ s) (showFix <$> xs))+errNonFunction t = printf "Sort %s is not a function" (showFix t)+errNonNumeric l = printf "FObj sort %s is not numeric" (showFix l)+errNonNumerics l l' = printf "FObj sort %s and %s are different and not numeric" (showFix l) (showFix l')+errNonFractional l = printf "FObj sort %s is not fractional" (showFix l)+errUnexpectedPred p = printf "Sort Checking: Unexpected Predicate %s" (showFix p)+
src/Language/Fixpoint/Types.hs view
@@ -7,14 +7,14 @@ {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE NoMonomorphismRestriction #-} {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE UndecidableInstances #-} ---- | This module contains the data types, operations and serialization functions--- for representing Fixpoint's implication (i.e. subtyping) and well-formedness--- constraints in Haskell. The actual constraint solving is done by the--- `fixpoint.native` which is written in Ocaml.+-- | This module contains the data types, operations and+-- serialization functions for representing Fixpoint's+-- implication (i.e. subtyping) and well-formedness+-- constraints in Haskell. The actual constraint+-- solving is done by the `fixpoint.native` which+-- is written in Ocaml. module Language.Fixpoint.Types ( @@ -29,8 +29,9 @@ , resultDoc -- * Symbols- , Symbol(..)- , anfPrefix, tempPrefix, vv, intKvar+ , Symbol+ , KVar (..)+ , anfPrefix, tempPrefix, vv, vv_, intKvar , symChars, isNonSymbol, nonSymbol , isNontrivialVV , symbolText, symbolString@@ -49,11 +50,16 @@ , realFTyCon , strFTyCon , propFTyCon+ , listFTyCon , appFTyCon , fTyconSymbol , symbolFTycon++ , strSort , fApp , fObj+ , isListTC+ , isFAppTyTC -- * Expressions and Predicates , SymConst (..)@@ -65,44 +71,53 @@ , pAnd, pOr, pIte , isTautoPred , symConstLits- , zero -- * Generalizing Embedding with Typeclasses , Symbolic (..) , Expression (..) , Predicate (..) - -- * Constraints and Solutions- , SubC --(..)- , WfC --(..)- , sid- , subC, lhsCs, rhsCs, wfC+ -- * Constraints+ , WfC (..)+ , SubC, sid, sgrd, senv, slhs, srhs, subC, lhsCs, rhsCs, wfC , Tag- , FixResult (..)- , FixSolution++ -- * Accessing Constraints+ , envCs , addIds, sinfo , trueSubCKvar , removeLhsKvars + -- * Solutions+ , Result+ , FixResult (..)+ , FixSolution+ -- * Environments , SEnv, SESearch(..) , emptySEnv, toListSEnv, fromListSEnv- , mapSEnv, mapSEnvWithKey+ -- , mapSEnv+ , mapSEnvWithKey , insertSEnv, deleteSEnv, memberSEnv, lookupSEnv , intersectWithSEnv , filterSEnv , lookupSEnvWithDistance , FEnv, insertFEnv- , IBindEnv, BindId- , emptyIBindEnv, insertsIBindEnv, deleteIBindEnv+ , IBindEnv, BindId, BindMap+ , emptyIBindEnv, insertsIBindEnv, deleteIBindEnv, elemsIBindEnv+ , BindEnv- , rawBindEnv, insertBindEnv, emptyBindEnv, mapBindEnv+ , insertBindEnv, emptyBindEnv, lookupBindEnv, mapBindEnv+ , bindEnvFromList, bindEnvToList+ , unionIBindEnv -- * Refinements , Refa (..), SortedReft (..), Reft(..), Reftable(..) -- * Constructing Refinements+ , refa+ , reft -- "smart , trueSortedReft -- trivial reft , trueRefa -- trivial reft , trueReft -- trivial reft@@ -113,19 +128,21 @@ , usymbolReft -- singleton: v ~~ x , propReft -- singleton: Prop(v) <=> p , predReft -- any pred : p- , isFunctionSortedReft- , isNonTrivialSortedReft- , isTautoReft+ , reftPred, reftBind+ , isFunctionSortedReft, functionSort+ , isNonTrivial , isSingletonReft , isEVar , isFalse- , flattenRefas, squishRefas+ , flattenRefas, squishRefas, conjuncts , shiftVV+ , mapPredReft -- * Substitutions- , Subst+ , Subst (..) , Subable (..) , mkSubst+ , isEmptySubst -- , emptySubst -- , catSubst , substExcept@@ -134,9 +151,6 @@ , sortSubst , targetSubstSyms - -- * Visitors- , reftKVars- -- * Functions on @Result@ , colorResult @@ -163,23 +177,20 @@ import Data.Typeable (Typeable) import GHC.Generics (Generic) -import Data.Char (chr, isAlpha, isUpper, ord, toLower)+import Data.Char (toLower) import qualified Data.Foldable as F import Data.Functor import Data.Hashable-import Data.Interned-import Data.List (foldl', intersect, nub, sort,- stripPrefix)+-- import Data.Interned+import Data.List (foldl', intersect, nub, sort) import Data.Monoid hiding ((<>)) import Data.String import Data.Text (Text) import qualified Data.Text as T import Data.Traversable--import Control.Arrow ((***)) import Control.DeepSeq import Control.Exception (assert)-import Data.Maybe (fromMaybe)+import Data.Maybe (isJust, mapMaybe, listToMaybe, fromMaybe) import Text.Printf (printf) import Language.Fixpoint.Misc@@ -191,6 +202,7 @@ import qualified Data.HashSet as S import Language.Fixpoint.Names + class Fixpoint a where toFix :: a -> Doc @@ -208,7 +220,7 @@ | Wfc (WfC a) | Con Symbol Sort | Qul Qualifier- | Kut Symbol+ | Kut KVar | IBind Int Symbol SortedReft deriving (Generic) -- Sol of solbind@@ -220,19 +232,14 @@ showFix = render . toFix traceFix :: (Fixpoint a) => String -> a -> a-traceFix s x = trace ("\nTrace: [" ++ s ++ "] : " ++ showFix x) $ x+traceFix s x = trace ("\nTrace: [" ++ s ++ "] : " ++ showFix x) x type TCEmb a = M.HashMap a FTycon --- instance (Eq a, Hashable a) => Monoid (TCEmb a) where--- mappend m1 m2 = M.fromList (M.toList m1 ++ M.toList m2)--- mempty = M.empty- exprSymbols :: Expr -> [Symbol] exprSymbols = go where go (EVar x) = [x]- -- go (EDat x _) = [x] go (ELit x _) = [val x] go (EApp f es) = val f : concatMap go es go (ENeg e) = go e@@ -244,32 +251,42 @@ predSymbols :: Pred -> [Symbol] predSymbols = go where- go (PAnd ps) = concatMap go ps- go (POr ps) = concatMap go ps- go (PNot p) = go p- go (PIff p1 p2) = go p1 ++ go p2- go (PImp p1 p2) = go p1 ++ go p2- go (PBexp e) = exprSymbols e- go (PAtom _ e1 e2) = exprSymbols e1 ++ exprSymbols e2- go (PAll xts p) = (fst <$> xts) ++ go p- go _ = []--reftKVars :: Reft -> [Symbol]-reftKVars (Reft (_,ras)) = [k | (RKvar k _) <- ras]+ go (PAnd ps) = concatMap go ps+ go (POr ps) = concatMap go ps+ go (PNot p) = go p+ go (PIff p1 p2) = go p1 ++ go p2+ go (PImp p1 p2) = go p1 ++ go p2+ go (PBexp e) = exprSymbols e+ go (PAtom _ e1 e2) = exprSymbols e1 ++ exprSymbols e2+ go (PKVar _ (Su su')) = {- CUTSOLVER k : -} concatMap syms su'+ go (PAll xts p) = (fst <$> xts) ++ go p+ go _ = [] --------------------------------------------------------------- ---------- (Kut) Sets of Kvars -------------------------------- ---------------------------------------------------------------+newtype KVar = KV {kv :: Symbol } deriving (Eq, Ord, Data, Typeable, Generic, IsString) -newtype Kuts = KS (S.HashSet Symbol)+intKvar :: Integer -> KVar+intKvar = KV . intSymbol "k_" +instance Show KVar where+ show (KV x) = "$" ++ show x++instance Hashable KVar++newtype Kuts = KS { ksVars :: S.HashSet KVar } deriving (Show)+ instance NFData Kuts where rnf (KS _) = () -- rnf s instance Fixpoint Kuts where toFix (KS s) = vcat $ ((text "cut " <>) . toFix) <$> S.toList s +ksEmpty :: Kuts ksEmpty = KS S.empty++ksUnion :: [KVar] -> Kuts -> Kuts ksUnion kvs (KS s') = KS (S.union (S.fromList kvs) s') ---------------------------------------------------------------@@ -289,31 +306,36 @@ simplify = map simplify instance (Fixpoint a, Fixpoint b) => Fixpoint (a,b) where- toFix (x,y) = (toFix x) <+> text ":" <+> (toFix y)+ toFix (x,y) = toFix x <+> text ":" <+> toFix y simplify (x,y) = (simplify x, simplify y) -toFix_gs (SE e)- = vcat $ map (toFix_constant . mapSnd sr_sort) $ hashMapToAscList e-toFix_constant (c, so)- = text "constant" <+> toFix c <+> text ":" <+> toFix so+toFixGs :: SEnv SortedReft -> Doc+toFixGs (SE e) = vcat $ map (toFixConstant . mapSnd sr_sort) $ hashMapToAscList e +toFixConstant (c, so)+ = text "constant" <+> toFix c <+> text ":" <+> parens (toFix so)+ ---------------------------------------------------------------------- ------------------------ Type Constructors --------------------------- ---------------------------------------------------------------------- newtype FTycon = TC LocSymbol deriving (Eq, Ord, Show, Data, Typeable, Generic) +intFTyCon, boolFTyCon, realFTyCon, strFTyCon, propFTyCon, appFTyCon, listFTyCon :: FTycon intFTyCon = TC $ dummyLoc "int" boolFTyCon = TC $ dummyLoc "bool" realFTyCon = TC $ dummyLoc "real" strFTyCon = TC $ dummyLoc strConName propFTyCon = TC $ dummyLoc propConName+listFTyCon = TC $ dummyLoc listConName appFTyCon = TC $ dummyLoc "FAppTy" -isListTC (TC (Loc _ c)) = c == listConName-isTupTC (TC (Loc _ c)) = c == tupConName+isListTC, isFAppTyTC :: FTycon -> Bool+isListTC (TC (Loc _ _ c)) = c == listConName+isTupTC (TC (Loc _ _ c)) = c == tupConName isFAppTyTC = (== appFTyCon) +fTyconSymbol :: FTycon -> Located Symbol fTyconSymbol (TC s) = s symbolFTycon :: LocSymbol -> FTycon@@ -334,7 +356,8 @@ | otherwise = fAppSorts (fTyconSort c) ts fApp (Right t) ts = fAppSorts t ts -fAppSorts t ts = foldl' (\t1 t2 -> FApp appFTyCon [t1, t2]) t ts+fAppSorts :: Sort -> [Sort] -> Sort+fAppSorts = foldl' (\t1 t2 -> FApp appFTyCon [t1, t2]) fTyconSort :: FTycon -> Sort fTyconSort = (`FApp` [])@@ -357,31 +380,32 @@ | FApp FTycon [Sort] -- ^ constructed type deriving (Eq, Ord, Show, Data, Typeable, Generic) +{-@ FFunc :: Nat -> ListNE Sort -> Sort @-}+ instance Hashable Sort newtype Sub = Sub [(Int, Sort)] instance Fixpoint Sort where- toFix = toFix_sort+ toFix = toFixSort -toFix_sort (FVar i) = text "@" <> parens (toFix i)-toFix_sort FInt = text "int"-toFix_sort FReal = text "real"-toFix_sort FFrac = text "frac"-toFix_sort (FObj x) = toFix x-toFix_sort FNum = text "num"-toFix_sort (FFunc n ts) = text "func" <> parens ((toFix n) <> (text ", ") <> (toFix ts))-toFix_sort (FApp c [t])- | isListTC c- = brackets $ toFix_sort t-toFix_sort (FApp c [FApp c' [],t])- | isFAppTyTC c && isListTC c'- = brackets $ toFix_sort t-toFix_sort (FApp c ts)- | otherwise- = toFix c <+> intersperse space (fp <$> ts)- where fp s@(FApp _ (_:_)) = parens $ toFix_sort s- fp s = toFix_sort s+toFixSort :: Sort -> Doc+toFixSort (FVar i) = text "@" <> parens (toFix i)+toFixSort FInt = text "int"+toFixSort FReal = text "real"+toFixSort FFrac = text "frac"+toFixSort (FObj x) = toFix x+toFixSort FNum = text "num"+toFixSort (FFunc n ts) = text "func" <> parens (toFix n <> text ", " <> toFix ts)+toFixSort (FApp c [t])+ | isListTC c = brackets $ toFixSort t+toFixSort (FApp c [FApp c' [],t])+ | isFAppTyTC c &&+ isListTC c' = brackets $ toFixSort t+toFixSort (FApp c ts) = toFix c <+> intersperse space (fp <$> ts)+ where+ fp s@(FApp _ (_:_)) = parens $ toFixSort s+ fp s = toFixSort s instance Fixpoint FTycon where@@ -389,7 +413,7 @@ -------------------------------------------------------------------------sortSubst :: (M.HashMap Symbol Sort) -> Sort -> Sort+sortSubst :: M.HashMap Symbol Sort -> Sort -> Sort ------------------------------------------------------------------------ sortSubst θ t@(FObj x) = fromMaybe t (M.lookup x θ) sortSubst θ (FFunc n ts) = FFunc n (sortSubst θ <$> ts)@@ -403,8 +427,9 @@ instance Fixpoint Subst where toFix (Su m) = case {- hashMapToAscList -} m of [] -> empty- xys -> hcat $ map (\(x,y) -> brackets $ (toFix x) <> text ":=" <> (toFix y)) xys+ xys -> hcat $ map (\(x,y) -> brackets $ toFix x <> text ":=" <> toFix y) xys +targetSubstSyms :: Subst -> [Symbol] targetSubstSyms (Su ms) = syms $ snd <$> ms @@ -458,6 +483,9 @@ instance Fixpoint Symbol where toFix = text . encode . T.unpack . symbolText +instance Fixpoint KVar where+ toFix (KV k) = text "$" <> toFix k+ instance Fixpoint Text where toFix = text . T.unpack @@ -484,7 +512,7 @@ toFix (ECon c) = toFix c toFix (EVar s) = toFix s toFix (ELit s _) = toFix s- toFix (EApp f es) = (toFix f) <> (parens $ toFix es)+ toFix (EApp f es) = toFix f <> parens (toFix es) toFix (ENeg e) = parens $ text "-" <+> parens (toFix e) toFix (EBin o e1 e2) = parens $ toFix e1 <+> toFix o <+> toFix e2 toFix (EIte p e1 e2) = parens $ toFix p <+> text "?" <+> toFix e1 <+> text ":" <+> toFix e2@@ -495,31 +523,48 @@ --------------------- Predicates ------------------------- ---------------------------------------------------------- + data Pred = PTrue | PFalse- | PAnd ![Pred]- | POr ![Pred]- | PNot !Pred- | PImp !Pred !Pred- | PIff !Pred !Pred- | PBexp !Expr- | PAtom !Brel !Expr !Expr- | PAll ![(Symbol, Sort)] !Pred+ | PAnd ![Pred]+ | POr ![Pred]+ | PNot !Pred+ | PImp !Pred !Pred+ | PIff !Pred !Pred+ | PBexp !Expr+ | PAtom !Brel !Expr !Expr+ | PKVar !KVar !Subst+ | PAll ![(Symbol, Sort)] !Pred | PTop deriving (Eq, Ord, Show, Data, Typeable, Generic) +{-@ type ListNE a = {v:[a] | 0 < len v} @-}++{-@ PAnd :: ListNE Pred -> Pred @-}++++instance Hashable Brel+instance Hashable Bop+instance Hashable SymConst+instance Hashable Constant+instance Hashable Subst+instance Hashable Expr+instance Hashable Pred+ instance Fixpoint Pred where toFix PTop = text "???" toFix PTrue = text "true" toFix PFalse = text "false" toFix (PBexp e) = parens $ text "?" <+> toFix e toFix (PNot p) = parens $ text "~" <+> parens (toFix p)- toFix (PImp p1 p2) = parens $ (toFix p1) <+> text "=>" <+> (toFix p2)- toFix (PIff p1 p2) = parens $ (toFix p1) <+> text "<=>" <+> (toFix p2)+ toFix (PImp p1 p2) = parens $ toFix p1 <+> text "=>" <+> toFix p2+ toFix (PIff p1 p2) = parens $ toFix p1 <+> text "<=>" <+> toFix p2 toFix (PAnd ps) = text "&&" <+> toFix ps toFix (POr ps) = text "||" <+> toFix ps toFix (PAtom r e1 e2) = parens $ toFix e1 <+> toFix r <+> toFix e2- toFix (PAll xts p) = text "forall" <+> (toFix xts) <+> text "." <+> (toFix p)+ toFix (PKVar k su) = toFix k <> toFix su+ toFix (PAll xts p) = text "forall" <+> toFix xts <+> text "." <+> toFix p simplify (PAnd []) = PTrue simplify (POr []) = PFalse@@ -539,9 +584,7 @@ | isTautoPred p = PTrue | otherwise = p -zero = ECon (I 0)-one = ECon (I 1)-+isContraPred :: Pred -> Bool isContraPred z = eqC z || (z `elem` contras) where contras = [PFalse]@@ -556,10 +599,9 @@ = x == y eqC _ = False -isTautoPred z = eqT z || (z `elem` tautos)+isTautoPred :: Pred -> Bool+isTautoPred z = z == PTop || z == PTrue || eqT z where- tautos = [PTop, PTrue]- eqT (PAtom Le x y) = x == y eqT (PAtom Ge x y)@@ -574,20 +616,29 @@ = x /= y eqT _ = False --isTautoReft (Reft (_, ras)) = all isTautoRa ras-isTautoRa (RConc p) = isTautoPred p-isTautoRa _ = False-+isEVar :: Expr -> Bool isEVar (EVar _) = True isEVar _ = False +isEq :: Brel -> Bool isEq r = r == Eq || r == Ueq -isSingletonReft (Reft (v, [RConc (PAtom r e1 e2)]))+isSingletonReft :: Reft -> Maybe Expr+isSingletonReft (Reft (v, ra)) = firstMaybe (isSingletonExpr v) $ conjuncts $ raPred ra++firstMaybe :: (a -> Maybe b) -> [a] -> Maybe b+firstMaybe f = listToMaybe . mapMaybe f++-- where +-- go (PAtom r e1 e2) | e1 == EVar v && isEq r = Just e2+-- | e2 == EVar v && isEq r = Just e1+-- go _ = Nothing++isSingletonExpr :: Symbol -> Pred -> Maybe Expr+isSingletonExpr v (PAtom r e1 e2) | e1 == EVar v && isEq r = Just e2 | e2 == EVar v && isEq r = Just e1-isSingletonReft _ = Nothing+isSingletonExpr _ _ = Nothing pAnd = simplify . PAnd pOr = simplify . POr@@ -595,17 +646,17 @@ mkProp = PBexp . EApp (dummyLoc propConName) . (: []) -ppr_reft (Reft (v, ras)) d- | all isTautoRa ras+pprReft (Reft (v, Refa p)) d+ | isTautoPred p = d | otherwise- = braces (toFix v <+> colon <+> d <+> text "|" <+> ppRas ras)+ = braces (toFix v <+> colon <+> d <+> text "|" <+> ppRas [Refa p]) -ppr_reft_pred (Reft (_, ras))- | all isTautoRa ras+pprReftPred (Reft (_, Refa p))+ | isTautoPred p = text "true" | otherwise- = ppRas ras+ = ppRas [Refa p] ppRas = cat . punctuate comma . map toFix . flattenRefas @@ -660,7 +711,7 @@ eProp = mkProp . eVar relReft :: (Expression a) => Brel -> a -> Reft-relReft r e = Reft (vv_, [RConc $ PAtom r (eVar vv_) (expr e)])+relReft r e = Reft (vv_, Refa $ PAtom r (eVar vv_) (expr e)) exprReft, notExprReft, uexprReft :: (Expression a) => a -> Reft exprReft = relReft Eq@@ -668,21 +719,27 @@ uexprReft = relReft Ueq propReft :: (Predicate a) => a -> Reft-propReft p = Reft (vv_, [RConc $ PIff (eProp vv_) (prop p)])+propReft p = Reft (vv_, Refa $ PIff (eProp vv_) (prop p)) predReft :: (Predicate a) => a -> Reft-predReft p = Reft (vv_, [RConc $ prop p])+predReft p = Reft (vv_, Refa $ prop p) +reft :: Symbol -> Pred -> Reft+reft v p = Reft (v, Refa p)++mapPredReft :: (Pred -> Pred) -> Reft -> Reft+mapPredReft f (Reft (v, Refa p)) = Reft (v, Refa (f p))++ --------------------------------------------------------------- ----------------- Refinements --------------------------------- --------------------------------------------------------------- -data Refa- = RConc !Pred- | RKvar !Symbol !Subst- deriving (Eq, Ord, Show, Data, Typeable, Generic)+newtype Refa = Refa { raPred :: Pred }+ deriving (Eq, Ord, Show, Data, Typeable, Generic) -newtype Reft = Reft (Symbol, [Refa]) deriving (Eq, Ord, Data, Typeable, Generic)+newtype Reft = Reft (Symbol, Refa)+ deriving (Eq, Ord, Data, Typeable, Generic) instance Show Reft where show (Reft x) = render $ toFix x@@ -690,24 +747,43 @@ data SortedReft = RR { sr_sort :: !Sort, sr_reft :: !Reft } deriving (Eq, Show, Data, Typeable, Generic) -isNonTrivialSortedReft (RR _ (Reft (_, ras)))- = not $ null ras+isFunctionSortedReft :: SortedReft -> Bool+isFunctionSortedReft = isJust . functionSort . sr_sort -isFunctionSortedReft (RR (FFunc _ _) _)- = True-isFunctionSortedReft _- = False+functionSort :: Sort -> Maybe (Int, [Sort], Sort)+functionSort (FFunc n ts) = Just (n, its, t)+ where+ (its, t) = safeUnsnoc "functionSort" ts+functionSort _ = Nothing -sortedReftValueVariable (RR _ (Reft (v,_))) = v +++isNonTrivial :: Reftable r => r -> Bool+isNonTrivial = not .isTauto++-- sortedReftValueVariable (RR _ (Reft (v,_))) = v++reftPred :: Reft -> Pred+reftPred (Reft (_, Refa p)) = p++reftBind :: Reft -> Symbol+reftBind (Reft (x, _)) = x++refa :: [Pred] -> Refa+refa = Refa . pAnd++ --------------------------------------------------------------------------------- Environments -------------------------------+-- | Environments --------------------------------------------- --------------------------------------------------------------- + toListSEnv :: SEnv a -> [(Symbol, a)] toListSEnv (SE env) = M.toList env fromListSEnv :: [(Symbol, a)] -> SEnv a fromListSEnv = SE . M.fromList+ mapSEnv f (SE env) = SE (fmap f env) mapSEnvWithKey f = fromListSEnv . fmap f . toListSEnv deleteSEnv x (SE env) = SE (M.delete x env)@@ -719,20 +795,21 @@ filterSEnv f (SE m) = SE (M.filter f m) lookupSEnvWithDistance x (SE env) = case M.lookup x env of- Just x -> Found x+ Just z -> Found z Nothing -> Alts $ symbol . T.pack <$> alts- where alts = takeMin $ (zip (editDistance x' <$> ss) ss)- ss = T.unpack . symbolText <$> fst <$> M.toList env- x' = T.unpack $ symbolText x- takeMin = \xs -> [x | (d, x) <- xs, d == getMin xs]- getMin = minimum . (fst <$>)+ where+ alts = takeMin $ zip (editDistance x' <$> ss) ss+ ss = T.unpack . symbolText <$> fst <$> M.toList env+ x' = T.unpack $ symbolText x+ takeMin xs = [z | (d, z) <- xs, d == getMin xs]+ getMin = minimum . (fst <$>) data SESearch a = Found a | Alts [Symbol] -- | Functions for Indexed Bind Environment emptyIBindEnv :: IBindEnv-emptyIBindEnv = FB (S.empty)+emptyIBindEnv = FB S.empty deleteIBindEnv :: BindId -> IBindEnv -> IBindEnv deleteIBindEnv i (FB s) = FB (S.delete i s)@@ -740,6 +817,10 @@ insertsIBindEnv :: [BindId] -> IBindEnv -> IBindEnv insertsIBindEnv is (FB s) = FB (foldr S.insert s is) +elemsIBindEnv :: IBindEnv -> [BindId]+elemsIBindEnv (FB s) = S.toList s++ -- | Functions for Global Binder Environment insertBindEnv :: Symbol -> SortedReft -> BindEnv -> (BindId, BindEnv) insertBindEnv x r (BE n m) = (n, BE (n + 1) (M.insert n (x, r) m))@@ -747,49 +828,59 @@ emptyBindEnv :: BindEnv emptyBindEnv = BE 0 M.empty -rawBindEnv :: [(BindId, Symbol, SortedReft)] -> BindEnv-rawBindEnv bs = BE (1 + nbs) be'+bindEnvFromList :: [(BindId, Symbol, SortedReft)] -> BindEnv+bindEnvFromList bs = BE (1 + nbs) be' where- nbs = length bs- be = M.fromList [(n, (x, r)) | (n, x, r) <- bs]- be' = assert (M.size be == nbs) be+ nbs = length bs+ be = M.fromList [(n, (x, r)) | (n, x, r) <- bs]+ be' = assert (M.size be == nbs) be +bindEnvToList :: BindEnv -> [(BindId, Symbol, SortedReft)]+bindEnvToList (BE _ be) = [(n, x, r) | (n, (x, r)) <- M.toList be]+ mapBindEnv :: ((Symbol, SortedReft) -> (Symbol, SortedReft)) -> BindEnv -> BindEnv-mapBindEnv f (BE n m) = (BE n $ M.map f m)+mapBindEnv f (BE n m) = BE n $ M.map f m +lookupBindEnv :: BindId -> BindEnv -> (Symbol, SortedReft)+lookupBindEnv k (BE _ m) = fromMaybe err (M.lookup k m)+ where+ err = errorstar $ "lookupBindEnv: cannot find binder" ++ show k +unionIBindEnv :: IBindEnv -> IBindEnv -> IBindEnv+unionIBindEnv (FB m1) (FB m2) = FB $ m1 `S.union` m2+ instance Functor SEnv where- fmap f (SE m) = SE $ fmap f m+ fmap = mapSEnv instance Fixpoint Refa where- toFix (RConc p) = toFix p- toFix (RKvar k su) = toFix k <> toFix su+ toFix (Refa p) = toFix $ conjuncts p -- toFix (RPvar p) = toFix p instance Fixpoint Reft where- toFix = ppr_reft_pred+ toFix = pprReftPred instance Fixpoint SortedReft where- toFix (RR so (Reft (v, ras)))+ toFix (RR so (Reft (v, ra))) = braces- $ (toFix v) <+> (text ":") <+> (toFix so) <+> (text "|") <+> toFix ras--instance Fixpoint FEnv where- toFix (SE m) = toFix (hashMapToAscList m)+ $ toFix v <+> text ":" <+> toFix so <+> text "|" <+> toFix ra instance Fixpoint BindEnv where- toFix (BE _ m) = vcat $ map toFix_bind $ hashMapToAscList m+ toFix (BE _ m) = vcat $ map toFixBind $ hashMapToAscList m -toFix_bind (i, (x, r)) = text "bind" <+> toFix i <+> toFix x <+> text ":" <+> toFix r+toFixBind (i, (x, r)) = text "bind" <+> toFix i <+> toFix x <+> text ":" <+> toFix r insertFEnv = insertSEnv . lower where lower s = case unconsSym s of Nothing -> s Just (c,s') -> consSym (toLower c) s' +-- instance (Fixpoint a) => Fixpoint (SEnv a) where+-- toFix (SE e) = vcat $ map pprxt $ hashMapToAscList e+-- where+-- pprxt (x,t) = toFix x <+> colon <> colon <+> toFix t+ instance (Fixpoint a) => Fixpoint (SEnv a) where- toFix (SE e) = vcat $ map pprxt $ hashMapToAscList e- where pprxt (x, t) = toFix x <+> colon <> colon <+> toFix t+ toFix (SE m) = toFix (hashMapToAscList m) instance Fixpoint (SEnv a) => Show (SEnv a) where show = render . toFix@@ -803,14 +894,18 @@ type BindId = Int type FEnv = SEnv SortedReft+type BindMap a = M.HashMap BindId a -- (Symbol, SortedReft) newtype IBindEnv = FB (S.HashSet BindId) deriving (Data, Typeable)-newtype SEnv a = SE { se_binds :: M.HashMap Symbol a } deriving (Eq, Data, Typeable, Generic, F.Foldable, Traversable)-data BindEnv = BE { be_size :: Int- , be_binds :: M.HashMap BindId (Symbol, SortedReft)- }+newtype SEnv a = SE { seBinds :: M.HashMap Symbol a }+ deriving (Eq, Data, Typeable, Generic, F.Foldable, Traversable) +data BindEnv = BE { beSize :: Int+ , beBinds :: BindMap (Symbol, SortedReft)+ }+ deriving (Show)+ data SubC a = SubC { senv :: !IBindEnv , sgrd :: !Pred , slhs :: !SortedReft@@ -828,13 +923,21 @@ } deriving (Generic) ++---------------------------------------------------------------------------+-- | The output of the Solver+---------------------------------------------------------------------------+type Result a = (FixResult (SubC a), M.HashMap KVar Pred)+---------------------------------------------------------------------------++ data FixResult a = Crash [a] String | Safe | Unsafe ![a] | UnknownError !String deriving (Show, Generic) -type FixSolution = M.HashMap Symbol Pred+type FixSolution = M.HashMap KVar Pred instance Eq a => Eq (FixResult a) where Crash xs _ == Crash ys _ = xs == ys@@ -861,27 +964,26 @@ instance (Ord a, Fixpoint a) => Fixpoint (FixResult (SubC a)) where toFix Safe = text "Safe" toFix (UnknownError d) = text $ "Unknown Error: " ++ d- toFix (Crash xs msg) = vcat $ [ text "Crash!" ] ++ ppr_sinfos "CRASH: " xs ++ [parens (text msg)]- toFix (Unsafe xs) = vcat $ text "Unsafe:" : ppr_sinfos "WARNING: " xs+ toFix (Crash xs msg) = vcat $ [ text "Crash!" ] ++ pprSinfos "CRASH: " xs ++ [parens (text msg)]+ toFix (Unsafe xs) = vcat $ text "Unsafe:" : pprSinfos "WARNING: " xs -ppr_sinfos :: (Ord a, Fixpoint a) => String -> [SubC a] -> [Doc]-ppr_sinfos msg = map ((text msg <>) . toFix) . sort . fmap sinfo+pprSinfos :: (Ord a, Fixpoint a) => String -> [SubC a] -> [Doc]+pprSinfos msg = map ((text msg <>) . toFix) . sort . fmap sinfo resultDoc :: (Ord a, Fixpoint a) => FixResult a -> Doc resultDoc Safe = text "Safe" resultDoc (UnknownError d) = text $ "Unknown Error: " ++ d-resultDoc (Crash xs msg) = vcat $ (text ("Crash!: " ++ msg)) : (((text "CRASH:" <+>) . toFix) <$> xs)-resultDoc (Unsafe xs) = vcat $ (text "Unsafe:") : (((text "WARNING:" <+>) . toFix) <$> xs)---+resultDoc (Crash xs msg) = vcat $ text ("Crash!: " ++ msg) : (((text "CRASH:" <+>) . toFix) <$> xs)+resultDoc (Unsafe xs) = vcat $ text "Unsafe:" : (((text "WARNING:" <+>) . toFix) <$> xs) colorResult (Safe) = Happy colorResult (Unsafe _) = Angry colorResult (_) = Sad +instance Show (WfC a) where+ show = showFix instance Show (SubC a) where show = showFix@@ -934,7 +1036,7 @@ | x `elem` xs = z | otherwise = subst1 z su -substfExcept :: (Symbol -> Expr) -> [Symbol] -> (Symbol -> Expr)+substfExcept :: (Symbol -> Expr) -> [Symbol] -> Symbol -> Expr substfExcept f xs y = if y `elem` xs then EVar y else f y substExcept :: Subst -> [Symbol] -> Subst@@ -942,7 +1044,7 @@ substExcept (Su xes) xs = Su $ filter (not . (`elem` xs) . fst) xes instance Subable Symbol where- substa f x = f x+ substa f = f substf f x = subSymbol (Just (f x)) x subst su x = subSymbol (Just $ appSubst su x) x -- subSymbol (M.lookup x s) x syms x = [x]@@ -981,7 +1083,8 @@ substf f (PIff p1 p2) = PIff (substf f p1) (substf f p2) substf f (PBexp e) = PBexp $ substf f e substf f (PAtom r e1 e2) = PAtom r (substf f e1) (substf f e2)- substf _ (PAll _ _) = errorstar $ "substf: FORALL"+ substf _ p@(PKVar _ _) = p+ substf _ (PAll _ _) = errorstar "substf: FORALL" substf _ p = p subst su (PAnd ps) = PAnd $ map (subst su) ps@@ -991,18 +1094,16 @@ subst su (PIff p1 p2) = PIff (subst su p1) (subst su p2) subst su (PBexp e) = PBexp $ subst su e subst su (PAtom r e1 e2) = PAtom r (subst su e1) (subst su e2)- subst _ (PAll _ _) = errorstar $ "subst: FORALL"+ subst su (PKVar k su') = PKVar k $ su' `catSubst` su+ subst _ (PAll _ _) = errorstar "subst: FORALL" subst _ p = p instance Subable Refa where- syms (RConc p) = syms p- syms (RKvar k (Su su')) = k : concatMap syms ({- M.elems -} su')- subst su (RConc p) = RConc $ subst su p- subst su (RKvar k su') = RKvar k $ su' `catSubst` su- -- subst _ (RPvar p) = RPvar p+ syms (Refa p) = syms p+ -- syms (RKvar k (Su su')) = k : concatMap syms ({- M.elems -} su')+ subst su (Refa p) = Refa $ subst su p substa f = substf (EVar . f)- substf f (RConc p) = RConc (substf f p)- substf _ ra@(RKvar _ _) = ra+ substf f (Refa p) = Refa (substf f p) instance (Subable a, Subable b) => Subable (a,b) where syms (x, y) = syms x ++ syms y@@ -1036,17 +1137,26 @@ substf f (RR so r) = RR so $ substf f r substa f (RR so r) = RR so $ substa f r -newtype Subst = Su [(Symbol, Expr)] deriving (Eq, Ord, Data, Typeable, Generic)+newtype Subst = Su [(Symbol, Expr)]+ deriving (Eq, Ord, Data, Typeable, Generic) +appSubst :: Subst -> Symbol -> Expr appSubst (Su s) x = fromMaybe (EVar x) (lookup x s)-emptySubst = Su [] -- M.empty +emptySubst :: Subst+emptySubst = Su [] -- M.empty +catSubst :: Subst -> Subst -> Subst catSubst = unsafeCatSubst-mkSubst = unsafeMkSubst -unsafeMkSubst = Su -- . M.fromList+mkSubst :: [(Symbol, Expr)] -> Subst+mkSubst = unsafeMkSubst +isEmptySubst :: Subst -> Bool+isEmptySubst (Su xes) = null xes++unsafeMkSubst = Su+ unsafeCatSubst (Su s1) θ2@(Su s2) = Su $ s1' ++ s2 where s1' = mapSnd (subst θ2) <$> s1@@ -1058,7 +1168,7 @@ unsafeCatSubstIgnoringDead (Su s1) (Su s2) = Su $ s1' ++ s2' where s1' = mapSnd (subst (Su s2')) <$> s1- s2' = filter (\(x,_) -> not (x `elem` (fst <$> s1))) s2+ s2' = filter (\(x,_) -> (x `notElem` (fst <$> s1))) s2 -- TODO: nano-js throws all sorts of issues, will look into this later... -- but also, the check is too conservative, because of degenerate substitutions,@@ -1097,32 +1207,36 @@ usymbolReft :: (Symbolic a) => a -> Reft usymbolReft = uexprReft . eVar -vv_ = vv Nothing+vv_ :: Symbol+vv_ = vv Nothing trueSortedReft :: Sort -> SortedReft trueSortedReft = (`RR` trueReft) -trueReft = Reft (vv_, [])-falseReft = Reft (vv_, [RConc PFalse])+trueReft = Reft (vv_, trueRefa)+falseReft = Reft (vv_, Refa PFalse) -trueRefa = RConc PTrue+trueRefa :: Refa+trueRefa = Refa PTrue flattenRefas :: [Refa] -> [Refa] flattenRefas = concatMap flatRa where- flatRa (RConc p) = RConc <$> flatP p+ flatRa (Refa p) = Refa <$> flatP p flatRa ra = [ra] flatP (PAnd ps) = concatMap flatP ps flatP p = [p] -squishRefas :: [Refa] -> [Refa]-squishRefas ras = (squish [p | RConc p <- ras]) : []+squishRefas :: [Refa] -> [Refa]+squishRefas ras = [squish (raPred <$> ras)] where- squish = RConc . pAnd . sortNub . filter (not . isTautoPred) . concatMap conjuncts+ squish = Refa . pAnd . sortNub . filter (not . isTautoPred) . concatMap conjuncts -conjuncts (PAnd ps) = concatMap conjuncts ps-conjuncts p | isTautoPred p = []- | otherwise = [p]+conjuncts (PAnd ps) = concatMap conjuncts ps+conjuncts p+ | isTautoPred p = []+ | otherwise = [p]+ ---------------------------------------------------------------- ---------------------- Strictness ------------------------------ ----------------------------------------------------------------@@ -1187,8 +1301,8 @@ rnf (_) = () instance NFData Refa where- rnf (RConc x) = rnf x- rnf (RKvar x1 x2) = rnf x1 `seq` rnf x2+ rnf (Refa x) = rnf x+ -- rnf (RKvar x1 x2) = rnf x1 `seq` rnf x2 -- rnf (RPvar _) = () -- rnf x instance NFData Reft where@@ -1216,32 +1330,76 @@ -------- Constraint Constructor Wrappers ---------------------------------- --------------------------------------------------------------------------- +wfC :: IBindEnv -> SortedReft -> Maybe Integer -> a -> WfC a wfC = WfC -subC γ p (RR t1 r1) (RR t2 (Reft (v2, ra2s))) x y z- = [subC' r2' | r2' <- [r2K, r2P], not $ isTauto r2']- where- subC' r2' = SubC γ p (RR t1 (shiftVV r1 vvCon)) (RR t2 (shiftVV r2' vvCon)) x y z- r2K = Reft (v2, [ra | ra@(RKvar _ _) <- ra2s])- r2P = Reft (v2, [ra | ra@(RConc _ ) <- ra2s])+-- subC :: IBindEnv -> Pred -> SortedReft -> SortedReft -> Maybe Integer -> Tag -> a -> [SubC a]+-- subC γ p (RR t1 r1) (RR t2 (Reft (v2, ra2s))) i y z+-- = error "TODO:subC" -- NEW [subC' r2' | r2' <- [r2P], not $ isTauto r2']+-- where+-- subC' r2' = SubC γ p (RR t1 (shiftVV r1 vv')) (RR t2 (shiftVV r2' vv')) i y z+-- r2P = Reft (v2, ra2s) -- ORIG [ra | ra@(Refa _ ) <- ra2s])+-- -- ORIG r2K = Reft (v2, [ra | ra@(RKvar _ _) <- ra2s])+-- vv' = mkVV i -lhsCs = sr_reft . slhs-rhsCs = sr_reft . srhs +-- ORIG subC γ p (RR t1 r1) (RR t2 (Reft (v2, ra2s))) x y z+-- ORIG = [subC' r2' | r2' <- [r2K, r2P], not $ isTauto r2']+-- ORIG where+-- ORIG subC' r2' = SubC γ p (RR t1 (shiftVV r1 vvCon)) (RR t2 (shiftVV r2' vvCon)) x y z+-- ORIG r2K = Reft (v2, [ra | ra@(RKvar _ _) <- ra2s])+-- ORIG r2P = Reft (v2, [ra | ra@(RConc _ ) <- ra2s])+++subC :: IBindEnv -> Pred -> SortedReft -> SortedReft -> Maybe Integer -> Tag -> a -> [SubC a]+-- subC γ p (RR t1 r1) (RR t2 r2) i y z+subC γ p sr1 sr2 i y z = [SubC γ p sr1' (sr2' r2') i y z | r2' <- reftConjuncts r2]+ where+ RR t1 r1 = sr1+ RR t2 r2 = sr2+ sr1' = RR t1 $ shiftVV r1 vv'+ sr2' r2' = RR t2 $ shiftVV r2' vv'+ vv' = mkVV i++reftConjuncts :: Reft -> [Reft]+reftConjuncts (Reft (v, ra)) = [Reft (v, ra') | ra' <- refaConjuncts ra]++refaConjuncts :: Refa -> [Refa]+refaConjuncts (Refa p) = [Refa p' | p' <- conjuncts p, not $ isTautoPred p']++mkVV :: Maybe Integer -> Symbol+mkVV (Just i) = vv $ Just i+mkVV Nothing = vvCon++lhsCs, rhsCs :: SubC a -> Reft+lhsCs = sr_reft . slhs+rhsCs = sr_reft . srhs++envCs :: BindEnv -> IBindEnv -> [(Symbol, SortedReft)]+envCs be env = [lookupBindEnv i be | i <- elemsIBindEnv env]++-- mkFEnv :: BindEnv -> IBindEnv -> FEnv+-- mkFEnv be env = fromListSEnv $ envCs be env+++ removeLhsKvars cs vs- = cs{slhs = goRR (slhs cs)}- where goRR rr = rr{sr_reft = goReft (sr_reft rr)}- goReft (Reft(v, rs)) = Reft(v, filter f rs)- f (RKvar v _) | v `elem` vs = False- f r = True+ = error "TODO:cutsolver: removeLhsKvars (why is this function needed?)" -trueSubCKvar v- = subC emptyIBindEnv PTrue mempty (RR mempty (Reft(vv_, [RKvar v emptySubst]))) Nothing [0]+-- CUTSOLVER = cs {slhs = goRR (slhs cs)}+-- CUTSOLVER where goRR rr = rr{sr_reft = goReft (sr_reft rr)}+-- CUTSOLVER goReft (Reft(v, rs)) = Reft(v, filter f rs)+-- CUTSOLVER f (RKvar v _) | v `elem` vs = False+-- CUTSOLVER f r = True +trueSubCKvar k = subC emptyIBindEnv PTrue mempty rhs Nothing [0]+ where+ rhs = RR mempty (Reft (vv_, Refa $ PKVar k mempty))+ shiftVV :: Reft -> Symbol -> Reft shiftVV r@(Reft (v, ras)) v' | v == v' = r- | otherwise = Reft (v', (subst1 ras (v, EVar v')))+ | otherwise = Reft (v', subst1 ras (v, EVar v')) addIds = zipWith (\i c -> (i, shiftId i $ c {sid = Just i})) [1..]@@ -1252,28 +1410,6 @@ shiftR i r@(Reft (v, _)) = shiftVV r (v `mappend` symbol (show i)) --- subC γ p r1 r2 x y z = (vvsu, SubC γ p r1' r2' x y z)--- where (vvsu, r1', r2') = unifySRefts r1 r2---- unifySRefts (RR t1 r1) (RR t2 r2) = (z, RR t1 r1', RR t2 r2')--- where (r1', r2') = unifyRefts r1 r2---- unifyRefts r1@(Reft (v1, _)) r2@(Reft (v2, _))--- | v1 == v2 = (r1, r2)--- | otherwise = (r1, shiftVV r2 v1)---- unifySRefts (RR t1 r1) (RR t2 r2) = (z, RR t1 r1', RR t2 r2')--- where (z, r1', r2') = unifyRefts r1 r2------ unifyRefts r1@(Reft (v1, _)) r2@(Reft (v2, _))--- | v1 == v2 = ((v1, emptySubst), r1, r2)--- | v1 /= vv_ = let (su, r2') = shiftVV r2 v1 in ((v1, su), r1 , r2')--- | otherwise = let (su, r1') = shiftVV r1 v2 in ((v2, su), r1', r2 )------ shiftVV (Reft (v, ras)) v' = (su, (Reft (v', subst su ras)))--- where su = mkSubst [(v, EVar v')]-- ------------------------------------------------------------------------ ----------------- Qualifiers ------------------------------------------- ------------------------------------------------------------------------@@ -1293,8 +1429,13 @@ rnf (Q x1 x2 x3 _) = rnf x1 `seq` rnf x2 `seq` rnf x3 pprQual (Q n xts p l) = text "qualif" <+> text (symbolString n) <> parens args <> colon <+> toFix p <+> text "//" <+> toFix l- where args = intersperse comma (toFix <$> xts)+ where+ args = intersperse comma (toFix <$> xts) +------------------------------------------------------------------------+----------------- Top-Level Constraint System --------------------------+------------------------------------------------------------------------+ data FInfo a = FI { cm :: M.HashMap Integer (SubC a) , ws :: ![WfC a] , bs :: !BindEnv@@ -1303,37 +1444,41 @@ , kuts :: Kuts , quals :: ![Qualifier] }---- Original Ocaml definition------ type 'bind cfg = {--- a : int (* Tag arity *)--- ; ts : Ast.Sort.t list (* New sorts, now = [] *)--- ; ps : Ast.pred list (* New axioms, now = [] *)--- ; cs : FixConstraint.t list (* Implication Constraints *)--- ; ws : FixConstraint.wf list (* Well-formedness Constraints *)--- ; ds : FixConstraint.dep list (* Constraint Dependencies *)--- ; qs : Qualifier.t list (* Qualifiers *)--- ; kuts : Ast.Symbol.t list (* "Cut"-Kvars, which break cycles *)--- ; bm : 'bind Ast.Symbol.SMap.t (* Initial Sol Bindings *)--- ; uops : Ast.Sort.t Ast.Symbol.SMap.t (* Globals: measures + distinct consts) *)--- ; cons : Ast.Symbol.t list (* Distinct Constants, defined in uops *)--- ; assm : FixConstraint.soln (* Seed Solution: must be a fixpoint over constraints *)--- }+ deriving (Show) +instance Monoid Kuts where+ mempty = KS S.empty+ mappend k1 k2 = KS $ S.union (ksVars k1) (ksVars k2) --- toFixs = brackets . hsep . punctuate comma -- . map toFix+instance Monoid (SEnv a) where+ mempty = SE M.empty+ mappend s1 s2 = SE $ M.union (seBinds s1) (seBinds s2) -toFixpoint x' = kutsDoc x' $+$ gsDoc x' $+$ conDoc x' $+$ bindsDoc x' $+$ csDoc x' $+$ wsDoc x'- where conDoc = vcat . map toFix_constant . getLits- csDoc = vcat . map toFix . M.elems . cm- wsDoc = vcat . map toFix . ws- kutsDoc = toFix . kuts- bindsDoc = toFix . bs- gsDoc = toFix_gs . gs+instance Monoid BindEnv where+ mempty = BE 0 M.empty+ mappend (BE 0 _) b = b+ mappend b (BE 0 _) = b+ mappend _ _ = errorstar "mappend on non-trivial BindEnvs" -getLits x = lits x -- ++ symConstLits x+instance Monoid (FInfo a) where+ mempty = FI M.empty mempty mempty mempty mempty mempty mempty+ mappend i1 i2 = FI { cm = mappend (cm i1) (cm i2)+ , ws = mappend (ws i1) (ws i2)+ , bs = mappend (bs i1) (bs i2)+ , gs = mappend (gs i1) (gs i2)+ , lits = mappend (lits i1) (lits i2)+ , kuts = mappend (kuts i1) (kuts i2)+ , quals = mappend (quals i1) (quals i2)+ } +toFixpoint x' = kutsDoc x' $+$ gsDoc x' $+$ conDoc x' $+$ bindsDoc x' $+$ csDoc x' $+$ wsDoc x'+ where+ conDoc = vcat . map toFixConstant . lits+ csDoc = vcat . map toFix . M.elems . cm+ wsDoc = vcat . map toFix . ws+ kutsDoc = toFix . kuts+ bindsDoc = toFix . bs+ gsDoc = toFixGs . gs ------------------------------------------------------------------------- -- | A Class Predicates for Valid Refinements Types ---------------------@@ -1358,15 +1503,20 @@ instance Monoid Pred where mempty = PTrue mappend p q = pAnd [p, q]+ mconcat = pAnd +instance Monoid Refa where+ mempty = Refa mempty+ mappend ra1 ra2 = Refa $ mappend (raPred ra1) (raPred ra2)+ instance Monoid Reft where mempty = trueReft mappend = meetReft -meetReft r@(Reft (v, ras)) r'@(Reft (v', ras'))- | v == v' = Reft (v , ras ++ ras')- | v == dummySymbol = Reft (v', ras' ++ (ras `subst1` (v , EVar v')))- | otherwise = Reft (v , ras ++ (ras' `subst1` (v', EVar v )))+meetReft (Reft (v, ra)) (Reft (v', ra'))+ | v == v' = Reft (v , ra `mappend` ra')+ | v == dummySymbol = Reft (v', ra' `mappend` (ra `subst1` (v , EVar v')))+ | otherwise = Reft (v , ra `mappend` (ra' `subst1` (v', EVar v ))) instance Subable () where syms _ = []@@ -1384,15 +1534,22 @@ ofReft _ = mempty params _ = [] +-- NUKE isTautoReft :: Reft -> Bool+-- NUKE isTautoReft (Reft (_, ra)) = isTautoRa ra+-- NUKE+-- NUKE isTautoRa :: Refa -> Bool+-- NUKE isTautoRa = isTautoPred . raPred++ instance Reftable Reft where- isTauto = isTautoReft- ppTy = ppr_reft+ isTauto = all isTautoPred . conjuncts . reftPred+ ppTy = pprReft toReft = id ofReft = id params _ = [] bot _ = falseReft- top (Reft(v,_)) = Reft(v,[])+ top (Reft(v,_)) = Reft (v, mempty) instance Monoid Sort where mempty = FObj "any"@@ -1422,11 +1579,10 @@ isFalse _ = False instance Falseable Refa where- isFalse (RConc p) = isFalse p- isFalse _ = False+ isFalse (Refa p) = isFalse p instance Falseable Reft where- isFalse (Reft(_, rs)) = or [isFalse p | RConc p <- rs]+ isFalse (Reft(_, (Refa p))) = isFalse p --------------------------------------------------------------- -- | String Constants -----------------------------------------@@ -1439,6 +1595,9 @@ -- Used to transform parsed output from fixpoint back into fq. +instance Symbolic SymConst where+ symbol = encodeSymConst+ encodeSymConst :: SymConst -> Symbol encodeSymConst (SL s) = symbol $ litPrefix `mappend` s @@ -1452,8 +1611,7 @@ litPrefix = "lit" `T.snoc` symSepName strSort :: Sort-strSort = FApp strFTyCon []-+strSort = FInt class SymConsts a where symConsts :: a -> [SymConst]@@ -1462,8 +1620,8 @@ symConsts fi = sortNub $ csLits ++ bsLits ++ gsLits ++ qsLits where csLits = concatMap symConsts $ M.elems $ cm fi- bsLits = concatMap symConsts $ map snd $ M.elems $ be_binds $ bs fi- gsLits = concatMap symConsts $ M.elems $ se_binds $ gs fi+ bsLits = concatMap symConsts $ map snd $ M.elems $ beBinds $ bs fi+ gsLits = concatMap symConsts $ M.elems $ seBinds $ gs fi qsLits = concatMap symConsts $ q_body <$> quals fi instance SymConsts (SubC a) where@@ -1475,11 +1633,10 @@ symConsts = symConsts . sr_reft instance SymConsts Reft where- symConsts (Reft (_, ras)) = concatMap symConsts ras+ symConsts (Reft (_, ra)) = symConsts ra instance SymConsts Refa where- symConsts (RConc p) = symConsts p- symConsts (RKvar _ (Su xes)) = concatMap symConsts $ snd <$> xes+ symConsts (Refa p) = symConsts p instance SymConsts Expr where symConsts (ESym c) = [c]@@ -1491,15 +1648,16 @@ symConsts _ = [] instance SymConsts Pred where- symConsts (PNot p) = symConsts p- symConsts (PAnd ps) = concatMap symConsts ps- symConsts (POr ps) = concatMap symConsts ps- symConsts (PImp p q) = concatMap symConsts [p, q]- symConsts (PIff p q) = concatMap symConsts [p, q]- symConsts (PAll _ p) = symConsts p- symConsts (PBexp e) = symConsts e- symConsts (PAtom _ e e') = concatMap symConsts [e, e']- symConsts _ = []+ symConsts (PNot p) = symConsts p+ symConsts (PAnd ps) = concatMap symConsts ps+ symConsts (POr ps) = concatMap symConsts ps+ symConsts (PImp p q) = concatMap symConsts [p, q]+ symConsts (PIff p q) = concatMap symConsts [p, q]+ symConsts (PAll _ p) = symConsts p+ symConsts (PBexp e) = symConsts e+ symConsts (PAtom _ e e') = concatMap symConsts [e, e']+ symConsts (PKVar _ (Su xes)) = concatMap symConsts $ snd <$> xes+ symConsts _ = [] --------------------------------------------------------------- -- | Edit Distance --------------------------------------------@@ -1527,8 +1685,9 @@ -- | Located Values --------------------------------------------------------- ----------------------------------------------------------------------------- -data Located a = Loc { loc :: !SourcePos- , val :: a+data Located a = Loc { loc :: !SourcePos -- ^ Start Position+ , locE :: !SourcePos -- ^ End Position+ , val :: a } deriving (Data, Typeable, Generic) instance (IsString a) => IsString (Located a) where@@ -1538,7 +1697,7 @@ type LocText = Located Text dummyLoc :: a -> Located a-dummyLoc = Loc (dummyPos "Fixpoint.Types.dummyLoc")+dummyLoc = Loc l l where l = dummyPos "Fixpoint.Types.dummyLoc" dummyPos :: String -> SourcePos dummyPos s = newPos s 0 0@@ -1559,32 +1718,32 @@ expr = expr . val instance Functor Located where- fmap f (Loc l x) = Loc l (f x)+ fmap f (Loc l l' x) = Loc l l' (f x) instance F.Foldable Located where- foldMap f (Loc _ x) = f x+ foldMap f (Loc _ _ x) = f x instance Traversable Located where- traverse f (Loc l x) = Loc l <$> f x+ traverse f (Loc l l' x) = Loc l l' <$> f x instance Show a => Show (Located a) where- show (Loc l x) = show x ++ " defined at " ++ show l+ show (Loc l l' x) = show x ++ " defined from: " ++ show l ++ " to: " ++ show l' instance Eq a => Eq (Located a) where- (Loc _ x) == (Loc _ y) = x == y+ (Loc _ _ x) == (Loc _ _ y) = x == y instance Ord a => Ord (Located a) where compare x y = compare (val x) (val y) instance Subable a => Subable (Located a) where- syms (Loc _ x) = syms x- substa f (Loc l x) = Loc l (substa f x)- substf f (Loc l x) = Loc l (substf f x)- subst su (Loc l x) = Loc l (subst su x)+ syms (Loc _ _ x) = syms x+ substa f (Loc l l' x) = Loc l l' (substa f x)+ substf f (Loc l l' x) = Loc l l' (substf f x)+ subst su (Loc l l' x) = Loc l l' (subst su x) instance Hashable a => Hashable (Located a) where hashWithSalt i = hashWithSalt i . val instance (NFData a) => NFData (Located a) where -- FIXME: no instance NFData SrcSpan- rnf (Loc l x) = rnf x+ rnf (Loc _ _ x) = rnf x
src/Language/Fixpoint/Visitor.hs view
@@ -13,20 +13,25 @@ -- * Accumulators , fold + -- * Clients+ , kvars+ , envKVars+ , mapKVars++ -- * Sorts+ , foldSort, mapSort ) where -import Control.Applicative (Applicative (), (<$>), (<*>))-import Control.Exception (throw)+import Control.Applicative (Applicative, (<$>), (<*>)) import Control.Monad.Trans.State (State, modify, runState) import Data.Monoid-import Data.Traversable (traverse)-import Language.Fixpoint.Misc (mapSnd)+import Data.Traversable (Traversable, traverse) import Language.Fixpoint.Types--+import qualified Data.HashSet as S+import qualified Data.List as L data Visitor acc ctx = Visitor {- -- | Context @ctx@ is built up in a "top-down" fashion but not across siblings+ -- | Context @ctx@ is built in a "top-down" fashion; not "across" siblings ctxExpr :: ctx -> Expr -> ctx , ctxPred :: ctx -> Pred -> ctx @@ -51,7 +56,6 @@ , accPred = \_ _ -> mempty } - ------------------------------------------------------------------------ fold :: (Visitable t, Monoid a) => Visitor a ctx -> ctx -> a -> t -> a@@ -67,6 +71,7 @@ accum :: (Monoid a) => a -> VisitM a () accum = modify . mappend +(<$$>) :: (Traversable t, Applicative f) => (a -> f b) -> t a -> f (t b) f <$$> x = traverse f x ------------------------------------------------------------------------------@@ -80,11 +85,10 @@ visit = visitPred instance Visitable Refa where- visit v c (RConc p) = RConc <$> visit v c p- visit _ _ r = return r+ visit v c (Refa p) = Refa <$> visit v c p instance Visitable Reft where- visit v c (Reft (vv, ras)) = (Reft . (vv,)) <$> visitMany v c ras+ visit v c (Reft (x, ra)) = (Reft . (x, )) <$> visit v c ra visitMany :: (Monoid a, Visitable t) => Visitor a ctx -> ctx -> [t] -> VisitM a [t] visitMany v c xs = visit v c <$$> xs@@ -92,15 +96,15 @@ visitExpr :: (Monoid a) => Visitor a ctx -> ctx -> Expr -> VisitM a Expr visitExpr v = vE where- vP = visitPred v- vE c e = accum acc >> step c' e' where c' = ctxExpr v c e- e' = txExpr v c' e- acc = accExpr v c' e- step c e@EBot = return e- step c e@(ESym _) = return e- step c e@(ECon _) = return e- step c e@(ELit _ _) = return e- step c e@(EVar _) = return e+ vP = visitPred v+ vE c e = accum acc >> step c' e' where c' = ctxExpr v c e+ e' = txExpr v c' e+ acc = accExpr v c' e+ step _ e@EBot = return e+ step _ e@(ESym _) = return e+ step _ e@(ECon _) = return e+ step _ e@(ELit _ _) = return e+ step _ e@(EVar _) = return e step c (EApp f es) = EApp f <$> (vE c <$$> es) step c (ENeg e) = ENeg <$> vE c e step c (EBin o e1 e2) = EBin o <$> vE c e1 <*> vE c e2@@ -110,10 +114,12 @@ visitPred :: (Monoid a) => Visitor a ctx -> ctx -> Pred -> VisitM a Pred visitPred v = vP where- vE = visitExpr v- vP c p = accum acc >> step c' p' where c' = ctxPred v c p- p' = txPred v c' p- acc = accPred v c' p+ -- vS1 c (x, e) = (x,) <$> vE c e+ -- vS c (Su xes) = Su <$> vS1 c <$$> xes+ vE = visitExpr v+ vP c p = accum acc >> step c' p' where c' = ctxPred v c p+ p' = txPred v c' p+ acc = accPred v c' p step c (PAnd ps) = PAnd <$> (vP c <$$> ps) step c (POr ps) = POr <$> (vP c <$$> ps) step c (PNot p) = PNot <$> vP c p@@ -122,6 +128,61 @@ step c (PBexp e) = PBexp <$> vE c e step c (PAtom r e1 e2) = PAtom r <$> vE c e1 <*> vE c e2 step c (PAll xts p) = PAll xts <$> vP c p- step c p@PTrue = return p- step c p@PFalse = return p- step c p@PTop = return p+ step _ p@(PKVar _ _) = return p -- PAtom r <$> vE c e1 <*> vE c e2+ step _ p@PTrue = return p+ step _ p@PFalse = return p+ step _ p@PTop = return p+++---------------------------------------------------------------------------------+-- reftKVars :: Reft -> [KVar]+---------------------------------------------------------------------------------++-- reftKVars (Reft (_, ra)) = predKVars $ raPred ra+-- predKVars :: Pred -> [Symbol]++mapKVars :: Visitable t => (KVar -> Maybe Pred) -> t -> t+mapKVars f = trans kvVis () []+ where+ kvVis = defaultVisitor { txPred = txK }+ txK _ (PKVar k su)+ | Just p' <- f k = subst su p'+ txK _ p = p++kvars :: Visitable t => t -> [KVar]+kvars = fold kvVis () []+ where+ kvVis = defaultVisitor { accPred = kv }+ kv _ (PKVar k _) = [k]+ kv _ _ = []++envKVars :: BindEnv -> SubC a -> [KVar]+envKVars be c = squish [ kvs sr | (_, sr) <- envCs be (senv c)]+ where+ squish = S.toList . S.fromList . concat+ kvs = kvars . sr_reft++++---------------------------------------------------------------------------------+-- | Visitors over @Sort@+---------------------------------------------------------------------------------+foldSort :: (a -> Sort -> a) -> a -> Sort -> a+---------------------------------------------------------------------------------+foldSort f = step+ where+ step b t = go (f b t) t+ go b (FFunc _ ts) = L.foldl' step b ts+ go b (FApp _ ts) = L.foldl' step b ts+ go b _ = b+++---------------------------------------------------------------------------------+mapSort :: (Sort -> Sort) -> Sort -> Sort+---------------------------------------------------------------------------------+mapSort f = step+ where+ step = go . f+ go (FFunc n ts) = FFunc n $ step <$> ts+ go (FApp c ts) = FApp c $ step <$> ts+ go t = t
+ tests/test.hs view
@@ -0,0 +1,263 @@+{-# LANGUAGE OverloadedStrings #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}++module Main where++-- import Language.Fixpoint.Config+-- import Language.Fixpoint.Names+-- import Language.Fixpoint.Parse+-- import Language.Fixpoint.PrettyPrint+-- import Language.Fixpoint.Types++import Control.Applicative+-- import Data.Char+-- import Data.Tagged+-- import Data.Typeable+-- import Options.Applicative+import System.Directory+import System.Exit+import System.FilePath+import System.IO+-- import qualified System.Posix as Posix+import System.Process++-- import Control.Monad+-- import Data.Proxy+-- import Data.Text (Text, cons, inits, pack)+-- import Test.QuickCheck+import Test.Tasty+import Test.Tasty.HUnit+-- import Test.Tasty.Ingredients.Rerun+-- import Test.Tasty.Options+-- import Test.Tasty.QuickCheck+-- import Test.Tasty.Runners+import Text.Printf++main :: IO ()+main = defaultMain =<< tests+ where+ tests = group "Tests" [unitTests] -- [ quickCheckTests ]+ -- run = defaultMainWithIngredients [+ -- rerunningTests [ listingTests, consoleTestReporter ]+ -- , includingOptions [ Option (Proxy :: Proxy QuickCheckTests)+ -- ]+ -- ]+++unitTests+ = group "Unit" [+ testGroup "pos" <$> dirTests "tests/pos" [] ExitSuccess+ , testGroup "neg" <$> dirTests "tests/neg" [] (ExitFailure 1)+ ]++---------------------------------------------------------------------------+dirTests :: FilePath -> [FilePath] -> ExitCode -> IO [TestTree]+---------------------------------------------------------------------------+dirTests root ignored code+ = do files <- walkDirectory root+ let tests = [ rel | f <- files, isTest f, let rel = makeRelative root f, rel `notElem` ignored ]+ return $ mkTest code root <$> tests -- hs f code | f <- hs]++isTest :: FilePath -> Bool+isTest f = takeExtension f `elem` [".fq"]++---------------------------------------------------------------------------+mkTest :: ExitCode -> FilePath -> FilePath -> TestTree+---------------------------------------------------------------------------+mkTest code dir file+ = -- askOption $ \(smt :: SMTSolver) ->+ testCase file $+ if test `elem` knownToFail+ then do+ printf "%s is known to fail: SKIPPING" test+ assertEqual "" True True+ else do+ createDirectoryIfMissing True $ takeDirectory log+ bin <- canonicalizePath "dist/build/fixpoint/fixpoint"+ withFile log WriteMode $ \h -> do+ let cmd = testCmd bin dir file+ (_,_,_,ph) <- createProcess $ (shell cmd) {std_out = UseHandle h, std_err = UseHandle h}+ c <- waitForProcess ph+ assertEqual "Wrong exit code" code c+ where+ test = dir </> file+ log = let (d,f) = splitFileName file in dir </> d </> ".liquid" </> f <.> "log"++knownToFail = []++---------------------------------------------------------------------------+testCmd :: FilePath -> FilePath -> FilePath -> String+---------------------------------------------------------------------------+testCmd bin dir file = printf "cd %s && %s -n %s" dir bin file++++++++++++++++---------------------------------------------------------------------------+---------------------------------------------------------------------------+---------------------------------------------------------------------------+---------------------------------------------------------------------------+---------------------------------------------------------------------------+---------------------------------------------------------------------------+---------------------------------------------------------------------------++{-++quickCheckTests :: TestTree+quickCheckTests+ = testGroup "Properties"+ [ testProperty "prop_pprint_parse_inv_expr" prop_pprint_parse_inv_expr+ , testProperty "prop_pprint_parse_inv_pred" prop_pprint_parse_inv_pred+ ]++prop_pprint_parse_inv_pred :: Pred -> Bool+prop_pprint_parse_inv_pred p = p == rr (showpp p)++prop_pprint_parse_inv_expr :: Expr -> Bool+prop_pprint_parse_inv_expr p = simplify p == rr (showpp $ simplify p)++instance Arbitrary Sort where+ arbitrary = sized arbSort++arbSort 0 = oneof [return FInt, return FReal, return FNum]+arbSort n = frequency+ [(1, return FInt)+ ,(1, return FReal)+ ,(1, return FNum)+ ,(2, fmap FObj arbitrary)+ ]+++instance Arbitrary Pred where+ arbitrary = sized arbPred+ shrink = filter valid . genericShrink+ where+ valid (PAnd []) = False+ valid (PAnd [_]) = False+ valid (POr []) = False+ valid (POr [_]) = False+ valid (PBexp (EBin _ _ _)) = True+ valid (PBexp _) = False+ valid _ = True++arbPred 0 = elements [PTrue, PFalse]+arbPred n = frequency+ [(1, return PTrue)+ ,(1, return PFalse)+ ,(2, fmap PAnd twoPreds)+ ,(2, fmap POr twoPreds)+ ,(2, fmap PNot (arbPred (n `div` 2)))+ ,(2, liftM2 PImp (arbPred (n `div` 2)) (arbPred (n `div` 2)))+ ,(2, liftM2 PIff (arbPred (n `div` 2)) (arbPred (n `div` 2)))+ ,(2, fmap PBexp (arbExpr (n `div` 2)))+ ,(2, liftM3 PAtom arbitrary (arbExpr (n `div` 2)) (arbExpr (n `div` 2)))+ -- ,liftM2 PAll arbitrary arbitrary+ -- ,return PTop+ ]+ where+ twoPreds = do+ x <- arbPred (n `div` 2)+ y <- arbPred (n `div` 2)+ return [x,y]++instance Arbitrary Expr where+ arbitrary = sized arbExpr+ shrink = filter valid . genericShrink+ where valid (EApp _ []) = False+ valid _ = True++arbExpr 0 = oneof [fmap ESym arbitrary, fmap ECon arbitrary, fmap EVar arbitrary, return EBot]+arbExpr n = frequency+ [(1, fmap ESym arbitrary)+ ,(1, fmap ECon arbitrary)+ ,(1, fmap EVar arbitrary)+ ,(1, return EBot)+ -- ,liftM2 ELit arbitrary arbitrary -- restrict literals somehow+ ,(2, choose (1,3) >>= \m -> liftM2 EApp arbitrary (vectorOf m (arbExpr (n `div` 2))))+ ,(2, liftM3 EBin arbitrary (arbExpr (n `div` 2)) (arbExpr (n `div` 2)))+ ,(2, liftM3 EIte (arbPred (max 2 (n `div` 2)) `suchThat` isRel)+ (arbExpr (n `div` 2))+ (arbExpr (n `div` 2)))+ ,(2, liftM2 ECst (arbExpr (n `div` 2)) (arbSort (n `div` 2)))+ ]+ where+ isRel (PAtom _ _ _) = True+ isRel _ = False++instance Arbitrary Brel where+ arbitrary = oneof (map return [Eq, Ne, Gt, Ge, Lt, Le, Ueq, Une])++instance Arbitrary Bop where+ arbitrary = oneof (map return [Plus, Minus, Times, Div, Mod])++instance Arbitrary SymConst where+ arbitrary = fmap SL arbitrary++instance Arbitrary Symbol where+ arbitrary = fmap (symbol :: Text -> Symbol) arbitrary++instance Arbitrary Text where+ arbitrary = choose (1,4) >>= \n ->+ fmap pack (vectorOf n char `suchThat` valid)+ where+ char = elements ['a'..'z']+ valid x = x `notElem` fixpointNames && not (isFixKey x)++instance Arbitrary FTycon where+ arbitrary = do+ c <- elements ['A'..'Z']+ t <- arbitrary+ return $ symbolFTycon $ dummyLoc $ symbol $ cons c t++instance Arbitrary Constant where+ arbitrary = oneof [fmap I (arbitrary `suchThat` (>=0))+ -- ,fmap R arbitrary+ ]+ shrink = genericShrink++instance Arbitrary a => Arbitrary (Located a) where+ arbitrary = fmap dummyLoc arbitrary+ shrink = fmap dummyLoc . shrink . val++-}++----------------------------------------------------------------------------------------+-- Generic Helpers+----------------------------------------------------------------------------------------++group n xs = testGroup n <$> sequence xs++----------------------------------------------------------------------------------------+walkDirectory :: FilePath -> IO [FilePath]+----------------------------------------------------------------------------------------+walkDirectory root+ = do (ds,fs) <- partitionM doesDirectoryExist . candidates =<< getDirectoryContents root+ (fs++) <$> concatMapM walkDirectory ds+ where+ candidates fs = [root </> f | f <- fs, not (isExtSeparator (head f))]++partitionM :: Monad m => (a -> m Bool) -> [a] -> m ([a],[a])+partitionM f = go [] []+ where+ go ls rs [] = return (ls,rs)+ go ls rs (x:xs) = do b <- f x+ if b then go (x:ls) rs xs+ else go ls (x:rs) xs++-- isDirectory :: FilePath -> IO Bool+-- isDirectory = fmap Posix.isDirectory . Posix.getFileStatus++concatMapM :: Applicative m => (a -> m [b]) -> [a] -> m [b]+concatMapM _ [] = pure []+concatMapM f (x:xs) = (++) <$> f x <*> concatMapM f xs