blob: ab0e7d404af4b6f81b432b741b4ccbae7afe3510 [file] [log] [blame] [edit]
-- |
-- Module : Minigent.TC.Solver
-- Copyright : (c) Data61 2018-2019
-- Commonwealth Science and Research Organisation (CSIRO)
-- ABN 41 687 119 230
-- License : BSD3
--
-- The solver portion of the type inference.
--
-- May be used qualified or unqualified.
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Minigent.TC.Solver
( Solver
, runSolver
, solve
, substAssign
) where
import Minigent.TC.Normalise
import Minigent.TC.Simplify
import Minigent.TC.Unify
import Minigent.TC.Equate
import Minigent.TC.SinkFloat
import Minigent.TC.Assign
import Minigent.Fresh
import Minigent.Syntax
import Minigent.Syntax.Utils
import Minigent.Syntax.PrettyPrint
import qualified Minigent.Syntax.Utils.Rewrite as Rewrite
import Control.Applicative
import Control.Monad.Trans.Maybe
import Control.Monad.State
import Control.Monad.Writer
import Data.Maybe (fromMaybe)
import Debug.Trace
-- | A monad that combines writer effects for accumulating assignments to
-- unification variables, and fresh variables.
newtype Solver a = Solver (WriterT [Assign] (FreshT VarName IO) a)
deriving ( Monad, Applicative, Functor
, MonadFresh VarName, MonadWriter [Assign]
)
-- | Given a set of axioms and a set of constraints to solve, attempt to
-- find assignments to satisfy all the constraints assuming the axioms.
--
-- Right now, only 'Share', 'Drop' and 'Escape' constraints on type
-- variables can be axioms.
--
-- Returns any constraints that could not be satisfied. So, an empty list
-- means that the solver successfully solved everything.
solve :: [Constraint] -> [Constraint] -> Solver [Constraint]
solve axs cs = do
cs'' <- runMaybeT (Rewrite.run' solverRewrites cs)
case cs'' of
Nothing -> pure (normaliseConstraints cs)
Just a -> pure a
where
solverRewrites :: Rewrite.Rewrite' Solver [Constraint]
solverRewrites = Rewrite.untilFixedPoint $
-- Rewrite.debugNewline "SOLV" debugPrettyConstraints <>
Rewrite.pre normaliseConstraints (
-- debugStr "[simp]" <>
Rewrite.lift (simplify axs) <>
-- debugStr "[unify]" <>
unify <>
-- debugStr "[equate]" <>
Rewrite.lift equate <>
-- debugStr "[sink/float]" <>
sinkFloat)
-- | Run a solver computation.
runSolver :: Solver a -> FreshT VarName IO (a,[Assign])
runSolver (Solver x) = runWriterT x
debugStr :: String -> Rewrite.Rewrite' Solver a
debugStr s = Rewrite.Rewrite $ \cs -> do
_ <- (lift . Solver . lift . lift . traceIO $ s :: MaybeT Solver ())
empty