Changeset 14113
- Timestamp:
- 10/09/06 17:26:24 (2 years ago)
- Location:
- src/Pugs
- Files:
-
- 11 modified
-
AST/Eval.hs (modified) (6 diffs)
-
AST/Internals.hs (modified) (8 diffs)
-
AST/Internals.hs-boot (modified) (1 diff)
-
Eval.hs (modified) (1 diff)
-
Eval/Var.hs (modified) (1 diff)
-
Internals.hs (modified) (2 diffs)
-
Monads.hs (modified) (2 diffs)
-
Parser.hs (modified) (3 diffs)
-
Parser/Unsafe.hs (modified) (1 diff)
-
Prim/List.hs (modified) (1 diff)
-
Run.hs (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
src/Pugs/AST/Eval.hs
r13592 r14113 10 10 11 11 {- Eval Monad -} 12 type Eval = EvalT ( ContT Val (ReaderT Env SIO))12 type Eval = EvalT (ErrorT Val (ReaderT Env SIO)) 13 13 newtype EvalT m a = EvalT { runEvalT :: m a } 14 14 15 15 instance ((:>:) (Eval a)) (SIO a) where cast = liftSIO 16 16 17 liftEither :: Either a a -> a 18 liftEither (Left a) = a 19 liftEither (Right a) = a 20 17 21 runEvalSTM :: Env -> Eval Val -> STM Val 18 runEvalSTM env = runSTM . (`runReaderT` enterAtomicEnv env) . (`runContT` return). runEvalT22 runEvalSTM env = fmap liftEither . runSTM . (`runReaderT` enterAtomicEnv env) . runErrorT . runEvalT 19 23 20 24 runEvalIO :: Env -> Eval Val -> IO Val 21 runEvalIO env = runIO . (`runReaderT` env) . (`runContT` return). runEvalT25 runEvalIO env = fmap liftEither . runIO . (`runReaderT` env) . runErrorT . runEvalT 22 26 23 27 tryIO :: a -> IO a -> Eval a … … 41 45 -- @esc@ is the current (sub)continuation 42 46 -> Eval a 43 shiftT e = EvalT . ContT $ \k -> 44 runContT (runEvalT . e $ lift . lift . k) return 47 shiftT f = do 48 rv <- f (error "invalid use of shiftT under ErrorT") 49 EvalT (throwError rv) 45 50 46 51 {-| … … 87 92 resetT :: Eval Val -- ^ An evaluation, possibly containing a 'shiftT' 88 93 -> Eval Val 89 resetT e = lift . lift $ 90 runContT (runEvalT e) return 94 resetT e = catchError e return 91 95 92 96 instance Monad Eval where … … 97 101 fail str = do 98 102 pos <- asks envPos' 99 shiftT . const . return $ errStrPos (cast str) pos 103 EvalT (throwError $ errStrPos (cast str) pos) 104 105 instance Error Val where 106 noMsg = errStr "" 107 strMsg = errStr 100 108 101 109 instance MonadTrans EvalT where … … 111 119 throwError err = do 112 120 pos <- asks envPos' 113 shiftT . const . return $ errValPos err pos114 catchError _ _ = fail "catchError unimplemented"121 EvalT (throwError $ errValPos err pos) 122 catchError (EvalT action) handler = EvalT (catchError action (runEvalT . handler)) 115 123 116 124 {-| … … 161 169 local f m = EvalT $ local f (runEvalT m) 162 170 171 {- 163 172 instance MonadCont Eval where 164 173 -- callCC :: ((a -> Eval b) -> Eval a) -> Eval a 165 174 callCC f = EvalT . callCCT $ \c -> runEvalT . f $ \a -> EvalT $ c a 175 -} 166 176 167 177 {- -
src/Pugs/AST/Internals.hs
r14039 r14113 10 10 InitDat(..), 11 11 12 EvalT(..), ContT(..),SubAssoc(..),12 EvalT(..), SubAssoc(..), 13 13 14 14 Pad(..), PadEntry(..), PadMutator, -- uses Var, TVar, VRef … … 53 53 transformExp, 54 54 55 runEvalSTM, runEvalIO, shiftT, resetT, ca llCC,55 runEvalSTM, runEvalIO, shiftT, resetT, catchT, 56 56 undef, defined, tryIO, guardSTM, guardIO, guardIOexcept, 57 57 readRef, writeRef, clearRef, dumpRef, forceRef, … … 76 76 newObjectId, runInvokePerl5, 77 77 78 errStr Pos, errValPos, enterAtomicEnv, valToBool, envPos', -- for circularity78 errStr, errStrPos, errValPos, enterAtomicEnv, valToBool, envPos', -- for circularity 79 79 expToEvalVal, -- Hack, should be removed once it's figured out how 80 80 … … 85 85 import Pugs.Internals 86 86 import Pugs.Types 87 import Pugs.Cont hiding (shiftT, resetT)88 87 import qualified Data.Set as Set 89 88 import qualified Data.Map as Map … … 131 130 #include "../Types/Pair.hs" 132 131 #include "../Types/Object.hs" 132 133 catchT :: ((Val -> Eval b) -> Eval Val) -> Eval Val 134 catchT action = resetT (action retShift) 133 135 134 136 {-| … … 712 714 deriving (Show, Eq, Ord, Typeable) {-!derive: YAML_Pos!-} 713 715 716 errStr :: VStr -> Val 717 errStr str = VError (VStr str) [] 718 714 719 errStrPos :: VStr -> Pos -> Val 715 720 errStrPos str pos = VError (VStr str) [pos] … … 1486 1491 1487 1492 retShift :: Val -> Eval a 1488 retShift = shiftT . const . return 1493 -- retShift = shiftT . const . return 1494 retShift = EvalT . throwError 1489 1495 1490 1496 retShiftEmpty :: Eval a 1491 retShiftEmpty = shiftT (const retEmpty) 1497 -- retShiftEmpty = shiftT (const retEmpty) 1498 retShiftEmpty = retShift =<< retEmpty 1492 1499 1493 1500 defined :: VScalar -> Bool … … 1847 1854 typeOf (MkRef x) = typeOf x 1848 1855 1849 instance Typeable1 (EvalT ( ContT Val (ReaderT Env SIO))) where1856 instance Typeable1 (EvalT (ErrorT Val (ReaderT Env SIO))) where 1850 1857 typeOf1 _ = typeOf () 1851 1858 -
src/Pugs/AST/Internals.hs-boot
r12460 r14113 24 24 25 25 envPos' :: Env -> Pos 26 errStr :: VStr -> Val 26 27 errStrPos :: VStr -> Pos -> Val 27 28 errValPos :: Val -> Pos -> Val -
src/Pugs/Eval.hs
r14079 r14113 187 187 evalRef ref = do 188 188 if refType ref == (mkType "Thunk") then forceRef ref else do 189 val <- ca llCC$ \esc -> do189 val <- catchT $ \esc -> do 190 190 MkEnv{ envContext = cxt, envLValue = lv, envClasses = cls } <- ask 191 191 let typ = typeOfCxt cxt -
src/Pugs/Eval/Var.hs
r13861 r14113 103 103 doFindVarRef :: Var -> Eval (Maybe (TVar VRef)) 104 104 doFindVarRef var = do 105 callCC $ \foundIt -> do 106 lexSym <- fmap (findSym var . envLexical) ask 107 when (isJust lexSym) $ foundIt lexSym 108 -- XXX - this is bogus; we should not fallback if it's not in lex csope. 109 glob <- liftSTM . readTVar . envGlobal =<< ask 110 var' <- toQualified var 111 let globSym = findSym var' glob 112 when (isJust globSym) $ foundIt globSym 113 -- XXX - ditto for globals 114 let globSym = findSym (toGlobalVar var) glob 115 when (isJust globSym) $ foundIt globSym 116 return Nothing 105 lexSym <- fmap (findSym var . envLexical) ask 106 if isJust lexSym then return lexSym else do 107 -- XXX - this is bogus; we should not fallback if it's not in lex csope. 108 glob <- liftSTM . readTVar . envGlobal =<< ask 109 var' <- toQualified var 110 let globSym = findSym var' glob 111 if isJust globSym then return globSym else do 112 -- XXX - ditto for globals 113 let globSym = findSym (toGlobalVar var) glob 114 if isJust globSym then return globSym else do 115 return Nothing 117 116 118 117 -
src/Pugs/Internals.hs
r14089 r14113 122 122 import Control.Monad.RWS (MonadIO(..), MonadReader(..), MonadState(..), MonadWriter(..), MonadTrans(..), asks, ReaderT(..), WriterT(..), when, join, liftM, filterM, modify, unless, gets, foldM, guard, liftM2, liftM3, fix, mplus, mappend, mzero, mconcat, msum, censor) 123 123 import Control.Monad.Identity (Identity(..)) 124 import Control.Monad.Error (MonadError(..) )124 import Control.Monad.Error (MonadError(..), ErrorT(..), Error(..)) 125 125 import Control.Concurrent 126 126 import Control.Concurrent.STM … … 153 153 154 154 import qualified UTF8 155 import qualified Judy.CollectionsM as C 155 import qualified Judy.CollectionsM as C () 156 156 import qualified Data.HashTable as H 157 157 import qualified Foreign as Foreign -
src/Pugs/Monads.hs
r14060 r14113 186 186 -> Eval Val -- ^ Result of passing the pad-transformer to the 187 187 -- \'action\' 188 genSymCC symName action = ca llCC$ \esc -> do188 genSymCC symName action = catchT $ \esc -> do 189 189 genSymPrim symName (const $ esc undef) action 190 190 … … 205 205 doFix <- fixEnv return env 206 206 local doFix runAction 207 else resetT . ca llCC$ \cc -> do207 else resetT . catchT $ \cc -> do 208 208 doFix <- fixEnv cc env 209 209 local doFix runAction -
src/Pugs/Parser.hs
r14107 r14113 783 783 imp <- option emptyExp ruleExpression 784 784 let sub = _Var $ ('&':pkg) ++ if use then "::import" else "::unimport" 785 unsafeEvalExp $ Syn "if" 785 786 Val res <- unsafeEvalExp $ Syn "if" 786 787 [ sub 787 788 , App sub (Just $ Val $ VStr $ pkg) [imp] … … 789 790 ] 790 791 791 Val (VList exportList) <- unsafeEvalExp $ case lang of792 Val (VList exportList) <- res `seq` unsafeEvalExp $ case lang of 792 793 -- map { ~$_, [::Pkg.can($_)] }, @importlist 793 794 "perl5" -> App (_Var "&map") Nothing [Syn "sub" … … 1057 1058 vcode2initBlock :: Val -> RuleParser Exp 1058 1059 vcode2initBlock code = do 1059 body <- vcode2startBlock code1060 body <- vcode2startBlock code 1060 1061 fstcode <- unsafeEvalExp $ Syn "sub" [ Val $ VCode mkSub { subBody = body } ] 1061 unsafeEvalExp $1062 Val res <- unsafeEvalExp $ 1062 1063 App (_Var "&push") (Just $ _Var "@*INIT") [ fstcode ] 1063 return $ App fstcode Nothing []1064 return (res `seq` App fstcode Nothing []) 1064 1065 1065 1066 vcode2checkBlock :: Val -> RuleParser Exp 1066 1067 vcode2checkBlock code = do 1067 body <- vcode2startBlock code1068 body <- vcode2startBlock code 1068 1069 fstcode <- unsafeEvalExp $ 1069 1070 Syn "sub" [ Val $ VCode mkSub { subBody = checkForIOLeak body } ] 1070 unsafeEvalExp $1071 Val res <- unsafeEvalExp $ 1071 1072 App (_Var "&unshift") (Just $ _Var "@*CHECK") [ fstcode ] 1072 return $ App fstcode Nothing []1073 return (res `seq` App fstcode Nothing []) 1073 1074 1074 1075 -- Constructs ------------------------------------------------ -
src/Pugs/Parser/Unsafe.hs
r13802 r14113 47 47 evl exp 48 48 case val of 49 VError _ _-> error $ pretty (val :: Val)50 _ -> return $ Val val49 VError{} -> error $ pretty (val :: Val) 50 _ -> return $ Val val 51 51 52 52 {-# NOINLINE possiblyApplyMacro #-} -
src/Pugs/Prim/List.hs
r13976 r14113 200 200 then fail 201 201 "When reducing using a chain-associative sub,\nthe sub must take exactly two arguments." 202 else ca llCC$ \esc -> do202 else catchT $ \esc -> do 203 203 let doFold' x y = do 204 204 val <- doFold [x, y] -
src/Pugs/Run.hs
r14018 r14113 273 273 runEnv env{ envBody = ast, envDebug = Nothing } 274 274 -- Right Nothing -> fail "" 275 {-# OPTIONS_GHC -fglasgow-exts #-} 276 277 {- 278 279 This needs to be redone as a proper Haskell parser, 280 which will be one of my next projects. But so far, 281 this works. 282 283 The operators are simple prefix operators 284 with zero or one argument, except for everything 285 that ultimatively goes into @ARGS for the Pugs 286 script. 287 288 If you change anything here, make sure all tests under 289 t/pugsrun/ still pass. Otherwise you might break building 290 for everybody, once you commit. 291 292 -} 293 294 -- | Command line argument parser for pugs. 295 module Pugs.Run.Args ( 296 canonicalArgs, 297 gatherArgs, 298 unpackOptions, 299 ) where 300 import Pugs.Internals 301 302 {- | 303 Convert command line arguments into canonical form for 304 'Pugs.Run.runWithArgs'. The switch ordering is defined 305 by compareArgs and is currently: 306 307 > (-h -v -V) (-I) (-d) (-w) (-c) (-C) (--external) (-M) (-n -p) (-0 -e other) 308 309 Args -M, -n and -p are converted to -e scripts by desugarDashE. 310 -} 311 canonicalArgs :: [String] -> [String] 312 canonicalArgs x = concatMap procArg 313 . concatDashE 314 . desugarDashE 315 . sortBy compareArgs 316 . gatherArgs 317 . unpackOptions 318 $ x 319 320 concatDashE :: [Arg] -> [Arg] 321 concatDashE (Opt "-e" e:xs) = (Opt "-e" $ concat (intersperse "\n" (e:map optArg es))) : rest 322 where 323 (es, rest) = partition isOptE xs 324 isOptE (Opt "-e" _) = True 325 isOptE _ = False 326 concatDashE (x:xs) = (x:concatDashE xs) 327 concatDashE xs = xs 328 329 data Arg 330 = File !String 331 | Switch !Char 332 | Opt { _optFlag :: !String, optArg :: !String } 333 deriving Show 334 335 procArg :: Arg -> [String] 336 procArg (Opt name arg) = [name, arg] 337 procArg (File name) = [name] 338 procArg (Switch name) = ['-':name:[]] 339 340 unpackOptions :: [String] -> [String] 341 unpackOptions [] = [] 342 unpackOptions (("-"):rest) = ("-":unpackOptions rest) 343 unpackOptions opts@("--":_) = opts 344 unpackOptions (('-':opt):arg:rest) 345 | takesArg opt = unpackOption opt ++ (arg:unpackOptions rest) 346 unpackOptions (('-':opt):rest) = unpackOption opt ++ unpackOptions rest 347 unpackOptions opts@[_] = opts 348 unpackOptions (filename:rest) = filename : "--" : rest 349 350 takesArg :: String -> Bool 351 takesArg xs | xs `elem` withParam = True 352 takesArg (x:xs) | x `elem` composable = takesArg xs 353 takesArg _ = False 354 355 unpackOption :: String -> [String] 356 unpackOption "" = [] -- base case for composing 357 unpackOption opt 358 | Just short <- lookup ('-':opt) longOptions = [short] 359 | head opt `elem` composable = ['-', head opt] : unpackOption (tail opt) 360 | Just (prefix, param) <- prefixOpt opt = ['-':prefix, param] 361 | otherwise = ['-':opt] 362 363 -- | List of options with long and sort variants, as tupples of long, short (with the dashes). 364 longOptions :: [(String, String)] 365 longOptions = [("--help", "-h"), ("--version", "-v")] 366 367 -- | List of options that can have their argument just after, with no space. 368 composable :: [Char] 369 composable = "cdlnpw" 370 371 -- | List of options that can take arguments 372 withParam :: [String] 373 withParam = words "e C B I M V:" 374 375 prefixOpt :: [Char] -> Maybe (String, String) 376 prefixOpt opt = msum $ map (findArg opt) withParam 377 378 findArg :: Eq a => [a] -> [a] -> Maybe ([a], [a]) 379 findArg arg prefix = do 380 param <- afterPrefix prefix arg 381 guard (not (null param)) 382 return (prefix, param) 383 384 {- 385 Enforce a canonical order of command line switches. Currently this is: 386 387 > (-h -v -V) (-I) (-d) (-w) (-c) (-C) (--external) (-M) (-n -p) (-0 -e other) 388 389 This makes pattern matching more convenient 390 391 Backwards incompatible changes: 392 393 * -p and -n autochomp. 394 395 * -p uses say() instead of print() 396 -} 397 398 compareArgs :: Arg -> Arg -> Ordering 399 compareArgs a b = compare (argRank a) (argRank b) 400 401 argRank :: Arg -> Int 402 argRank (Switch 'h') = -1 403 argRank (Switch 'v') = -1 404 argRank (Opt "-V:" _) = -1 405 argRank (Switch 'V') = -1 406 argRank (Opt "-I" _) = 0 407 argRank (Switch 'd') = 1 408 argRank (Switch 'w') = 2 409 argRank (Switch 'c') = 3 410 argRank (Opt "-C" _) = 4 411 argRank (Opt "-B" _) = 4 412 argRank (Opt "--external" _) = 5 413 argRank (Opt "-M" _) = 98 414 argRank (Switch 'n') = 99 -- translated into Perl code (later) 415 argRank (Switch 'p') = 99 -- translated into Perl code (later) 416 argRank (Switch 'l') = 100 -- translated into Perl code (later) 417 argRank (Switch '0') = 100 -- translated into Perl code (later) 418 argRank (Opt "-e" _) = 100 -- translated into Perl code 419 argRank _ = 100 -- filename or @ARGS or whatever 420 421 gatherArgs :: [String] -> [Arg] 422 gatherArgs [] = [] 423 gatherArgs ("-e":frag:rest) = [Opt "-e" frag] ++ gatherArgs(rest) 424 gatherArgs ("--external":mod:rest) = [Opt "--external" mod] ++ gatherArgs(rest) 425 gatherArgs ("-I":dir:rest) = [Opt "-I" dir] ++ gatherArgs(rest) 426 gatherArgs ("-M":mod:rest) = [Opt "-M" mod] ++ gatherArgs(rest) 427 gatherArgs ("-C":backend:rest) = [Opt "-C" backend] ++ gatherArgs(rest) 428 gatherArgs ("-B":backend:rest) = [Opt "-B" backend] ++ gatherArgs(rest) 429 gatherArgs ("-V:":item:rest) = [Opt "-V:" item] ++ gatherArgs(rest) 430 gatherArgs (('-':[]):xs) = [File "-"] ++ gatherArgs(xs) 431 gatherArgs (("--"):rest) = [File x | x <- rest] 432 gatherArgs (('-':x:[]):xs) = [Switch x] ++ gatherArgs(xs) 433 gatherArgs (x:xs) = [File x] ++ gatherArgs(xs) 434 435 {- collect "-e" switches together, 436 handle transformation of "-M", "-n" 437 and "-p" into "-e" fragments 438 -} 439 desugarDashE :: [Arg] -> [Arg] 440 desugarDashE [] = [] 441 desugarDashE ((Switch 'p'):args) = desugarDashE $ 442 (Opt "-e" "env $_; while (defined($_ = =<>)) { " : args) ++ [Opt "-e" "; say $_; }"] 443 desugarDashE ((Switch 'n'):args) = desugarDashE $ 444 (Opt "-e" "env $_; while (defined($_ = =<>)) { " : args) ++ [Opt "-e" "}"] 445 446 -- -E is like -e, but not accessible as a normal parameter and used only 447 -- internally: 448 -- "-e foo bar.pl" executes "foo" with @*ARGS[0] eq "bar.pl", 449 -- "-E foo bar.pl" executes "foo" and then bar.pl. 450 desugarDashE ((Opt "-M" mod):args) 451 | (mod', (_:args)) <- break (== '=') mod 452 = useWith $ mod' ++ " '" ++ escape args ++ "'.split(',')" 453 | otherwise 454 = useWith mod 455 where 456 useWith mod = desugarDashE ((Opt "-E" (";use " ++ mod ++ ";\n")):args) 457 escape [] = [] 458 escape ('\'':xs) = '\\':'\'':escape xs 459 escape ('\\':xs) = '\\':'\\':escape xs 460 escape (x:xs) = x:escape xs 461 462 463 -- Preserve the curious Perl5 behaviour: 464 -- perl -e 'print CGI->VERSION' -MCGI # works 465 -- perl print_cgi.pl -MCGI # fails 466 desugarDashE (x@(Opt "-e" _):y@(Opt "-E" _):args) = desugarDashE (y:x:args) 467 desugarDashE ((Opt "-E" a):y@(Opt "-e" _):args) = desugarDashE ((Opt "-e" a):y:args) 468 desugarDashE (x:xs) = (x:desugarDashE xs) 275 469 -- x -> fail $ "Error loading precompiled Prelude: " ++ show x
