Subversion

Galculator

?curdirlinks? - Rev 7

?prevdifflink? - Blame



{-# OPTIONS_GHC -Wall #-}

-------------------------------------------------------------------------------
 
{- |
Module      :  Galculator.StepEval
Description :  
Copyright   :  (c) Paulo Silva
License     :  LGPL
 
Maintainer  :  paufil@di.uminho.pt
Stability   :  experimental
Portability :  portable
 
-}


-------------------------------------------------------------------------------

module Galculator.StepEval (
  stepEval
 ) where

import Control.GalcError
import Control.Monad.Error
import Control.Monad.Fresh
import Data.Existential
import Galculator.Evaluate
import Galculator.Rule
import Galculator.State
import Galculator.Proof
import Language.Law.Syntax
import Language.R.Equality
import Language.R.Match
import qualified Language.R.Refresh as RR
import Language.R.SafeCast
import Language.R.Syntax
import Language.R.SyntaxADT
import qualified Language.R.TypeInference as RI
import qualified Language.R.Verify as RV
import Language.Step.Syntax
import Language.Type.Constraint
import Language.Type.Syntax
import Language.Type.Unification

-------------------------------------------------------------------------------

eitherId :: Either a a -> a
eitherId = either id id

-------------------------------------------------------------------------------

eitherFunct :: (a -> c) -> (b -> d) -> Either a b -> Either c d
eitherFunct f g = either (Left . f) (Right . g)

-------------------------------------------------------------------------------

compileR :: S -> GalcStateT RType
compileR s = do
  env <- getEnvironment
  RI.infer =<< RR.refresh =<< RV.verify env s  

-------------------------------------------------------------------------------
stepEval :: Step -> GalcStateT ()
-------------------------------------------------------------------------------
stepEval (Comb comb) =
 inMode [ProofMode, IndirectProofMode] $ updateProof $ \prf -> do
  rl <- evalCombinator comb
  Exists t r <- getCurExpr
  return $ maybe prf
                 (\(expr, proof) ->
    prf {curExpr = eitherFunct (const (Exists t expr)) (const (Exists t expr)) (curExpr prf),
         curProof = addStep (RewriteStep (eitherId (curExpr prf)) proof) (curProof prf)}) (rewrite rl t r)
-------------------------------------------------------------------------------
stepEval (Indirect ord'') = inMode [ProofMode] $ (updateProof $ \prf -> do
  let cexpr = eitherId . curExpr $ prf
  ord' <- either compileR compileR ord''
  let ord = either (const (Left ord')) (const (Right ord')) ord''
  nexpr <- either (auxLeft cexpr)  (auxRight cexpr) ord
  return $ prf {
    curExpr = eitherFunct (const nexpr) (const nexpr) (curExpr prf),
    curProof = addStep (IndirectProof cexpr ord []) (curProof prf) } )
  >> enterIndirectProofMode
  where
    auxLeft :: RType -> RType -> GalcStateT RType
    auxLeft (Exists te e) (Exists to o) = do
      t1 <- getFreshLift (TVar . ('t':)); t2 <- getFreshLift (TVar . ('t':))
      constr <- unify [to :=: Ord t2, te :=: Fun t2 t1]
      Hide t1' <- typeRewrite constr t1
      Hide t2' <- typeRewrite constr t2
      o' <- rCast constr (Ord t2') o
      e' <- rCast constr (Fun t2' t1') e
      return $ Exists (Rel t2' t1') (COMP t2' (ORD o') (FUN e'))
    auxRight :: RType -> RType -> GalcStateT RType
    auxRight (Exists te e) (Exists to o) = do
      t1 <- getFreshLift (TVar . ('t':)); t2 <- getFreshLift (TVar . ('t':))
      constr <- unify [to :=: Ord t2, te :=: Fun t2 t1]
      Hide t1' <- typeRewrite constr t1
      Hide t2' <- typeRewrite constr t2
      o' <- rCast constr (Ord t2') o
      e' <- rCast constr (Fun t2' t1') e
      return $ Exists (Rel t1' t2') (COMP t2' (CONV (FUN e')) (ORD o'))
-------------------------------------------------------------------------------
stepEval IndirectEnd = inMode [IndirectProofMode] $ (updateProof $ \prf -> do
  let cexpr = eitherId . curExpr $ prf
  ord <- getOrd . curProof $ prf
  nexpr <- either (auxLeft cexpr) (auxRight cexpr) ord
  return $ prf {curExpr = eitherFunct (const nexpr) (const nexpr) (curExpr prf),
           curProof = addStep QED (curProof prf)}) >> enterProofMode
  where
    auxLeft :: RType -> RType -> GalcStateT RType
    auxLeft (Exists te e) (Exists to o) = do
      t1 <- getFreshLift (TVar . ('t':)); t2 <- getFreshLift (TVar . ('t':))
      constr <- unify [to :=: Ord t2, te :=: Rel t2 t1]
      Hide t1' <- typeRewrite constr t1
      Hide t2' <- typeRewrite constr t2
      o' <- rCast constr (Ord t2') o
      e' <- rCast constr (Rel t2' t1') e
      r <- getFreshLift (Var . ('r':))
      rConstr <- rMatch (COMP t2' (ORD o') (FUN r)) e'
      let r' = rSubst rConstr (Fun t2' t1') r
      return $ Exists (Fun t2' t1') r'
    auxRight :: RType -> RType -> GalcStateT RType
    auxRight (Exists te e) (Exists to o) = do
      t1 <- getFreshLift (TVar . ('t':)); t2 <- getFreshLift (TVar . ('t':))
      constr <- unify [to :=: Ord t2, te :=: Rel t1 t2]
      Hide t1' <- typeRewrite constr t1
      Hide t2' <- typeRewrite constr t2
      o' <- rCast constr (Ord t2') o
      e' <- rCast constr (Rel t1' t2') e
      r <- getFreshLift (Var . ('r':))
      rConstr <- rMatch (COMP t2' (CONV (FUN r)) (ORD o')) e'
      let r' = rSubst rConstr (Fun t2' t1') r
      return $ Exists (Fun t2' t1') r'
-------------------------------------------------------------------------------
stepEval LeftP = inMode [SetProofMode] $ (updateProof $ \prf ->
  return $ prf {curExpr = Left $ getLeft (expression prf)}) >> enterProofMode
-------------------------------------------------------------------------------
stepEval Qed = inMode [ProofMode] $ (updateProof $ \prf ->
     either (aux getRight prf) (aux getLeft prf) (curExpr prf)) >>
    enterFinalProofMode
  where
   aux f p expr =
     if req' expr (f (expression p))
     then return $ p {curProof = addStep QED (curProof p)}
     else throwError $ QedError (show expr) (show (f (expression p)))
   req' (Exists _ r) (Exists _ r') = req r r'
-------------------------------------------------------------------------------
stepEval RightP = inMode [SetProofMode] $ (updateProof $ \prf ->
  return $ prf {curExpr = Right $ getRight (expression prf)}) >> enterProofMode
-------------------------------------------------------------------------------
stepEval (SeqC s1 s2) =
  stepEval s1 >> stepEval s2
-------------------------------------------------------------------------------

Theme by Vikram Singh | Powered by WebSVN v2.3.3