module Derive.Bounded(deriveBounded) where import Syntax import IntState import IdKind import NT import State import Derive.Lib import TokenId(tminBound,tmaxBound,tBounded,tTrue) deriveBounded :: ((TokenId,IdKind) -> Id) -> Id -> Id -> [Id] -> [(Id,Id)] -> Pos -> a -> IntState -> (Decl Id,IntState) deriveBounded tidFun cls typ tvs ctxs pos = getInfo typ >>>= \ typInfo -> let expTrue = ExpCon pos (tidFun (tTrue,Con)) constrs = constrsI typInfo tidTyp = tidI typInfo nt = NewType tvs [] ctxs [mkNTcons typ (map mkNTvar tvs)] in getInfo (head constrs) >>>= \ minInfo -> getInfo (last constrs) >>>= \ maxInfo -> addInstMethod tBounded tidTyp tminBound nt (tidFun (tminBound,Method)) >>>= \ methodMinBound -> addInstMethod tBounded tidTyp tmaxBound nt (tidFun (tmaxBound,Method)) >>>= \ methodMaxBound -> unitS $ DeclInstance pos (syntaxCtxs pos ctxs) cls [syntaxType pos typ tvs] $ DeclsParse [mkBound expTrue pos minInfo methodMinBound (tidFun (tminBound,Var)) ,mkBound expTrue pos maxInfo methodMaxBound (tidFun (tmaxBound,Var)) ] mkBound :: a -> Pos -> Info -> Id -> Id -> Decl Id mkBound expTrue pos constrInfo methodBound funBound = case ntI constrInfo of NewType _ _ _ [nt] -> -- This constructor has no arguments DeclFun pos methodBound [Fun [] (Unguarded (ExpCon pos (uniqueI constrInfo))) (DeclsParse [])] NewType _ _ _ (_:nts) -> -- We only want a list with one element for each argument, the elements themselves are never used let args = (map fst . zip (repeat expBound)) nts expBound = ExpVar pos funBound in DeclFun pos methodBound [Fun [] (Unguarded (ExpApplication pos (ExpCon pos (uniqueI constrInfo):args))) (DeclsParse [])]