module Agda.Compiler.Alonzo.Main where import Language.Haskell.Syntax import Language.Haskell.Pretty import Agda.Compiler.Alonzo.Haskell import Agda.Compiler.Alonzo.Debug import Agda.Compiler.Alonzo.Names import qualified Agda.Syntax.Concrete.Name as C import Agda.Syntax.Internal import Agda.Syntax.Literal import Agda.Syntax.Scope import Text.PrettyPrint import Agda.Syntax.Common import Control.Monad.State import Control.Monad.Error import Data.List as List import Data.Map as Map import Agda.Syntax.Abstract.Test import Agda.Syntax.Abstract.Name import qualified Agda.Syntax.Concrete.Name as CN import Agda.Interaction.Options import Agda.Interaction.Monad import Agda.TypeChecker import Agda.TypeChecking.Monad import Agda.TypeChecking.Monad.Builtin import Agda.Utils.Monad import System.IO import Data.List(nub) -- import Agda.Version -- | The main function compilerMain :: IM () -> IM () compilerMain typeCheck = do typeCheck sig <- gets stSignature debugSigInfo sig let [moduleName] = keys sig builtinMap <- getBuiltinThings let sigs = toList sig let definitions = mdefDefs (snd (head sigs)) -- :: Map Name Definition let defs = toList definitions let names = List.map fst defs hsdefs <- mapM processDefWithDebug defs impNames <- getImports let imps = List.map show (List.nub impNames) let mainNum = (numOfMainS names) let fileBase = show moduleName let moduleString = fileBase let hsmod = hsModuleImporting moduleString imps (concat hsdefs) liftIO $ outputHsModule fileBase hsmod mainNum -- let almod = List.map AlDecl hsdefs -- liftIO $ printAlModule moduleString almod numOfMainS :: [Name] -> Maybe Int numOfMainS [] = Nothing numOfMainS (n:ns) | isMain n = Just $ numOfName n | otherwise = numOfMainS ns -- isMain (Name _ (C.Name _ [C.Id "mainS"])) = True isMain n = (show n == "mainS") getConArity :: QName -> IM Nat getConArity qn = do definitions <- getDefinitions let (Defn ty fv (Constructor np _ isa)) = definitions ! (qnameName qn) -- return $ typeArity ty return $ arity ty typeArity :: Type -> Nat typeArity (El s t) = ar t where ar (Pi _ (Abs _ t2)) = typeArity t2 + 1 ar (Fun a t2) = typeArity t2 + 1 ar _ = 0 -- returnOne :: Monad m => a -> m [a] -- returnOne = return . return type PState = Nat initPState = 0 type PM a = State PState a processArgPats :: [Arg Pattern] -> [HsPat] processArgPats args = pats where pm = mapM processArgPat args (pats, pst) = runState pm initPState initPState = 0 processArgPat :: (Arg Pattern) -> PM HsPat processArgPat (Arg hid pat) = processPat pat processPat :: Pattern -> PM HsPat processPat (VarP _) = do n <- get put (n+1) return $ HsPVar $ HsIdent ("v" ++ (show n)) processPat (ConP qname args) = do let name = qnameName qname hspats <- mapM processArgPat args return $ HsPParen $ HsPApp (conQName qname) hspats processPat (LitP (LitInt _ i)) = return $ HsPLit (HsInt i) processPat (LitP (LitChar _ c)) = return $ HsPParen $ HsPApp (rtpCon "CharT") [HsPLit (HsChar c)] processPat (LitP _) = error "Unimplemented literal patttern" -- return HsPWildCard processPat AbsurdP = return HsPWildCard processBody :: ClauseBody -> PM HsExp processBody (NoBind cb) = processBody cb processBody (Bind (Abs n cb)) = processBody cb processBody (Body t) = processTerm t >>= (return . hsCast) processBody NoBody = return hsUndefined processTerm :: Term -> PM HsExp processTerm (Var n ts) = do cnt <- get processVap (hsVar $ "v" ++ (show (cnt - n -1))) ts processTerm (Def qn ts) = processVap (HsVar $ dfQName qn) ts processTerm (Con qn ts) = processVap (HsCon $ conQName qn) ts processTerm (Lam h (Abs n t)) = do exp <- processTerm t return $ hsLam n exp processTerm (Lit l) = return $ (processLit l) processTerm (Pi arg abs) = error "Unimplemented term: Pi" processTerm (Fun arg typ) = error "Unimplemented term: Fun" processTerm (Sort s) = error "Unimplemented term: Sort" processTerm (BlockedV b) = error "Unimplemented term: Blocked" processTerm (MetaV _ _) = error "Can't have metavariables" -- processTerm t = return hsUndefined processLit :: Literal -> HsExp processLit (LitInt _ i) = hsPreludeTypedExp "Integer" $ HsLit $ HsInt i processLit (LitFloat _ f) = hsPreludeTypedExp "Double" $ HsLit $ HsFrac $ toRational f -- processLit (LitFloat _ f) = HsApp (HsVar $ rtpCon "FloatT") -- (HsLit $ HsFrac $ toRational f) processLit (LitString _ s) = HsLit $ HsString s processLit (LitChar _ c) = HsApp (HsVar $ rtpCon "CharT") (HsLit $ HsChar c) processVap :: HsExp -> [Arg Term] -> PM HsExp processVap e ts = do p <- get return $ unfoldVap p e ts unfoldVap :: PState -> HsExp -> [Arg Term] -> HsExp unfoldVap _ e [] = e unfoldVap p e ((Arg NotHidden t):ts) = unfoldVap p (hsAp e e1) ts where e1 = evalState (processTerm t) p unfoldVap p e ((Arg Hidden t):ts) = unfoldVap p e ts processDefWithDebug :: (Name,Definition) -> IM [HsDecl] processDefWithDebug (name,def) = do hsdecls <- processDef (name,def) return (nameInfo:hsdecls) where nameInfo = infoDecl infoName (show name) infoName = "name" ++ (show $ numOfName name) infoDecl :: String -> String -> HsDecl infoDecl name val = HsFunBind [ HsMatch dummyLoc hsname [] rhs []] where rhs = HsUnGuardedRhs $ HsLit $ HsString val hsname = HsIdent name processClause :: Name -> Int -> Clause -> IM HsDecl processClause name number (Clause args (body)) = do return $ HsFunBind $ [HsMatch dummyLoc hsid pats rhs decls] where decls = [] hsid = dfNameSub name number -- pats = processArgPats args pm = mapM processArgPat args (pats, pst) = runState pm initPState rhs = HsUnGuardedRhs exp (exp, pst2) = runState (processBody body) pst contClause :: Name -> Int -> Clause -> IM HsDecl contClause name number (Clause args (body)) = do return $ HsFunBind $ [HsMatch dummyLoc hsid pats rhs decls] where decls = [] hsid = dfNameSub name number pats = replicate (length args) HsPWildCard rhs = HsUnGuardedRhs exp exp = HsVar $ UnQual $ dfNameSub name (number+1) foldClauses :: Name -> Nat -> [Clause] -> IM [HsDecl] foldClauses name n [] = return [] foldClauses name n [c] = do decl <- processClause name n c return [decl] foldClauses name n (c:cs) = do head <- processClause name n c cont <- contClause name n c tail <- foldClauses name (n+1) cs return (head:cont:tail) processDef :: (Name,Definition) -> IM [HsDecl] processDef (name,Defn typ fvs (Function clauses isa)) = -- mapM (processClause name) clauses do hsDecls <- foldClauses name 1 clauses return [HsFunBind [HsMatch dummyLoc (dfName name) [] rhs hsDecls]] where rhs = HsUnGuardedRhs $ HsVar $ UnQual $ dfNameSub name 1 processDef (name,Defn typ fvs (Datatype n [] sort isa)) = do return [ddecl,vdecl] where ddecl = HsDataDecl dummyLoc [] (dataName name) tvars cons [] tvars = [] cons = [HsConDecl dummyLoc (conName name) [] ] vdecl = HsFunBind [ HsMatch dummyLoc hsname (nDummyArgs n) rhs []] rhs = HsUnGuardedRhs $ HsVar $ unit_con_name hsname = dfName name nDummyArgs :: Nat -> [HsPat] nDummyArgs 0 = [] nDummyArgs k = (HsPVar $ HsIdent ("v" ++ (show k))) : nDummyArgs (k-1) processDef (name,Defn typ fvs (Datatype n cs sort isa)) = do cons <- consForName name cs arities <- getConArities cs return [ddecl cons arities,vdecl] where ddecl cs arities= HsDataDecl dummyLoc [] (dataName name) (tvars arities) cs [] tvars arities = take (List.maximum arities) $ List.map HsIdent ["a", "b", "c", "d", "e"] vdecl = HsFunBind [ HsMatch dummyLoc hsname (nDummyArgs n) rhs []] rhs = HsUnGuardedRhs $ HsVar $ unit_con_name hsname = dfName name nDummyArgs 0 = [] nDummyArgs k = (HsPVar $ HsIdent ("v" ++ (show k))) : nDummyArgs (k-1) processDef def@(name,Defn typ fvs con@(Constructor n qn isa)) = do return [] processDef def@(name,Defn typ fvs Axiom) = return [] processDef (name,Defn typ fvs (Primitive info prim expr)) = return $ [HsFunBind [HsMatch dummyLoc hsid [] rhs decls]] where -- rhs = HsUnGuardedRhs $ error $ "primitive: " ++ (show prim) rhs = HsUnGuardedRhs $ HsVar $ rtpQName prim decls = [] hsid = dfName name {- processDef (name,Defn typ fvs _) = return $ [HsFunBind [HsMatch dummyLoc hsid [] rhs decls]] where rhs = HsUnGuardedRhs hsUndefined decls = [] hsid = dfName name -} consForName dname qns = mapM (processCon dname) qns times :: Nat -> a -> [a] times 0 x = [] times n x = x:(times (n-1) x) processCon dname qn = do let id = nameId $ qnameName qn let NameId cn = id arity <- getConArity qn -- let arg = HsUnBangedTy $ HsTyCon unit_tycon_name let arg = HsUnBangedTy $ HsTyVar $ HsIdent "a" let letters = List.map HsIdent ["a", "b", "c", "d", "e"] let args = List.map (HsUnBangedTy . HsTyVar) $ take arity letters return $ HsConDecl dummyLoc (conName $ qnameName qn) args {- dummyCon :: Int -> Int -> HsConDecl dummyCon i j = HsConDecl dummyLoc (mangleConName i j) [] mangleConName :: Int -> Int -> HsName -- mangleConName i j = (HsIdent $ "C"++(show i)++"_"++(show j)) mangleConName i j = (HsIdent $ "C"++(show j)) -} -- consForData :: QName -> IM [Definition] -- consForData qn = undefined consDefs :: [QName] -> IM [Definition] consDefs qns = do definitions <- getDefinitions let ns = List.map qnameName qns return [definitions ! name | name <- ns] getDefinitions :: IM Definitions getDefinitions = do sig <- gets stSignature let sigs = toList sig let definitions = mdefDefs (snd (head sigs)) -- :: Map Name Definition return definitions getConArities cs = mapM getConArity cs