module Derive.Ord(deriveOrd) where
import Syntax
import IntState
import IdKind
import NT
import State
import Derive.Lib
import TokenId(t_fromEnum,tTrue,tOrd,t_equalequal,t_lessthan,t_lessequal,tcompare,tLT,tEQ,tGT,t_andand,t_pipepipe)
deriveOrd :: ((TokenId,IdKind) -> Id)
-> Id -> Id -> [Id] -> [(Id,Id)] -> Pos -> a -> IntState -> (Decl Id,IntState)
deriveOrd tidFun cls typ tvs ctxs pos =
getUnique >>>= \x ->
getUnique >>>= \y ->
getUnique >>>= \z ->
getUnique >>>= \w ->
let expX = ExpVar pos x
expY = ExpVar pos y
expZ = ExpVar pos z
expW = ExpVar pos w
iLessEqual = tidFun (t_lessequal,Method)
expLessEqual = ExpVar pos iLessEqual
iCompare = tidFun (tcompare,Method)
expCompare = ExpVar pos iCompare
expTrue = ExpCon pos (tidFun (tTrue,Con))
exp_fromEnum = ExpVar pos (tidFun (t_fromEnum,Var))
in
getInfo typ >>>= \ typInfo ->
mapS getInfo (constrsI typInfo) >>>= \ constrInfos ->
addInstMethod tOrd (tidI typInfo) t_lessequal (NewType tvs [] ctxs [mkNTcons typ (map mkNTvar tvs)]) iLessEqual >>>= \ funle ->
addInstMethod tOrd (tidI typInfo) tcompare (NewType tvs [] ctxs [mkNTcons typ (map mkNTvar tvs)]) iCompare >>>= \ funcompare ->
if all noArgs constrInfos
then unitS $
DeclInstance pos (syntaxCtxs pos ctxs) cls [syntaxType pos typ tvs] $
DeclsParse [DeclFun pos funle
[Fun [expX,expY]
(Unguarded
(ExpApplication pos
[expLessEqual
,ExpApplication pos [exp_fromEnum,expX]
,ExpApplication pos [exp_fromEnum,expY]]))
(DeclsParse [])]
,DeclFun pos funcompare
[Fun [expZ,expW]
(Unguarded
(ExpApplication pos
[expCompare
,ExpApplication pos [exp_fromEnum,expZ]
,ExpApplication pos [exp_fromEnum,expW]]))
(DeclsParse [])]
]
else
let expLess = ExpVar pos (tidFun (t_lessthan,Method))
expEqual = ExpVar pos (tidFun (t_equalequal,Method))
expLT = ExpCon pos (tidFun (tLT,Con))
expEQ = ExpCon pos (tidFun (tEQ,Con))
expGT = ExpCon pos (tidFun (tGT,Con))
in mapS (mkOrdFunLe expTrue expLessEqual expLess expEqual tidFun pos)
constrInfos >>>= \ funles ->
mapS (mkOrdFunCompare expTrue expCompare expLT expEQ expGT tidFun pos)
constrInfos >>>= \ funcompares ->
unitS $
DeclInstance pos (syntaxCtxs pos ctxs) cls [syntaxType pos typ tvs] $
DeclsParse
[DeclFun pos funle (funles++
[Fun [expX,expY]
(Unguarded (ExpApplication pos
[expLessEqual
,ExpApplication pos [exp_fromEnum,expX]
,ExpApplication pos [exp_fromEnum,expY]]))
(DeclsParse [])])
,DeclFun pos funcompare (funcompares++
[Fun [expZ,expW]
(Unguarded (ExpApplication pos
[expCompare
,ExpApplication pos [exp_fromEnum,expZ]
,ExpApplication pos [exp_fromEnum,expW]]))
(DeclsParse [])])
]
mkOrdFunLe :: Exp Id -> Exp Id -> Exp Id -> Exp Id
-> ((TokenId,IdKind) -> Id) -> Pos -> Info -> a -> IntState -> (Fun Id,IntState)
mkOrdFunLe expTrue expLessEqual expLess expEqual tidFun pos constrInfo =
let con = ExpCon pos (uniqueI constrInfo)
in case ntI constrInfo of
NewType _ _ _ [nt] -> -- This constructor has no arguments
unitS (Fun [ExpApplication pos [con],ExpApplication pos [con]]
(Unguarded expTrue) (DeclsParse []))
NewType _ _ _ (_:nts) -> -- We only want a list with one element for each argument, the elements themselves are never used
mapS ( \ _ ->
getUnique >>>= \ x ->
getUnique >>>= \ y ->
unitS (ExpVar pos x,ExpVar pos y))
nts >>>= \ (v@(l,r):vars) ->
let (lvs,rvs) = unzip vars
expAnd = ExpVar pos (tidFun (t_andand,Var))
expOr = ExpVar pos (tidFun (t_pipepipe,Var))
in
unitS (
Fun [ExpApplication pos (con:lvs++[l])
,ExpApplication pos (con:rvs++[r])]
(Unguarded
(foldr ( \ (v,r) e ->
ExpApplication pos
[expOr
,ExpApplication pos [expLess,v,r]
,ExpApplication pos [expAnd
,ExpApplication pos [expEqual,v,r],e]])
(ExpApplication pos [expLessEqual,l,r])
vars))
(DeclsParse [])
)
mkOrdFunCompare :: a -> Exp Id -> Exp Id -> Exp Id -> Exp Id -> b
-> Pos -> Info -> c -> IntState -> (Fun Id,IntState)
mkOrdFunCompare expTrue expCompare expLT expEQ expGT tidFun pos constrInfo =
let con = ExpCon pos (uniqueI constrInfo)
in case ntI constrInfo of
NewType _ _ _ [nt] -> -- This constructor has no arguments
unitS (Fun [ExpApplication pos [con],ExpApplication pos [con]]
(Unguarded expEQ) (DeclsParse []))
NewType _ _ _ (_:nts) -> -- We only want a list with one element for each argument, the elements themselves are never used
mapS ( \ _ ->
getUnique >>>= \ x ->
getUnique >>>= \ y ->
unitS (ExpVar pos x,ExpVar pos y))
nts >>>= \ (v@(l,r):vars) ->
let (lvs,rvs) = unzip vars
in
unitS (
Fun [ExpApplication pos (con:lvs++[l])
,ExpApplication pos (con:rvs++[r])]
(Unguarded
(foldr ( \ (v,r) e ->
ExpCase pos (ExpApplication pos [expCompare,v,r])
[Alt expLT (Unguarded expLT) (DeclsParse [])
,Alt expEQ (Unguarded e) (DeclsParse [])
,Alt expGT (Unguarded expGT) (DeclsParse [])
])
(ExpApplication pos [expCompare,l,r])
vars))
(DeclsParse [])
)
|