solveConstraints :: (?globals :: Globals) => Pred -> Span -> Id -> Checker ()
solveConstraints predicate s name = do

  -- Get the coeffect kind context and constraints
  checkerState <- get
  let ctxtCk  = tyVarContext checkerState
  coeffectVars <- justCoeffectTypesConverted s ctxtCk
  -- remove any variables bound already in the preciate
  coeffectVars <- return (coeffectVars `deleteVars` boundVars predicate)

  debugM "tyVarContext" (pretty $ tyVarContext checkerState)
  debugM "context into the solver" (pretty $ coeffectVars)
  debugM "Solver predicate" $ pretty predicate

  result <- liftIO $ provePredicate predicate coeffectVars
  case result of
    QED -> return ()
    NotValid msg -> do
      msg' <- rewriteMessage msg
      simplPred <- simplifyPred predicate

      -- try trivial unsats again
      let unsats' = trivialUnsatisfiableConstraints simplPred
      if not (null unsats')
        then mapM_ (\c -> throw GradingError{ errLoc = getSpan c, errConstraint = Neg c }) unsats'
        else
          if msg' == "is Falsifiable\n"
            then throw SolverErrorFalsifiableTheorem
              { errLoc = s, errDefId = name, errPred = simplPred }
            else throw SolverErrorCounterExample
              { errLoc = s, errDefId = name, errPred = simplPred }
    NotValidTrivial unsats ->
       mapM_ (\c -> throw GradingError{ errLoc = getSpan c, errConstraint = Neg c }) unsats
    Timeout ->
        throw SolverTimeout{ errLoc = s, errSolverTimeoutMillis = solverTimeoutMillis, errDefId = name, errContext = "grading", errPred = predicate }
    OtherSolverError msg -> throw SolverError{ errLoc = s, errMsg = msg }
    SolverProofError msg -> error msg

-- Rewrite an error message coming from the solver
solveConstraints :: (?globals :: Globals) => Pred -> Span -> Id -> Checker ()
solveConstraints predicate s name = do

  -- Get the coeffect kind context and constraints
  checkerState <- get
  let ctxtCk  = tyVarContext checkerState
  coeffectVars <- justCoeffectTypesConverted s ctxtCk
  -- remove any variables bound already in the preciate
  coeffectVars <- return (coeffectVars `deleteVars` boundVars predicate)

  debugM "tyVarContext" (pretty $ tyVarContext checkerState)
  debugM "context into the solver" (pretty $ coeffectVars)
  debugM "Solver predicate" $ pretty predicate

  result <- liftIO $ provePredicate predicate coeffectVars
  case result of
    QED -> return ()
    NotValid msg -> do
      msg' <- rewriteMessage msg
      simplPred <- simplifyPred predicate

      -- try trivial unsats again
      let unsats' = trivialUnsatisfiableConstraints simplPred
      if not (null unsats')
        then mapM_ (\c -> throw GradingError{ errLoc = getSpan c, errConstraint = Neg c }) unsats'
        else
          if msg' == "is Falsifiable\n"
            then throw SolverErrorFalsifiableTheorem
              { errLoc = s, errDefId = name, errPred = simplPred }
            else throw SolverErrorCounterExample
              { errLoc = s, errDefId = name, errPred = simplPred }
    NotValidTrivial unsats ->
       mapM_ (\c -> throw GradingError{ errLoc = getSpan c, errConstraint = Neg c }) unsats
    Timeout ->
        throw SolverTimeout{ errLoc = s, errSolverTimeoutMillis = solverTimeoutMillis, errDefId = name, errContext = "grading", errPred = predicate }
    OtherSolverError msg -> throw SolverError{ errLoc = s, errMsg = msg }
    SolverProofError msg -> error msg

-- Rewrite an error message coming from the solver
solveConstraints predicate s name = do

  -- Get the coeffect kind context and constraints
  checkerState <- get
  let ctxtCk  = tyVarContext checkerState
  coeffectVars <- justCoeffectTypesConverted s ctxtCk
  -- remove any variables bound already in the preciate
  coeffectVars <- return (coeffectVars `deleteVars` boundVars predicate)

  debugM "tyVarContext" (pretty $ tyVarContext checkerState)
  debugM "context into the solver" (pretty $ coeffectVars)
  debugM "Solver predicate" $ pretty predicate

  result <- liftIO $ provePredicate predicate coeffectVars
  case result of
    QED -> return ()
    NotValid msg -> do
      msg' <- rewriteMessage msg
      simplPred <- simplifyPred predicate

      -- try trivial unsats again
      let unsats' = trivialUnsatisfiableConstraints simplPred
      if not (null unsats')
        then mapM_ (\c -> throw GradingError{ errLoc = getSpan c, errConstraint = Neg c }) unsats'
        else
          if msg' == "is Falsifiable\n"
            then throw SolverErrorFalsifiableTheorem
              { errLoc = s, errDefId = name, errPred = simplPred }
            else throw SolverErrorCounterExample
              { errLoc = s, errDefId = name, errPred = simplPred }
    NotValidTrivial unsats ->
       mapM_ (\c -> throw GradingError{ errLoc = getSpan c, errConstraint = Neg c }) unsats
    Timeout ->
        throw SolverTimeout{ errLoc = s, errSolverTimeoutMillis = solverTimeoutMillis, errDefId = name, errContext = "grading", errPred = predicate }
    OtherSolverError msg -> throw SolverError{ errLoc = s, errMsg = msg }
    SolverProofError msg -> error msg

-- Rewrite an error message coming from the solver