module Derive.XML (deriveXML) where import List import Syntax import MkSyntax(mkInt) import IntState import IdKind import NT import State import Derive.Lib import TokenId(TokenId,tTrue,t_Tuple,t_Colon,t_List ,tShowXml,t_toHType,t_showsElem ,t_stagparen,t_showConstr,t_compose,t_Defined,t_Constr ,dropM) import Nice(showsOp,showsVar) deriveXML tidFun cls typ tvs ctxs pos = getUnique >>>= \d -> let expD = ExpVar pos d iToHType = tidFun (t_toHType,Method) iShowsElem = tidFun (t_showsElem,Method) expToHType = ExpVar pos iToHType expShowsElem = ExpVar pos iShowsElem expTrue = ExpCon pos (tidFun (tTrue,Con)) expPair = ExpCon pos (tidFun (t_Tuple 2,Con)) expCons = ExpCon pos (tidFun (t_Colon,Con)) expNil = ExpCon pos (tidFun (t_List,Con)) expDefined= ExpCon pos (tidFun (t_Defined,Con)) expConstr = ExpCon pos (tidFun (t_Constr,Con)) expDot = ExpVar pos (tidFun (t_compose,Var)) expId = ExpVar pos (tidFun (t_id,Var)) expStagparen = ExpVar pos (tidFun (t_stagparen,Var)) expShowConstr = ExpVar pos (tidFun (t_showConstr,Var)) in getInfo typ >>>= \ typInfo -> mapS getInfo (constrsI typInfo) >>>= \ constrInfos -> let sizeC = ((ceiling . logBase 2 . fromIntegral . length) constrInfos)::Int in addInstMethod tShowXml (tidI typInfo) t_toHType (NewType tvs [] ctxs [mkNTcons typ (map mkNTvar tvs)]) iToHType >>>= \ funH -> addInstMethod tShowXml (tidI typInfo) t_showsElem (NewType tvs [] ctxs [mkNTcons typ (map mkNTvar tvs)]) iShowsElem >>>= \ funS -> mapS (mkShowsFun expTrue expShowsElem expToHType expStagparen expShowConstr expDot expId pos) (zip [0..] constrInfos) >>>= \ funSs -> mkHTypeFuns expTrue expToHType expDefined expConstr expCons expNil pos typInfo constrInfos >>>= \ funHs -> unitS $ DeclInstance pos (syntaxCtxs pos ctxs) cls [syntaxType pos typ tvs] $ DeclsParse [DeclFun pos funH funHs ,DeclFun pos funS funSs] mkShowsFun expTrue expShowsElem expToHType expStagparen expShowConstr expDot expId pos (numC,constrInfo) = getUnique >>>= \v -> let --conTid = dropM (tidI constrInfo) con = ExpCon pos (uniqueI constrInfo) expV = ExpVar pos v expTag = ExpApplication pos [expShowConstr, mkInt pos numC, ExpApplication pos [expToHType, expV]] expStag x = ExpApplication pos [expStagparen, expTag, x] in case ntI constrInfo of NewType _ _ _ [nt] -> -- This constructor has no arguments unitS (Fun [PatAs pos v con] [(expTrue,expStag expId)] (DeclsParse [])) NewType _ _ _ (_:nts) -> -- We want a list with one element for each arg mapS ( \ _ -> unitS (ExpVar pos) =>>> getUnique) nts >>>= \args -> let expShowsArg arg = ExpApplication pos [expShowsElem,arg] in unitS ( Fun [PatAs pos v (ExpApplication pos (con:args))] [(expTrue, expStag (foldr1 (\arg z-> ExpApplication pos [expDot,arg,z]) (map expShowsArg args)))] (DeclsParse [])) -- this code is modified from *showType*, not from *readsPrec*. mkHTypeFuns expTrue expToHType expDefined expConstr expCons expNil pos typInfo constrInfos = getUnique >>>= \ v -> let expV = ExpVar pos v expGetCon = ExpApplication pos [expGetBits, expBH, mkInt pos sizeC] in --mkListExp pos expCons expNil expGtGtEq expGet expBH expReturn constrInfos >>>= \listExp-> mkAltList pos expTrue (mkGetExp pos expGtGtEq expGet expBH expReturn) constrInfos >>>= \altList-> unitS [Fun [expBH] [(expTrue, ExpApplication pos [expGtGtEq, expGetCon, ExpLambda pos [expI] (ExpCase pos expI altList) ])] (DeclsParse [])] mkGetExp pos expGtGtEq expGet expBH expReturn expCon args constrInfo = foldr (\ arg z -> ExpApplication pos [expGtGtEq, (ExpApplication pos [expGet,expBH]), ExpLambda pos [arg] z]) (ExpApplication pos [expReturn, ExpApplication pos (expCon:args)]) args mkAltList pos expTrue mkExpFun constrInfos = mapS (\(n,constrInfo) -> let expCon = ExpCon pos (uniqueI constrInfo) expN = mkInt pos n in case ntI constrInfo of NewType _ _ _ (_:nts) -> mapS ( \ _ -> unitS (ExpVar pos) =>>> getUnique) nts >>>= \args -> unitS (Alt expN [(expTrue, mkExpFun expCon args constrInfo)] (DeclsParse [])) ) (zip [0..] constrInfos) -- this code is modified from *showType*, not from *readsPrec*. mkFGetFuns expTrue expGetBitsF expFGet expLtLt expPair expCons expNil sizeC pos typInfo constrInfos = getUnique >>>= \ bh -> getUnique >>>= \ p -> getUnique >>>= \ p' -> getUnique >>>= \ n -> let expBH = ExpVar pos bh expP = ExpVar pos p expP' = ExpVar pos p' expN = ExpVar pos n expInit = ExpApplication pos [expGetBitsF, expBH, mkInt pos sizeC, expP] expFGetBH = ExpApplication pos [expFGet, expBH] in mkAltList pos expTrue (mkGetFExp pos expLtLt expFGetBH expPair expP') constrInfos >>>= \altList-> unitS [Fun [expBH,expP] [(expTrue, ExpLet pos (DeclsParse [DeclPat (Alt (ExpApplication pos [expPair,expN,expP']) [(expTrue,expInit)] (DeclsParse []))]) (ExpCase pos expN altList) )] (DeclsParse [])] mkGetFExp pos expLtLt expFGetBH expPair expP' expCon args constrInfo = foldl (\ acc arg -> ExpApplication pos [expLtLt, acc, expFGetBH]) (ExpApplication pos [expPair,expCon,expP']) args mkSizeFun sizeC expTrue expSize expPlus pos constrInfo = let con = ExpCon pos (uniqueI constrInfo) expCsize = mkInt pos sizeC expSizeOf arg = ExpApplication pos [expSize,arg] in case ntI constrInfo of NewType _ _ _ (_:nts) -> mapS ( \_ -> unitS (ExpVar pos) =>>> getUnique) nts >>>= \args -> unitS ( Fun [ExpApplication pos (con:args)] [(expTrue, foldl (\z arg-> ExpApplication pos [expPlus,expSizeOf arg,z]) expCsize args)] (DeclsParse []))