module Derive.Eq(deriveEq) where import Syntax import IntState import IdKind import Id(Id) import NT import State import Derive.Lib import TokenId(t_fromEnum,tFalse,tTrue,tEq,t_equalequal,t_andand) deriveEq :: ((TokenId,IdKind) -> Id) -> Id -> Id -> [Id] -> [(Id,Id)] -> Pos -> a -> IntState -> (Decl Id,IntState) deriveEq tidFun cls typ tvs ctxs pos = getUnique >>>= \x -> getUnique >>>= \y -> let iEqual = tidFun (t_equalequal,Method) expTrue = ExpCon pos (tidFun (tTrue,Con)) expX = ExpVar pos x expY = ExpVar pos y in getInfo typ >>>= \ typInfo -> mapS getInfo (constrsI typInfo) >>>= \ constrInfos -> addInstMethod tEq (tidI typInfo) t_equalequal (NewType tvs [] ctxs [mkNTcons typ (map mkNTvar tvs)]) iEqual >>>= \ fun -> if all noArgs constrInfos then let exp_fromEnum = ExpVar pos (tidFun (t_fromEnum,Var)) expEqual = ExpVar pos iEqual in unitS $ DeclInstance pos (syntaxCtxs pos ctxs) cls [syntaxType pos typ tvs] $ DeclsParse [DeclFun pos fun [Fun [expX,expY] (Unguarded (ExpApplication pos [expEqual ,ExpApplication pos [exp_fromEnum,expX] ,ExpApplication pos [exp_fromEnum,expY]])) (DeclsParse [])]] else mapS (mkEqFun expTrue tidFun pos) constrInfos >>>= \ funs -> getUnique >>>= \x -> getUnique >>>= \y -> unitS $ DeclInstance pos (syntaxCtxs pos ctxs) cls [syntaxType pos typ tvs] $ DeclsParse [DeclFun pos fun (funs ++ [Fun [ExpVar pos x,ExpVar pos y] (Unguarded (ExpCon pos (tidFun (tFalse,Con)))) (DeclsParse [])])] mkEqFun :: Exp Id -> ((TokenId,IdKind) -> Id) -> Pos -> Info -> a -> IntState -> (Fun Id,IntState) mkEqFun expTrue 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 >>>= \ vars -> let (lvs,rvs) = unzip vars expEqual = ExpVar pos (tidFun (t_equalequal,Method)) expAnd = ExpVar pos (tidFun (t_andand,Var)) in unitS ( Fun [ExpApplication pos (con:lvs),ExpApplication pos (con:rvs)] (Unguarded (foldr1 ( \ l v -> ExpApplication pos [expAnd,l,v]) (map ( \ (v,r) -> ExpApplication pos [expEqual,v,r] ) vars))) (DeclsParse []) )