| 15 | | import Pugs.Compile.PIR (genPIR) |
| 16 | | import Pugs.Compile.Pugs (genPugs) |
| 17 | | import Pugs.Compile.Haskell (genGHC) |
| 18 | | |
| 19 | | compile :: String -> Env -> IO String |
| 20 | | compile "GHC" env = fmap vCast $ runEvalIO env genGHC |
| 21 | | compile "Ghc" env = fmap vCast $ runEvalIO env genGHC |
| 22 | | compile "Haskell" env = fmap vCast $ runEvalIO env genGHC |
| 23 | | compile "Parrot" env = fmap vCast $ runEvalIO env genPIR |
| 24 | | compile "Pir" env = fmap vCast $ runEvalIO env genPIR |
| 25 | | compile "PIR" env = fmap vCast $ runEvalIO env genPIR |
| 26 | | compile "Pugs" env = fmap vCast $ runEvalIO env genPugs |
| 27 | | compile s _ = fail $ "Cannot compile to " ++ s |
| 28 | | |
| | 15 | import Pugs.Types |
| | 16 | import Pugs.Eval |
| | 17 | import Emit.PIR |
| | 18 | import Text.PrettyPrint |
| | 19 | |
| | 20 | {-| |
| | 21 | The plan here is to first compile the environment (subroutines, |
| | 22 | statements, etc.) to an abstract syntax tree ('PIL' -- Pugs Intermediate |
| | 23 | Language) using the 'compile' function and 'Compile' class. |
| | 24 | -} |
| | 25 | |
| | 26 | #ifndef HADDOCK |
| | 27 | -- Type-indexed with GADT; it is a bit too baroque -- refactor toward ANF? |
| | 28 | data (Typeable a) => PIL a where |
| | 29 | PNil :: PIL [a] |
| | 30 | PNoop :: PIL Stmt |
| | 31 | |
| | 32 | PRawName :: !VarName -> PIL Expression -- XXX HACK! |
| | 33 | |
| | 34 | PExp :: !(PIL LValue) -> PIL Expression |
| | 35 | PLit :: !(PIL Literal) -> PIL Expression |
| | 36 | PPos :: !Pos -> !Exp -> !(PIL a) -> PIL a |
| | 37 | PStmt :: !(PIL Expression) -> PIL Stmt |
| | 38 | PThunk :: !(PIL Expression) -> PIL Expression |
| | 39 | PCode :: !SubType -> ![TParam] -> !(PIL [Stmt]) -> PIL Expression |
| | 40 | |
| | 41 | PVal :: !Val -> PIL Literal |
| | 42 | PVar :: !VarName -> PIL LValue |
| | 43 | |
| | 44 | PStmts :: !(PIL Stmt) -> !(PIL [Stmt]) -> PIL [Stmt] |
| | 45 | PApp :: !TCxt -> !(PIL Expression) -> ![PIL Expression] -> PIL LValue |
| | 46 | PAssign :: ![PIL LValue] -> !(PIL Expression) -> PIL LValue |
| | 47 | PBind :: ![PIL LValue] -> !(PIL Expression) -> PIL LValue |
| | 48 | PPad :: !Scope -> ![(VarName, PIL Expression)] -> !(PIL [Stmt]) -> PIL [Stmt] |
| | 49 | |
| | 50 | PSub :: !SubName -> !SubType -> ![TParam] -> !(PIL [Stmt]) -> PIL Decl |
| | 51 | #endif |
| | 52 | |
| | 53 | instance Typeable1 PIL where |
| | 54 | typeOf1 _ = typeOf () |
| | 55 | |
| | 56 | data TParam = MkTParam |
| | 57 | { tpParam :: !Param |
| | 58 | , tpDefault :: !(Maybe (PIL Expression)) |
| | 59 | } |
| | 60 | deriving (Show, Typeable) |
| | 61 | |
| | 62 | data TCxt |
| | 63 | = TCxtVoid | TCxtLValue !Type | TCxtItem !Type | TCxtSlurpy !Type |
| | 64 | | TTailCall !TCxt |
| | 65 | deriving (Show, Eq, Typeable) |
| | 66 | |
| | 67 | tcVoid, tcLValue :: TCxt |
| | 68 | tcVoid = TCxtVoid |
| | 69 | tcLValue = TCxtLValue anyType |
| | 70 | |
| | 71 | {- |
| | 72 | tcItem, tcSlurpy :: TCxt |
| | 73 | tcItem = TCxtItem anyType |
| | 74 | tcSlurpy = TCxtSlurpy anyType |
| | 75 | -} |
| | 76 | |
| | 77 | instance Show (PIL a) where |
| | 78 | show (PVal x) = "(PVal " ++ show x ++ ")" |
| | 79 | show (PVar x) = "(PVar " ++ show x ++ ")" |
| | 80 | show (PLit x) = "(PLit " ++ show x ++ ")" |
| | 81 | show (PStmts x y) = "(PStmts " ++ show x ++ " " ++ show y ++ ")" |
| | 82 | show PNil = "PNil" |
| | 83 | show PNoop = "PNoop" |
| | 84 | show (PPos x y z) = "(PPos " ++ show x ++ " " ++ show y ++ " " ++ show z ++ ")" |
| | 85 | show (PApp x y z) = "(PApp " ++ show x ++ " " ++ show y ++ " " ++ show z ++ ")" |
| | 86 | show (PExp x) = "(PExp " ++ show x ++ ")" |
| | 87 | show (PStmt x) = "(PStmt " ++ show x ++ ")" |
| | 88 | show (PAssign x y) = "(PAssign " ++ show x ++ " " ++ show y ++ ")" |
| | 89 | show (PBind x y) = "(PBind " ++ show x ++ " " ++ show y ++ ")" |
| | 90 | show (PThunk x) = "(PThunk " ++ show x ++ ")" |
| | 91 | show (PRawName x) = "(PRawName " ++ show x ++ ")" |
| | 92 | show (PPad x y z) = unwords ["(PPad", show x, show y, show z, ")"] |
| | 93 | show (PCode x y z) = unwords ["(PCode", show x, show y, show z, ")"] |
| | 94 | show (PSub x y z w) = unwords ["(PSub", show x, show y, show z, show w, ")"] |
| | 95 | |
| | 96 | data TEnv = MkTEnv |
| | 97 | { tLexDepth :: !Int -- ^ Lexical scope depth |
| | 98 | , tTokDepth :: !Int -- ^ Exp nesting depth |
| | 99 | , tCxt :: !TCxt -- ^ Current context |
| | 100 | , tReg :: !(TVar (Int, String))-- ^ Register name supply |
| | 101 | , tLabel :: !(TVar Int) -- ^ Label name supply |
| | 102 | } |
| | 103 | deriving (Show, Eq) |
| | 104 | |
| | 105 | type Comp a = Eval a |
| | 106 | type CompMonad = EvalT (ContT Val (ReaderT Env SIO)) |
| | 107 | |
| | 108 | {-| Currently only 'Exp' → 'PIL' -} |
| | 109 | class (Show a, Typeable b) => Compile a b where |
| | 110 | compile :: a -> Comp b |
| | 111 | compile x = fail ("Unrecognized construct: " ++ show x) |
| | 112 | |
| | 113 | -- Compile instances |
| | 114 | instance Compile (Var, [(TVar Bool, TVar VRef)]) (PIL Decl) where |
| | 115 | compile = compError |
| | 116 | |
| | 117 | instance Compile Param TParam where |
| | 118 | compile prm = do |
| | 119 | defC <- if isOptional prm |
| | 120 | then fmap Just $ compile (paramDefault prm) |
| | 121 | else return Nothing |
| | 122 | return $ MkTParam |
| | 123 | { tpParam = prm |
| | 124 | , tpDefault = defC |
| | 125 | } |
| | 126 | |
| | 127 | {-| Compiles a 'Pad' to a list of 'PIL Decl's. Currently, only subroutines and |
| | 128 | @\@*END@ are compiled. -} |
| | 129 | instance Compile Pad [PIL Decl] where |
| | 130 | compile pad = do |
| | 131 | entries' <- mapM canCompile entries |
| | 132 | return $ concat entries' |
| | 133 | where |
| | 134 | entries = sortBy padSort $ padToList pad |
| | 135 | canCompile (name@('&':_), [(_, sym)]) = do |
| | 136 | ref <- liftSTM $ readTVar sym |
| | 137 | case ref of |
| | 138 | MkRef (ICode cv) |
| | 139 | -> doCode name =<< code_fetch cv |
| | 140 | MkRef (IScalar sv) | scalar_iType sv == mkType "Scalar::Const" |
| | 141 | -> doCode name =<< fromVal =<< scalar_fetch sv |
| | 142 | _ -> return [] |
| | 143 | canCompile ("@*END", [(_, sym)]) = do |
| | 144 | ref <- liftSTM $ readTVar sym |
| | 145 | cvList <- fromVals =<< readRef ref :: Comp [VCode] |
| | 146 | decls <- eachM cvList $ \(i, cv) -> do |
| | 147 | compile (("&*END_" ++ show i), cv) :: Comp [PIL Decl] |
| | 148 | compile ("&*END", concat decls) |
| | 149 | canCompile ((_:twigil:_), _) | not (isAlphaNum twigil) = return [] |
| | 150 | canCompile (name, [(_, sym)]) = do |
| | 151 | -- translate them into store_global calls? |
| | 152 | -- placing them each into one separate init function? |
| | 153 | val <- readRef =<< liftSTM (readTVar sym) |
| | 154 | valC <- compile val |
| | 155 | let assignC = PAssign [PVar name'] valC |
| | 156 | bodyC = PStmts (PStmt . PExp $ assignC) PNil |
| | 157 | initL = "__init_" ++ (render $ varText name) |
| | 158 | name' | ':' `elem` name = name |
| | 159 | | otherwise = "main::" ++ name -- XXX wrong |
| | 160 | return [PSub initL SubPrim [] bodyC] |
| | 161 | canCompile _ = return [] |
| | 162 | doCode name vsub = case subBody vsub of |
| | 163 | Prim _ -> return [] |
| | 164 | _ -> compile (name, vsub) |
| | 165 | |
| | 166 | eachM :: (Monad m) => [a] -> ((Int, a) -> m b) -> m [b] |
| | 167 | eachM = forM . ([0..] `zip`) |
| | 168 | |
| | 169 | instance Compile (SubName, [PIL Decl]) [PIL Decl] where |
| | 170 | compile (name, decls) = do |
| | 171 | let bodyC = [ PStmts . PStmt . PExp $ PApp tcVoid (PExp (PVar sub)) [] |
| | 172 | | PSub sub _ _ _ <- decls |
| | 173 | ] |
| | 174 | return (PSub name SubPrim [] (combine bodyC PNil):decls) |
| | 175 | |
| | 176 | instance Compile (SubName, VCode) [PIL Decl] where |
| | 177 | compile (name, vsub) | packageOf name /= packageOf (subName vsub) = do |
| | 178 | let storeC = PBind [PVar $ qualify name] (PExp . PVar . qualify $ subName vsub) |
| | 179 | bodyC = PStmts (PStmt . PExp $ storeC) PNil |
| | 180 | exportL = "__export_" ++ (render $ varText name) |
| | 181 | return [PSub exportL SubPrim [] bodyC] |
| | 182 | compile (name, vsub) = do |
| | 183 | bodyC <- enter cxtItemAny . compile $ case subBody vsub of |
| | 184 | Syn "block" [body] -> body |
| | 185 | body -> body |
| | 186 | paramsC <- compile $ subParams vsub |
| | 187 | return [PSub name (subType vsub) paramsC bodyC] |
| | 188 | |
| | 189 | instance Compile (String, [(TVar Bool, TVar VRef)]) (PIL Expression) where |
| | 190 | compile (name, _) = return $ PRawName name |
| | 191 | |
| | 192 | instance Compile Exp (PIL [Stmt]) where |
| | 193 | compile (Pos pos rest) = fmap (PPos pos rest) $ compile rest |
| | 194 | compile (Cxt cxt rest) = enter cxt $ compile rest |
| | 195 | compile (Stmts (Pad SOur _ exp) rest) = do |
| | 196 | compile $ mergeStmts exp rest |
| | 197 | compile (Stmts (Pad _ pad exp) rest) = do |
| | 198 | expC <- compile $ mergeStmts exp rest |
| | 199 | padC <- compile $ padToList pad |
| | 200 | return $ PPad SMy ((map fst $ padToList pad) `zip` padC) expC |
| | 201 | compile exp = compileStmts exp |
| | 202 | |
| | 203 | class EnterClass m a where |
| | 204 | enter :: a -> m b -> m b |
| | 205 | |
| | 206 | instance EnterClass CompMonad VCode where |
| | 207 | enter sub = local (\e -> e{ envLValue = subLValue sub, envContext = CxtItem (subReturns sub) }) |
| | 208 | |
| | 209 | instance EnterClass CompMonad Cxt where |
| | 210 | enter cxt = local (\e -> e{ envContext = cxt }) |
| | 211 | |
| | 212 | compileStmts :: Exp -> Comp (PIL [Stmt]) |
| | 213 | compileStmts exp = case exp of |
| | 214 | Stmts this Noop -> do |
| | 215 | thisC <- compile this |
| | 216 | return $ PStmts (tailCall thisC) PNil |
| | 217 | where |
| | 218 | tailCall (PStmt (PExp (PApp cxt fun args))) |
| | 219 | = PStmt $ PExp $ PApp (TTailCall cxt) fun args |
| | 220 | tailCall (PPos pos exp x) = PPos pos exp (tailCall x) |
| | 221 | tailCall x = x |
| | 222 | Stmts this rest -> do |
| | 223 | thisC <- enter cxtVoid $ compile this |
| | 224 | restC <- compileStmts rest |
| | 225 | return $ PStmts thisC restC |
| | 226 | Noop -> return PNil |
| | 227 | _ -> compile (Stmts exp Noop) |
| | 228 | |
| | 229 | instance Compile Val (PIL Stmt) where |
| | 230 | compile = fmap PStmt . compile . Val |
| | 231 | |
| | 232 | instance Compile Val (PIL Expression) where |
| | 233 | compile = compile . Val |
| | 234 | |
| | 235 | instance Compile Exp (PIL Stmt) where |
| | 236 | compile (Pos pos rest) = fmap (PPos pos rest) $ compile rest |
| | 237 | compile (Cxt cxt rest) = enter cxt $ compile rest |
| | 238 | compile Noop = return PNoop |
| | 239 | compile (Val val) = do |
| | 240 | cxt <- asks envContext |
| | 241 | if isVoidCxt cxt |
| | 242 | then case val of |
| | 243 | VBool True -> compile Noop |
| | 244 | _ -> do |
| | 245 | warn "Useless use of a constant in void context" val |
| | 246 | compile Noop |
| | 247 | else compile val |
| | 248 | compile (Syn "loop" [exp]) = |
| | 249 | compile (Syn "loop" $ [emptyExp, Val (VBool True), emptyExp, exp]) |
| | 250 | compile (Syn "loop" [pre, cond, post, (Syn "block" [body])]) = do |
| | 251 | preC <- compile pre |
| | 252 | condC <- compile cond |
| | 253 | bodyC <- compile body |
| | 254 | postC <- compile post |
| | 255 | funC <- compile (Var "&statement_control:loop") |
| | 256 | return . PStmt . PExp $ PApp TCxtVoid funC |
| | 257 | [preC, pBlock condC, pBlock bodyC, pBlock postC] |
| | 258 | compile exp@(Syn "unless" _) = fmap (PStmt . PExp) $ compConditional exp |
| | 259 | compile exp@(Syn "while" _) = compLoop exp |
| | 260 | compile exp@(Syn "until" _) = compLoop exp |
| | 261 | compile exp@(Syn "postwhile" _) = compLoop exp |
| | 262 | compile exp@(Syn "postuntil" _) = compLoop exp |
| | 263 | compile (Syn "for" [exp, body]) = do |
| | 264 | expC <- compile exp |
| | 265 | bodyC <- compile body |
| | 266 | funC <- compile (Var "&statement_control:for") |
| | 267 | return . PStmt . PExp $ PApp TCxtVoid funC [expC, bodyC] |
| | 268 | compile (Syn "given" _) = compile (Var "$_") -- XXX |
| | 269 | compile (Syn "when" _) = compile (Var "$_") -- XXX |
| | 270 | compile exp = fmap PStmt $ compile exp |
| | 271 | |
| | 272 | pBlock :: PIL [Stmt] -> PIL Expression |
| | 273 | pBlock = PCode SubBlock [] |
| | 274 | |
| | 275 | {- |
| | 276 | subTCxt :: VCode -> Eval TCxt |
| | 277 | subTCxt sub = return $ if subLValue sub |
| | 278 | then TCxtLValue (subReturns sub) |
| | 279 | else TCxtItem (subReturns sub) |
| | 280 | -} |
| | 281 | |
| | 282 | askTCxt :: Eval TCxt |
| | 283 | askTCxt = do |
| | 284 | env <- ask |
| | 285 | return $ if envLValue env |
| | 286 | then TCxtLValue (typeOfCxt $ envContext env) |
| | 287 | else case envContext env of |
| | 288 | CxtVoid -> TCxtVoid |
| | 289 | CxtItem typ -> TCxtItem typ |
| | 290 | CxtSlurpy typ -> TCxtSlurpy typ |
| | 291 | |
| | 292 | instance (Show (m a), FunctorM m, Typeable1 m, Compile a b) => Compile (m a) (m b) where |
| | 293 | compile = fmapM compile |
| | 294 | |
| | 295 | instance (Compile a b, Compile a c) => Compile [a] (b, c) where |
| | 296 | compile [x, y] = do { x' <- compile x ; y' <- compile y; return (x', y') } |
| | 297 | compile x = compError x |
| | 298 | |
| | 299 | instance (Compile a b, Compile a c, Compile a d) => Compile [a] (b, c, d) where |
| | 300 | compile [x, y, z] = do { x' <- compile x ; y' <- compile y; z' <- compile z; return (x', y', z') } |
| | 301 | compile x = compError x |
| | 302 | |
| | 303 | instance Compile Exp (PIL LValue) where |
| | 304 | compile (Pos pos rest) = fmap (PPos pos rest) $ compile rest |
| | 305 | compile (Cxt cxt rest) = enter cxt $ compile rest |
| | 306 | compile (Var name) = return $ PVar name |
| | 307 | compile (Syn (sigil:"::()") exps) = do |
| | 308 | compile $ App (Var "&Pugs::Internals::symbolic_deref") Nothing $ |
| | 309 | (Val . VStr $ sigil:""):exps |
| | 310 | compile (App (Var "&goto") (Just inv) args) = do |
| | 311 | cxt <- askTCxt |
| | 312 | funC <- compile inv |
| | 313 | argsC <- enter cxtItemAny $ compile args |
| | 314 | return $ PApp (TTailCall cxt) funC argsC |
| | 315 | compile (App fun (Just inv) args) = do |
| | 316 | compile (App fun Nothing (inv:args)) -- XXX WRONG |
| | 317 | compile (App fun Nothing args) = do |
| | 318 | cxt <- askTCxt |
| | 319 | funC <- compile fun |
| | 320 | argsC <- enter cxtItemAny $ compile args |
| | 321 | return $ PApp cxt funC argsC |
| | 322 | compile exp@(Syn "if" _) = compConditional exp |
| | 323 | compile (Syn "{}" (x:xs)) = compile $ App (Var "&postcircumfix:{}") (Just x) xs |
| | 324 | compile (Syn "[]" (x:xs)) = do |
| | 325 | compile (App (Var "&postcircumfix:[]") (Just x) xs) |
| | 326 | compile (Syn "," exps) = do |
| | 327 | compile (App (Var "&infix:,") Nothing exps) |
| | 328 | compile (Syn "\\[]" exps) = do |
| | 329 | compile (App (Var "&circumfix:[]") Nothing exps) |
| | 330 | compile (Syn "\\{}" exps) = do |
| | 331 | compile (App (Var "&circumfix:{}") Nothing exps) |
| | 332 | compile (Syn "=" [lhs, rhs]) = do |
| | 333 | lhsC <- enterLValue $ compile lhs |
| | 334 | rhsC <- enterRValue $ compile rhs |
| | 335 | return $ PAssign [lhsC] rhsC |
| | 336 | compile (Syn ":=" exps) = do |
| | 337 | (lhsC, rhsC) <- enterLValue $ compile exps |
| | 338 | return $ PBind [lhsC] rhsC |
| | 339 | compile (Syn syn [lhs, exp]) | last syn == '=' = do |
| | 340 | let op = "&infix:" ++ init syn |
| | 341 | compile $ Syn "=" [lhs, App (Var op) Nothing [lhs, exp]] |
| | 342 | compile exp = compError exp |
| | 343 | |
| | 344 | compLoop :: Exp -> Comp (PIL Stmt) |
| | 345 | compLoop (Syn name [cond, body]) = do |
| | 346 | cxt <- askTCxt |
| | 347 | condC <- enter (CxtItem $ mkType "Bool") $ compile cond |
| | 348 | bodyC <- enter CxtVoid $ compile body |
| | 349 | funC <- compile (Var $ "&statement_control:" ++ name) |
| | 350 | return . PStmt . PExp $ PApp cxt funC [pBlock condC, pBlock bodyC] |
| | 351 | compLoop exp = compError exp |
| | 352 | |
| | 353 | {-| Compiles a conditional 'Syn' (@if@ and @unless@) to a call to an |
| | 354 | appropriate function call (@&statement_control:if@ or |
| | 355 | @&statement_control:unless@). -} |
| | 356 | compConditional :: Exp -> Comp (PIL LValue) |
| | 357 | compConditional (Syn name exps) = do |
| | 358 | [condC, trueC, falseC] <- compile exps |
| | 359 | funC <- compile $ Var ("&statement_control:" ++ name) |
| | 360 | cxt <- askTCxt |
| | 361 | return $ PApp cxt funC [condC, PThunk trueC, PThunk falseC] |
| | 362 | compConditional exp = compError exp |
| | 363 | |
| | 364 | {-| Compiles various 'Exp's to 'PIL Expression's. -} |
| | 365 | instance Compile Exp (PIL Expression) where |
| | 366 | compile (Pos pos rest) = fmap (PPos pos rest) $ compile rest |
| | 367 | compile (Cxt cxt rest) = enter cxt $ compile rest |
| | 368 | compile (Var name) = return . PExp $ PVar name |
| | 369 | compile exp@(Val (VCode _)) = compile $ Syn "sub" [exp] |
| | 370 | compile (Val val) = fmap PLit $ compile val |
| | 371 | compile Noop = compile (Val undef) |
| | 372 | compile (Syn "block" [body]) = do |
| | 373 | cxt <- askTCxt |
| | 374 | bodyC <- compile body |
| | 375 | return $ PExp $ PApp cxt (pBlock bodyC) [] |
| | 376 | compile (Syn "sub" [Val (VCode sub)]) = do |
| | 377 | bodyC <- enter sub $ compile $ case subBody sub of |
| | 378 | Syn "block" [exp] -> exp |
| | 379 | exp -> exp |
| | 380 | paramsC <- compile $ subParams sub |
| | 381 | return $ PCode (subType sub) paramsC bodyC |
| | 382 | compile (Syn "module" _) = compile Noop |
| | 383 | compile (Syn "match" exp) = compile $ Syn "rx" exp -- wrong |
| | 384 | compile (Syn "//" exp) = compile $ Syn "rx" exp |
| | 385 | compile (Syn "rx" [exp, _]) = compile exp -- XXX WRONG - use PCRE |
| | 386 | compile (Syn "subst" [exp, _, _]) = compile exp -- XXX WRONG - use PCRE |
| | 387 | compile exp@(App _ _ _) = fmap PExp $ compile exp |
| | 388 | compile exp@(Syn _ _) = fmap PExp $ compile exp |
| | 389 | compile exp = compError exp |
| | 390 | |
| | 391 | compError :: forall a b. Compile a b => a -> Comp b |
| | 392 | compError = die $ "Compile error -- invalid " |
| | 393 | ++ (show $ typeOf (undefined :: b)) |
| | 394 | |
| | 395 | {-| Compiles a 'Val' to a 'PIL Literal'. -} |
| | 396 | instance Compile Val (PIL Literal) where |
| | 397 | compile val = return $ PVal val |
| | 398 | |
| | 399 | die :: (MonadIO m, Show a) => String -> a -> m b |
| | 400 | die x y = do |
| | 401 | warn x y |
| | 402 | liftIO $ exitFailure |
| | 403 | |
| | 404 | warn :: (MonadIO m, Show a) => String -> a -> m () |
| | 405 | warn str val = liftIO $ do |
| | 406 | hPutStrLn stderr $ "*** " ++ str ++ ":\n " ++ show val |
| | 407 | |
| | 408 | -- utility functions |
| | 409 | padSort :: (Var, [(TVar Bool, TVar VRef)]) -> (String, [(a, b)]) -> Ordering |
| | 410 | padSort (a, [(_, _)]) (b, [(_, _)]) |
| | 411 | | (head a == ':' && head b == '&') = LT |
| | 412 | | (head b == ':' && head a == '&') = GT |
| | 413 | | otherwise = GT |
| | 414 | padSort _ _ = EQ |
| | 415 | |
| | 416 | varText :: String -> Doc |
| | 417 | varText ('$':name) = text $ "s__" ++ escaped name |
| | 418 | varText ('@':name) = text $ "a__" ++ escaped name |
| | 419 | varText ('%':name) = text $ "h__" ++ escaped name |
| | 420 | varText ('&':name) = text $ "c__" ++ escaped name |
| | 421 | varText x = error $ "invalid name: " ++ x |
| | 422 | |
| | 423 | packageOf :: String -> String |
| | 424 | packageOf name = case isQualified name of |
| | 425 | Just (pkg, _) -> pkg |
| | 426 | _ -> "main" |
| | 427 | |
| | 428 | qualify :: String -> String |
| | 429 | qualify name = case isQualified name of |
| | 430 | Just _ -> name |
| | 431 | _ -> let (sigil, name') = span (not . isAlphaNum) name |
| | 432 | in sigil ++ "main::" ++ name' |
| | 433 | |
| | 434 | isQualified :: String -> Maybe (String, String) |
| | 435 | isQualified name | Just (post, pre) <- breakOnGlue "::" (reverse name) = |
| | 436 | let (sigil, pkg) = span (not . isAlphaNum) preName |
| | 437 | name' = possiblyFixOperatorName (sigil ++ postName) |
| | 438 | preName = reverse pre |
| | 439 | postName = reverse post |
| | 440 | in Just (pkg, name') |
| | 441 | isQualified _ = Nothing |