Show
Ignore:
Timestamp:
01/15/06 16:49:47 (3 years ago)
Author:
audreyt
Message:

* -BPIR now returned to its full glory.
* Test.pm doesn't work yet because of named args.

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • src/Pugs/CodeGen/PIR.hs

    r7853 r8681  
    1414-} 
    1515 
    16 module Pugs.CodeGen.PIR (genPIR) where 
     16module Pugs.CodeGen.PIR (genPIR, genPIR_YAML) where 
    1717import Pugs.Internals 
    1818import Pugs.AST 
     
    2727import Pugs.Compile 
    2828import Pugs.Run (getLibs) 
     29import DrIFT.YAML 
    2930 
    3031type CodeGen a = WriterT [Stmt] (ReaderT TEnv IO) a 
     
    7879    trans (PExp exp) = fmap ExpLV $ trans exp 
    7980    trans (PLit (PVal VUndef)) = do 
    80         pmc     <- genLV "undef" 
     81        pmc     <- genScalar "undef" 
    8182        return $ ExpLV pmc 
    8283    trans (PLit lit) = do 
    8384        -- generate fresh supply and things... 
    8485        litC    <- trans lit 
    85         pmc     <- genLV "lit" 
    86         tellIns $ pmc <== ExpLit litC 
     86        pmc     <- genScalar "lit" 
     87        tellIns $ pmc <== litC 
    8788        return $ ExpLV pmc 
    8889    trans (PThunk exp) = do 
    89         [begL, sndL, retL, endL] <- genLabel ["thunkBegin", "thunkAgain", "thunkReturn", "thunkEnd"] 
    90         this    <- genPMC "block" 
    91         tellIns $ InsNew (reg this) Continuation 
    92         tellIns $ "set_addr" .- [reg this, bare begL] 
    93         tellIns $ "goto" .- [bare endL] 
    94         tellLabel begL 
    95         cc      <- genPMC "cc" 
    96         fetchCC cc (reg this) 
    97         expC    <- trans exp 
    98         tellIns $ "set_addr" .- [reg this, bare sndL] 
    99         tellIns $ "goto" .- [bare retL] 
    100         tellLabel sndL 
    101         fetchCC cc (reg this) 
    102         tellLabel retL 
    103         tellIns $ if parrotBrokenXXX 
    104             then "store_global" .- [tempSTR, expC] 
    105             else "set_args" .- [lit "(0b10)", expC] 
    106         tellIns $ "invokecc" .- [reg cc] 
    107         tellLabel endL 
     90        [begL, initL]  <- genLabel ["thunk", "thunkInit"] 
     91        this    <- genPMC "thunk" 
     92        let begP = begL ++ "_C" 
     93        tellIns $ InsConst (VAR begP) Sub (lit begL) 
     94        tellIns $ reg this <-- "newclosure" $ [bare begP] 
     95        -- inner subroutine begins 
     96        censor ((:[]) . StmtSub begL) $ do 
     97            -- tellIns $ "push_eh" .- [bare initL] 
     98            expC <- trans exp 
     99            tellIns $ "set_returns" .- retSigList [expC] 
     100            tellIns $ "returncc" .- [] 
    108101        return (ExpLV this) 
    109102    trans (PCode styp params _ _ body) = do 
    110         [begL, endL] <- genLabel ["blockBegin", "blockEnd"] 
     103        [begL]  <- genLabel ["block"] 
    111104        this    <- genPMC "block" 
    112105        let begP = begL ++ "_C" 
    113106        tellIns $ InsConst (VAR begP) Sub (lit begL) 
    114107        tellIns $ reg this <-- "newclosure" $ [bare begP] 
    115         tellIns $ "goto" .- [bare endL] 
    116         tellLabel begL 
    117         let prms = map tpParam params 
    118         mapM_ (tellIns . InsLocal RegPMC . prmToIdent) prms 
    119         tellIns $ "get_params" .- sigList (map prmToSig prms) 
    120         tellIns $ "new_pad" .- [lit curPad] 
    121         wrapSub styp $ do 
    122             mapM storeLex params 
    123             trans body  -- XXX - consistency check 
    124             bodyC   <- lastPMC 
    125             tellIns $ "set_returns" .- retSigList [bodyC] 
    126             tellIns $ "returncc" .- [] 
    127         tellLabel endL 
     108        -- inner subroutine begins 
     109        censor ((:[]) . StmtSub begL) $ do 
     110            let prms = map tpParam params 
     111            tell [StmtPad (map prmToPad prms) []] 
     112            tellIns $ "get_params" .- sigList (map prmToSig prms) 
     113            wrapSub styp $ do 
     114                mapM storeLex params 
     115                bodyC   <- case body of 
     116                    PNil -> return nullPMC 
     117                    _    -> trans body >> lastPMC 
     118                tellIns $ "set_returns" .- retSigList [bodyC] 
     119                tellIns $ "returncc" .- [] 
    128120        return (ExpLV this) 
     121 
     122prmToPad :: Param -> (VarName, Expression) 
     123prmToPad prm = (paramName prm, ExpLV (VAR $ prmToIdent prm)) 
    129124 
    130125instance Translate PIL_Decl Decl where 
     
    135130        (_, stmts)  <- listen $ do 
    136131            let prms = map tpParam params 
    137             mapM_ (tellIns . InsLocal RegPMC . prmToIdent) prms 
     132            tell [StmtPad (map prmToPad prms) []] 
    138133            tellIns $ "get_params" .- sigList (map prmToSig prms) 
    139             tellIns $ "new_pad" .- [lit curPad] 
     134            -- tellIns $ "new_pad" .- [lit curPad] 
    140135            wrapSub styp $ do 
    141136                mapM storeLex params 
    142                 trans body 
    143                 bodyC <- lastPMC 
     137                bodyC   <- case body of 
     138                    PNil -> return nullPMC 
     139                    _    -> trans body >> lastPMC 
    144140                tellIns $ "set_returns" .- retSigList [bodyC] 
    145141                tellIns $ "returncc" .- [] 
    146         return (DeclSub name [] stmts) 
    147  
    148 instance Translate PIL_Literal Literal where 
    149     trans (PVal (VBool bool)) = return $ LitInt (toInteger $ fromEnum bool) 
    150     trans (PVal (VStr str)) = return $ LitStr str 
    151     trans (PVal (VInt int)) = return $ LitInt int 
    152     trans (PVal (VNum num)) = return $ LitNum num 
    153     trans (PVal (VRat rat)) = return $ LitNum (ratToNum rat) 
    154     trans (PVal (VList [])) = return $ LitInt 0 -- XXX Wrong 
     142        return (DeclSub name [SubOUTER "main"] stmts) 
     143 
     144instance Translate PIL_Literal Expression where 
     145    trans (PVal (VBool bool)) = return $ ExpLit (LitInt (toInteger $ fromEnum bool)) 
     146    trans (PVal (VStr str)) = return $ ExpLit (LitStr str) 
     147    trans (PVal (VInt int)) = return $ ExpLit (LitInt int) 
     148    trans (PVal (VNum num)) = return $ ExpLit (LitNum num) 
     149    trans (PVal (VRat rat)) = return $ ExpLit (LitNum (ratToNum rat)) 
     150    -- trans (PVal (VList [])) = return $ LitInt 0 -- XXX Wrong 
     151    trans (PVal (VList vs)) = do 
     152        pmc <- genArray "vlist" 
     153        forM vs $ \val -> do 
     154            valC <- trans (PVal val) 
     155            tellIns $ "push" .- [pmc, valC] 
     156        return pmc 
    155157    trans val@(PVal _) = transError val 
    156158 
    157159instance Translate PIL_LValue LValue where 
    158160    trans (PVar name) | Just (pkg, name') <- isQualified name = do 
    159         -- XXX - this is terribly ugly.  Fix at parrot side perhaps? 
    160         pmc     <- genLV "glob" 
    161         let initL   = "init_" ++ pmcStr 
    162             doneL   = "done_" ++ pmcStr 
    163             pmcStr  = render (emit pmc) 
    164         tellIns $ "push_eh" .- [bare initL] 
    165         tellIns $ pmc <-- "find_global" $ [lit pkg, lit name'] 
    166         tellIns $ "goto" .- [bare doneL] 
    167         tellLabel initL 
     161        [globL] <- genLabel ["glob"] 
     162        pmc     <- genScalar "glob" 
     163        tell [StmtRaw (text "errorsoff .PARROT_ERRORS_GLOBALS_FLAG")] 
     164        tellIns $ pmc       <-- "find_global" $ [lit pkg, lit name'] 
     165        tellIns $ tempINT   <-- "defined" $ [reg pmc] 
     166        tellIns $ "if" .- [tempINT, bare globL] 
     167        tellIns $ InsNew pmc PerlScalar 
    168168        tellIns $ "store_global" .- [lit pkg, lit name', reg pmc] 
    169         tellLabel doneL 
    170         tellIns $ "clear_eh" .- [] 
     169        tellLabel globL 
     170        tell [StmtRaw (text "errorson .PARROT_ERRORS_GLOBALS_FLAG")] 
    171171        return pmc 
    172172    trans (PVar name) = do 
    173         pmc     <- genLV "lex" 
     173        pmc     <- genScalar "lex" 
    174174        tellIns $ pmc <-- "find_name" $ [lit $ possiblyFixOperatorName name] 
    175175        return pmc 
     
    179179        tellIns $ lhsC <== rhsC 
    180180        return lhsC 
    181     trans (PBind [PVar name] rhs) 
    182         | Just (pkg, name') <- isQualified (qualify name) = do 
     181    trans (PBind [PVar name] rhs) = do 
    183182        rhsC    <- trans rhs 
    184         tellIns $ "store_global" .- [lit pkg, lit name', rhsC] 
     183        tellIns $ "store_lex" .- [lit name, rhsC] 
    185184        trans (PVar name) 
    186185    trans (PBind [lhs] rhs) = do 
     
    189188        tellIns $ lhsC <:= rhsC 
    190189        return lhsC 
    191     trans (PApp _ exp@(PCode _ _ _ _ _) Nothing []) = do 
     190    trans (PApp _ exp@PCode{} Nothing []) = do 
    192191        blockC  <- trans exp 
    193192        tellIns $ [reg tempPMC] <-& blockC $ [] 
     
    200199        trans (PApp ctx fun Nothing (inv:args))  -- XXX wrong 
    201200    trans (PApp _ fun Nothing args) = do 
    202         funC    <- trans fun {- case fun of 
     201        funC <- trans fun {- case fun of 
    203202            PExp (PVar name) -> return $ lit name 
    204203            _           -> trans fun 
     
    206205        argsC   <- mapM trans args 
    207206        -- XXX WORKAROUND PARROT BUG (see below) 
    208         pmc     <- genLV "app" 
     207        pmc     <- genScalar "app" 
    209208        -- XXX - probe if funC is slurpy, then modify ExpLV pmc accordingly 
    210209        tellIns $ [reg pmc] <-& funC $ argsC 
     
    216215                return nullPMC 
    217216            _ -> do 
    218                 pmc     <- genLV "app" 
     217                pmc     <- genScalar "app" 
    219218                -- XXX - probe if funC is slurpy, then modify ExpLV pmc accordingly 
    220219                tellIns $ [reg pmc] <-& funC $ argsC 
     
    222221        -} 
    223222    trans x = transError x 
    224  
    225 fetchCC :: LValue -> Expression -> CodeGen () 
    226 fetchCC cc begL | parrotBrokenXXX = do 
    227     tellIns $ tempINT   <-- "get_addr" $ [begL] 
    228     tellIns $ tempSTR   <:= tempINT 
    229     tellIns $ "find_global" .- [reg cc, tempSTR] 
    230 fetchCC cc _ = do 
    231     tellIns $ "get_params" .- sigList [reg cc] 
    232223 
    233224-- XXX - slow way of implementing "return" 
     
    240231    body 
    241232    tellLabel retL 
    242     tellIns $ tempPMC <:= ExpLV (errPMC `KEYED` lit False) 
     233    tellIns $ ("get_results" .- sigList [tempPMC, tempSTR]) 
    243234    tellIns $ "clear_eh" .- [] 
    244     tellIns $ tempSTR <-- "typeof" $ [errPMC] 
     235    tellIns $ tempSTR <-- "typeof" $ [tempPMC] 
    245236    tellIns $ "eq" .- [tempSTR, lit "Exception", bare errL] 
    246237    tellIns $ "set_returns" .- sigList [tempPMC] 
    247238    tellIns $ "returncc" .- [] 
    248239    tellLabel errL 
    249     tellIns $ "throw" .- [errPMC] 
     240    tellIns $ "throw" .- [tempPMC] 
    250241 
    251242prmToSig :: Param -> Sig 
     
    275266                tellIns $ VAR name <:= expC 
    276267        tellLabel defC 
    277     tellIns $ "store_lex" .- [lit curPad, lit var, bare name] 
     268    tellIns $ "store_lex" .- [lit var, bare name] 
    278269    where 
    279270    var     = paramName prm 
     
    291282lastPMC = do 
    292283    tvar    <- asks tReg 
    293     name'   <- liftIO $ liftSTM $ do 
     284    liftIO $ liftSTM $ do 
    294285        (cur, name) <- readTVar tvar 
    295         return $ ('P':show cur) ++ (if null name then name else ('_':name)) 
    296     return $ reg (VAR name') 
     286        return $ case cur of 
     287            0 -> nullPMC 
     288            _ -> reg (VAR (('p':show cur) ++ (if null name then name else ('_':name)))) 
    297289 
    298290genPMC :: (RegClass a) => String -> CodeGen a 
     
    302294        (cur, _) <- readTVar tvar 
    303295        writeTVar tvar (cur + 1, name) 
    304         return $ ('P':show (cur + 1)) ++ ('_':name) 
     296        return $ ('p':show (cur + 1)) ++ ('_':name) 
    305297    tellIns $ InsLocal RegPMC name' 
    306298    return $ reg (VAR name') 
    307299 
    308 genLV :: (RegClass a) => String -> CodeGen a 
    309 genLV name = do 
     300genWith :: (RegClass a) => (LValue -> Ins) -> String -> CodeGen a 
     301genWith f name = do 
    310302    pmc <- genPMC name 
    311     tellIns $ InsNew pmc PerlScalar 
     303    tellIns $ f pmc 
    312304    return $ reg pmc 
     305 
     306genScalar :: (RegClass a) => String -> CodeGen a 
     307genScalar = genWith (`InsNew` PerlScalar) 
     308 
     309genArray :: (RegClass a) => String -> CodeGen a 
     310genArray = genWith (`InsNew` PerlArray) 
     311 
     312genHash :: (RegClass a) => String -> CodeGen a 
     313genHash = genWith (`InsNew` PerlHash) 
    313314 
    314315genLabel :: [String] -> CodeGen [LabelName] 
     
    335336varInit x       = internalError $ "Invalid name: " ++ x 
    336337 
     338genPIR_YAML :: Eval Val 
     339genPIR_YAML = genPIRWith $ \globPIR mainPIR _ -> do 
     340    yaml <- liftIO (showYaml (mainPIR, globPIR)) 
     341    return (VStr yaml) 
     342 
    337343{-| Compiles the current environment to PIR code. -} 
    338344genPIR :: Eval Val 
    339 genPIR = do 
    340     tenv        <- initTEnv 
    341     -- Load the PIR Prelude. 
    342     local (\env -> env{ envDebug = Nothing }) $ do 
    343         opEval style "<prelude-pir>" preludeStr 
    344     penv        <- compile () 
    345     globPIR     <- runCodeGenGlob tenv (pilGlob penv) 
    346     mainPIR     <- runCodeGenMain tenv (pilMain penv) 
     345genPIR = genPIRWith $ \globPIR mainPIR penv -> do 
    347346    libs        <- liftIO $ getLibs 
    348347    return . VStr . unlines $ 
     
    350349        , renderStyle (Style PageMode 0 0) $ preludePIR $+$ vcat 
    351350        -- Namespaces have bugs in both pugs and parrot. 
    352         [ emit globPIR 
    353         , emit $ DeclNS "main" 
     351        [ emit $ DeclNS "main" 
    354352        [ DeclSub "init" [SubMAIN, SubANON] $ map StmtIns ( 
    355353            -- Eventually, we'll have to write our own find_name wrapper (or 
    356354            -- fix Parrot's find_name appropriately). See Pugs.Eval.Var. 
    357355            -- For now, we simply store $P0 twice. 
    358             [ "new_pad" .- [lit0] 
    359             , InsNew tempPMC PerlEnv 
     356            [ InsNew tempPMC PerlEnv 
    360357            , "store_global"    .- [lit "%*ENV", tempPMC] 
    361358            , "store_global"    .- [lit "%ENV", tempPMC] 
     
    392389            , StmtIns $ "invokecc" .- [tempPMC] 
    393390            ] 
    394         , DeclSub "main" [SubANON] [ StmtRaw $ emit mainPIR ] 
    395         ] ] ] 
     391        , DeclSub "main" [SubANON] (concatMap vivifySub globPIR ++ mainPIR) ] 
     392        , emit globPIR ] ] 
     393 
     394vivifySub :: Decl -> [Stmt] 
     395vivifySub (DeclNS "main" decls) = concatMap vivifySub decls 
     396vivifySub (DeclSub name@('&':c:_') [SubOUTER "main"] _) 
     397    | c /= '*' 
     398    = map StmtIns 
     399        [ tempPMC <-- "find_name" $ [lit name] 
     400        , tempPMC <-- "newclosure" $ [tempPMC] 
     401        , "store_global" .- [lit "main", lit name, tempPMC] 
     402        ] 
     403vivifySub _ = [] 
     404 
     405genPIRWith f = do 
     406    tenv        <- initTEnv 
     407    -- Load the PIR Prelude. 
     408    local (\env -> env{ envDebug = Nothing }) $ do 
     409        opEval style "<prelude-pir>" preludeStr 
     410    penv        <- compile () 
     411    globPIR     <- runCodeGenGlob tenv (pilGlob penv) 
     412    mainPIR     <- runCodeGenMain tenv (pilMain penv) 
     413    f globPIR mainPIR penv 
    396414    where 
    397415    style = MkEvalStyle