Raw File
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE LambdaCase #-}

module Language.Mist.Runner where

import System.IO
import Language.Mist.Types
import Language.Mist.Parser
import Language.Mist.Checker
import Language.Mist.CGen
import Language.Mist.ToFixpoint
import Language.Mist.Normalizer
import Language.Mist.Names
import qualified Language.Fixpoint.Horn.Types as HC
import qualified Language.Fixpoint.Types as F

import Text.Megaparsec.Pos (initialPos) -- NOTE: just for debugging

type R = HC.Pred

{-
  0) parse
  1) unique
  2) convert refinements from mist `Expr`s to fixpoint `Expr`s
  3) elaborate
  4) annotate each node with its type
  5) anf
  6) constraint generation
-}

---------------------------------------------------------------------------
runMist :: Handle -> FilePath -> IO (Result ())
---------------------------------------------------------------------------
runMist h f = act h f >>= \case
  r@Right{} -> hPutStrLn h "SAFE" >> return r
  Left es -> esHandle h (return . Left) es

act :: Handle -> FilePath -> IO (Result ())
act h f = do
  s <- readFile f
  (measures, e) <- parse f s
  let r = mist measures e
  case r of
    Right (measures', t) -> do
      -- !_ <- traceM $ pprint (anormal (annotate t TUnit))
      let c = generateConstraints (anormal (annotate t TUnit))
      solverResult <- solve measures' c
      hPrint h solverResult
      case F.resStatus solverResult of
        F.Safe -> return (Right ())
        _ -> return $ Left [mkError ("solver failed: " ++ show solverResult) (SS {ssBegin = initialPos f, ssEnd = initialPos f})] -- TODO: proper error
    Left l -> return (Left l)

esHandle :: Handle -> ([UserError] -> IO a) -> [UserError] -> IO a
esHandle h exitF es = renderErrors es >>= hPutStrLn h >> exitF es

-----------------------------------------------------------------------------------
mist :: Measures -> SSParsedExpr -> Result (Measures, ElaboratedExpr R SourceSpan)
-----------------------------------------------------------------------------------
mist measures expr =
  case wellFormed expr of
    [] -> do
      let (measures', uniqueExpr) = uniquify (measures, expr)
      let predExpr = parsedExprPredToFixpoint uniqueExpr
      result <- elaborate predExpr
      pure (measures', result)
    errors -> Left errors
back to top