module DerivingOrd where
import Maybe(mapMaybe)
import DerivingUtils
deriveOrd stdnames src t@(_,TypeInfo{constructors=cs}) =
do let pv = stdvalue stdnames mod_Prelude
pt = stdtype stdnames mod_Prelude
HsVar compare <- pv "compare"
lexOrder <- pv "lexOrder" -- nonstandard entity!
int <- hsTyId # pt "Int"
let branches = mapMaybe eqbranch cs `asTypeOf` def
n = length cs
def = if n<2 && length branches==n
then []
else [alt x y cmpcno]
where
x = var (localVal "x")
y = var (localVal "y")
cmpcno = hsLet cnodef (compareE (cnoE x) (cnoE y))
cnodef = oneDef (fun src (zipWith cnoalt [0..] cs))
cno = localVal "cno"
cnoE a = var cno `app` a
cnoalt i ConInfo{conName=c0,conArity=n} =
alt1 src cno (hsPApp c xs) (l i)
where xs = replicate n wild
c = convCon t c0
l 0 = intlit 0 -:: int -- add type restriction to the first branch
l i = intlit i
intlit = hsLit src . HsInt
eqbranch ConInfo{conName=c0,conArity=n} =
if n==0
then Nothing
else Just (alt (p xs) (p ys) rhs)
where
c = convCon t c0
p = hsPApp c
rhs = conj comps
conj = foldr1 (opapp lexOrder)
comps = zipWith compareE xs ys
xs = take n (vars "x")
ys = take n (vars "y")
compareE = opapp (HsVar compare)
alt = alt2 src compare
return [fun src (branches++def)]