module IRTS.Exports(findExports, getExpNames) where
import Idris.AbsSyntax
import Idris.Core.TT
import Idris.Core.CaseTree
import Idris.Core.Evaluate
import Idris.Error
import IRTS.Lang
import Data.Maybe
findExports :: Idris [ExportIFace]
findExports = do exps <- getExports
es <- mapM toIFace exps
logCodeGen 2 $ "Exporting " ++ show es
return es
getExpNames :: [ExportIFace] -> [Name]
getExpNames = concatMap expNames
expNames :: ExportIFace -> [Name]
expNames (Export _ _ es) = mapMaybe fnames es
where fnames (ExportData _) = Nothing
fnames (ExportFun n _ _ _) = Just n
toIFace :: Name -> Idris ExportIFace
toIFace n = do i <- getIState
let ctxt = tt_ctxt i
def <- case lookupDefExact n ctxt of
Just (CaseOp _ _ _ _ _ cs)
-> getExpList (snd (cases_compiletime cs))
Nothing -> ifail "Can't happen [toIFace]"
case lookupTyExact n ctxt of
Just ty -> toIFaceTyVal ty def
Nothing -> ifail "Can't happen [toIFace]"
where
getExpList (STerm t) = return t
getExpList _ = ifail "Badly formed export list"
toIFaceTyVal :: Type -> Term -> Idris ExportIFace
toIFaceTyVal ty tm
| (P _ exp _, [P _ ffi _, Constant (Str hdr), _]) <- unApply ty
= do tm' <- toIFaceVal tm
return $ Export ffi hdr tm'
toIFaceVal :: Term -> Idris [Export]
toIFaceVal tm
| (P _ end _, _) <- unApply tm,
end == sNS (sUN "End") ["FFI_Export"] = return []
| (P _ fun _, [_,_,_,_,(P _ fn _),extnm,prf,rest]) <- unApply tm,
fun == sNS (sUN "Fun") ["FFI_Export"]
= do rest' <- toIFaceVal rest
return $
ExportFun fn (toFDesc extnm) (toFDescRet prf) (toFDescArgs prf)
: rest'
| (P _ dat _, [_,_,_,_,d,rest]) <- unApply tm,
dat == sNS (sUN "Data") ["FFI_Export"]
= do rest' <- toIFaceVal rest
return $ ExportData (toFDesc d) : rest'
| otherwise = ifail $ "Badly formed export list " ++ show tm
toFDesc :: Term -> FDesc
toFDesc (Constant (Str str)) = FStr str
toFDesc tm
| (P _ n _, []) <- unApply tm = FCon (deNS n)
| (P _ n _, as) <- unApply tm = FApp (deNS n) (map toFDesc as)
toFDesc _ = FUnknown
toFDescRet :: Term -> FDesc
toFDescRet tm
| (P _ ret _, [_,_,_,b]) <- unApply tm,
ret == sNS (sUN "FFI_Ret") ["FFI_Export"]
= toFDescBase b
| (P _ io _, [_,_,_,b]) <- unApply tm,
io == sNS (sUN "FFI_IO") ["FFI_Export"]
= FIO $ toFDescBase b
| (P _ fun _, [_,_,_,_,_,t]) <- unApply tm,
fun == sNS (sUN "FFI_Fun") ["FFI_Export"]
= toFDescRet t
| otherwise = error "Badly formed export proof"
toFDescBase :: Term -> FDesc
toFDescBase tm
| (P _ prim _, [_, _, _, pdesc]) <- unApply tm,
prim == sNS (sUN "FFI_Prim") ["FFI_Export"]
= toFDescPrim pdesc
| (P _ prim _, [_, _, _, ddesc, _]) <- unApply tm,
prim == sNS (sUN "FFI_ExpType") ["FFI_Export"]
= toFDescPrim ddesc
| otherwise = error "Badly formed export type"
toFDescArgs :: Term -> [FDesc]
toFDescArgs tm
| (P _ fun _, [_,_,_,_,b,t]) <- unApply tm,
fun == sNS (sUN "FFI_Fun") ["FFI_Export"]
= toFDescBase b : toFDescArgs t
| otherwise = []
toFDescPrim (Constant (Str str)) = FStr str
toFDescPrim tm
| (P _ n _, []) <- unApply tm = FCon (deNS n)
| (P _ n _, as) <- unApply tm = FApp (deNS n) (map toFDescPrim as)
toFDescPrim _ = FUnknown
deNS (NS n _) = n
deNS n = n