Changeset 2951
- Timestamp:
- 05/11/05 00:04:52 (4 years ago)
- svk:copy_cache_prev:
- 4498
- Location:
- src/Pugs
- Files:
-
- 5 added
- 4 modified
-
AST.hs (modified) (2 diffs)
-
AST/Internals.hs (modified) (7 diffs)
-
AST/SIO.hs (added)
-
Parser (added)
-
Parser.hs (modified) (1 diff)
-
Parser/Number.hs (added)
-
Prim.hs (modified) (9 diffs)
-
Prim/List.hs (added)
-
Prim/Numeric.hs (added)
Legend:
- Unmodified
- Added
- Removed
-
src/Pugs/AST.hs
r2950 r2951 37 37 ThunkClass(..), 38 38 39 MonadSTM(..),40 39 -- MonadEval(..), 41 40 42 run STM, runIO, runEvalSTM, runEvalIO, shiftT, resetT, runEvalMain,41 runEvalSTM, runEvalIO, shiftT, resetT, runEvalMain, 43 42 evalExp, 44 43 undef, defined, … … 63 62 doPair, doHash, doArray, 64 63 65 -- TODO: move to Pugs.Parser.NaturalOrRat66 naturalOrRat,67 68 64 module Pugs.AST.Pos, 69 65 module Pugs.AST.Scope, 66 module Pugs.AST.SIO, 70 67 ) where 68 import Pugs.Internals 71 69 72 70 import Pugs.AST.Internals 73 71 import Pugs.AST.Pos 74 72 import Pugs.AST.Scope 73 import Pugs.AST.SIO 74 75 -- |Return an infinite (lazy) Haskell list of the given string and its 76 -- successors. 'strInc' is used to determine what the \'next\' string is. 77 -- Is used to implement the @...@ infinite-range operator on strings. 78 strRangeInf :: String -> [String] 79 strRangeInf s = (s:strRangeInf (strInc s)) 80 81 -- |Return a range of strings from the first argument to the second, inclusive 82 -- (as a Haskell list). 'strInc' is used to determine what the \'next\' string 83 -- is. Is used to implement the @..@ range operator on strings. 84 strRange :: String -> String -> [String] 85 strRange s1 s2 86 | s1 == s2 = [s2] 87 | length s1 > length s2 = [] 88 | otherwise = (s1:strRange (strInc s1) s2) 89 90 -- |Find the successor of a string (i.e. the next string \'after\' it). 91 -- Special rules are used to handle strings ending in an alphanumeric 92 -- character; otherwise the last character is simply incremented using 93 -- 'charInc'. 94 strInc :: String -> String 95 strInc [] = "1" 96 strInc "z" = "aa" 97 strInc "Z" = "AA" 98 strInc "9" = "10" 99 strInc str 100 | x == 'z' = strInc xs ++ "a" 101 | x == 'Z' = strInc xs ++ "A" 102 | x == '9' = strInc xs ++ "0" 103 | otherwise = xs ++ [charInc x] 104 where 105 x = last str 106 xs = init str 107 108 -- |Return the code-point-wise successor of a given character. 109 charInc :: Char -> Char 110 charInc x = chr $ 1 + ord x 111 -
src/Pugs/AST/Internals.hs
r2950 r2951 11 11 import qualified Data.IntMap as IntMap 12 12 13 import Pugs.Parser.Number 13 14 import Pugs.AST.Pos 14 15 import Pugs.AST.Scope 16 import Pugs.AST.SIO 15 17 16 18 #include "../Types/Array.hs" … … 392 394 castV = id -- XXX not really correct; need to referencify things 393 395 394 -- |Return an infinite (lazy) Haskell list of the given string and its395 -- successors. 'strInc' is used to determine what the \'next\' string is.396 -- Is used to implement the @...@ infinite-range operator on strings.397 strRangeInf :: String -> [String]398 strRangeInf s = (s:strRangeInf (strInc s))399 400 -- |Return a range of strings from the first argument to the second, inclusive401 -- (as a Haskell list). 'strInc' is used to determine what the \'next\' string402 -- is. Is used to implement the @..@ range operator on strings.403 strRange :: String -> String -> [String]404 strRange s1 s2405 | s1 == s2 = [s2]406 | length s1 > length s2 = []407 | otherwise = (s1:strRange (strInc s1) s2)408 409 -- |Find the successor of a string (i.e. the next string \'after\' it).410 -- Special rules are used to handle strings ending in an alphanumeric411 -- character; otherwise the last character is simply incremented using412 -- 'charInc'.413 strInc :: String -> String414 strInc [] = "1"415 strInc "z" = "aa"416 strInc "Z" = "AA"417 strInc "9" = "10"418 strInc str419 | x == 'z' = strInc xs ++ "a"420 | x == 'Z' = strInc xs ++ "A"421 | x == '9' = strInc xs ++ "0"422 | otherwise = xs ++ [charInc x]423 where424 x = last str425 xs = init str426 427 -- |Return the code-point-wise successor of a given character.428 charInc :: Char -> Char429 charInc x = chr $ 1 + ord x430 431 396 intCast :: Num b => Val -> b 432 397 intCast x = fromIntegral (vCast x :: VInt) … … 905 870 newtype EvalT m a = EvalT { runEvalT :: m a } 906 871 907 data SIO a = MkSTM !(STM a) | MkIO !(IO a) | MkSIO !a908 deriving (Typeable)909 910 runSTM :: SIO a -> STM a911 runSTM (MkSTM stm) = stm912 runSTM (MkIO _ ) = fail "Unsafe IO caught in STM"913 {-914 do915 let rv = unsafePerformIO io916 trace ("*** Unsafe CALL!") return rv917 -}918 runSTM (MkSIO x) = return x919 920 runIO :: SIO a -> IO a921 runIO (MkIO io) = io922 runIO (MkSTM stm) = atomically stm923 runIO (MkSIO x) = return x924 925 872 runEvalSTM :: Env -> Eval Val -> STM Val 926 873 runEvalSTM env = runSTM . (`runReaderT` env) . (`runContT` return) . runEvalT … … 936 883 resetT e = lift . lift $ 937 884 runContT (runEvalT e) return 938 939 instance Monad SIO where940 return a = MkSIO a941 (MkIO io) >>= k = MkIO $ do { a <- io; runIO (k a) }942 (MkSTM stm) >>= k = MkSTM $ do { a <- stm; runSTM (k a) }943 (MkSIO x) >>= k = k x944 885 945 886 instance Monad EvalMonad where … … 958 899 fmap f (EvalT a) = EvalT (fmap f a) 959 900 960 class (Monad m) => MonadSTM m where961 liftSTM :: STM a -> m a962 963 901 instance MonadIO EvalMonad where 964 902 liftIO io = EvalT (liftIO io) … … 968 906 -- liftSTM stm = EvalT (lift . lift . liftSTM $ stm) 969 907 liftSTM stm = EvalT (lift . lift . liftIO . liftSTM $ stm) 970 971 instance MonadSTM STM where972 liftSTM = id973 974 instance MonadSTM IO where975 liftSTM = atomically976 977 instance MonadIO SIO where978 liftIO io = MkIO io979 980 instance MonadSTM SIO where981 liftSTM stm = MkSTM stm982 908 983 909 instance MonadReader Env EvalMonad where … … 1052 978 retError :: (Show a) => VStr -> a -> Eval b 1053 979 retError str a = fail $ str ++ ": " ++ show a 1054 1055 naturalOrRat :: GenParser Char st (Either Integer (Ratio Integer))1056 naturalOrRat = (<?> "number") $ do1057 sig <- sign1058 num <- natRat1059 return $ if sig1060 then num1061 else case num of1062 Left i -> Left $ -i1063 Right d -> Right $ -d1064 where1065 natRat = do1066 char '0'1067 zeroNumRat1068 <|> decimalRat1069 1070 zeroNumRat = do1071 n <- hexadecimal <|> decimal <|> octalBad <|> octal <|> binary1072 return (Left n)1073 <|> decimalRat1074 <|> fractRat 01075 <|> return (Left 0)1076 1077 decimalRat = do1078 n <- decimalLiteral1079 option (Left n) (try $ fractRat n)1080 1081 fractRat n = do1082 fract <- try fraction1083 expo <- option (1%1) expo1084 return (Right $ ((n % 1) + fract) * expo) -- Right is Rat1085 <|> do1086 expo <- expo1087 if expo < 11088 then return (Right $ (n % 1) * expo)1089 else return (Right $ (n % 1) * expo)1090 1091 fraction = do1092 char '.'1093 notFollowedBy . satisfy $ \x ->1094 (isAlpha x && ((x /=) `all` "eE"))1095 || ((x ==) `any` ".=")1096 digits <- many digit <?> "fraction"1097 return (digitsToRat digits)1098 <?> "fraction"1099 where1100 digitsToRat d = digitsNum d % (10 ^ length d)1101 digitsNum d = foldl (\x y -> x * 10 + (toInteger $ digitToInt y)) 0 d1102 1103 expo :: GenParser Char st Rational1104 expo = do1105 oneOf "eE"1106 f <- sign1107 e <- decimalLiteral <?> "exponent"1108 return (power (if f then e else -e))1109 <?> "exponent"1110 where1111 power e | e < 0 = 1 % (10^abs(e))1112 | otherwise = (10^e) % 11113 1114 sign = (char '-' >> return False)1115 <|> (char '+' >> return True)1116 <|> return True1117 1118 decimalLiteral = number 10 digit1119 hexadecimal = do{ char 'x'; number 16 hexDigit }1120 decimal = do{ char 'd'; number 10 digit }1121 octal = do{ char 'o'; number 8 octDigit }1122 octalBad = do{ many1 octDigit ; fail "0100 is not octal in perl6 any more, use 0o100 instead." }1123 binary = do{ char 'b'; number 2 (oneOf "01") }1124 1125 number base baseDigit1126 = do{ digits <- many1 baseDigit1127 ; let n = foldl (\x d -> base*x + toInteger (digitToInt d)) 0 digits1128 ; seq n (return n)1129 }1130 980 1131 981 -- |Evaluate the given expression, using the currently active evaluator -
src/Pugs/Parser.hs
r2944 r2951 22 22 import Pugs.Pretty 23 23 import qualified Data.Set as Set 24 25 import Pugs.Parser.Number 24 26 25 27 -- Lexical units -------------------------------------------------- -
src/Pugs/Prim.hs
r2941 r2951 20 20 import Pugs.External 21 21 import Text.Printf 22 import qualified Data.Set as Set23 22 24 23 import Pugs.Prim.Keyed … … 26 25 import Pugs.Prim.Match 27 26 import qualified Pugs.Prim.FileTest as FileTest 27 import Pugs.Prim.List 28 import Pugs.Prim.Numeric 28 29 29 30 op0 :: Ident -> [Val] -> Eval Val … … 54 55 op0 "return" = \v -> return (VError "cannot return() outside a subroutine" (Val $ VList v)) 55 56 op0 other = \_ -> fail ("Unimplemented listOp: " ++ other) 56 57 op0Zip :: [[Val]] -> [[Val]]58 op0Zip lists | all null lists = []59 op0Zip lists = (map zipFirst lists):(op0Zip (map zipRest lists))60 where61 zipFirst [] = undef62 zipFirst (x:_) = x63 zipRest [] = []64 zipRest (_:xs) = xs65 57 66 58 op1 :: Ident -> Val -> Eval Val … … 225 217 else return undef 226 218 227 op1 ('[':op) = op1Fold . init $ op219 op1 ('[':op) = op1Fold . op2 . init $ op 228 220 op1 "rand" = \v -> do 229 221 x <- fromVal v … … 431 423 op1mkType str = (VStr . showType . mkType) str 432 424 433 op1Fold :: String -> Val -> Eval Val434 op1Fold op v = do435 args <- fromVal v436 case args of437 (a:as) -> foldM (op2 op) a as438 _ -> return undef439 440 441 425 op1EvalHaskell :: Val -> Eval Val 442 426 op1EvalHaskell cv = do … … 467 451 [] -> [] 468 452 (c:cs) -> (f c:cs) 469 470 op1Pick :: Val -> Eval Val471 op1Pick (VRef r) = op1Pick =<< readRef r472 op1Pick (VList []) = return undef473 op1Pick (VList vs) = do474 rand <- liftIO $ randomRIO (0, length vs - 1)475 return $ vs !! rand476 op1Pick (VJunc (MkJunc _ _ set)) | Set.null set = return undef477 op1Pick (VJunc (MkJunc JAny _ set)) = do -- pick mainly works on 'any'478 rand <- liftIO $ randomRIO (0 :: Int, (Set.size set) - 1)479 return $ (Set.elems set) !! rand480 op1Pick (VJunc (MkJunc JNone _ _)) = return undef481 op1Pick (VJunc (MkJunc JAll _ set)) =482 if (Set.size $ set) == 1 then return $ head $ Set.elems set483 else return undef484 op1Pick (VJunc (MkJunc JOne dups set)) =485 if (Set.size $ set) == 1 && (Set.size $ dups) == 0486 then return $ head $ Set.elems set487 else return undef488 op1Pick v = return $ VError "pick not defined" (Val v)489 490 op1Sum :: Val -> Eval Val491 op1Sum list = do492 vals <- fromVal list493 foldM (op2 "+") undef vals494 453 495 454 op1Print :: (Handle -> String -> IO ()) -> Val -> Eval Val … … 834 793 return $ castV idx 835 794 836 op2Fold :: Val -> Val -> Eval Val837 op2Fold sub@(VCode _) list = op2Fold list sub838 op2Fold list sub = do839 args <- fromVal list840 if null args then return undef else do841 let doFold x y = do842 evl <- asks envEval843 local (\e -> e{ envContext = cxtItemAny }) $ do844 evl (App (Val sub) [Val x, Val y] [])845 foldM doFold (head args) (tail args)846 847 op2Grep :: Val -> Val -> Eval Val848 op2Grep sub@(VCode _) list = op2Grep list sub849 op2Grep list sub = do850 args <- fromVal list851 vals <- (`filterM` args) $ \x -> do852 evl <- asks envEval853 rv <- local (\e -> e{ envContext = cxtItem "Bool" }) $ do854 evl (App (Val sub) [Val x] [])855 fromVal rv856 return $ VList vals857 858 op2Map :: Val -> Val -> Eval Val859 op2Map sub@(VCode _) list = op2Map list sub860 op2Map list sub = do861 args <- fromVal list862 vals <- (`mapM` args) $ \x -> do863 evl <- asks envEval864 rv <- local (\e -> e{ envContext = cxtSlurpyAny }) $ do865 evl (App (Val sub) [Val x] [])866 fromVal rv867 return $ VList $ concat vals868 869 op2Join :: Val -> Val -> Eval Val870 op2Join x y = do871 (strVal, listVal) <- ifValTypeIsa x "Scalar"872 (return (x, y))873 (return (y, x))874 str <- fromVal strVal875 ref <- fromVal listVal876 list <- readRef ref877 strList <- fromVals list878 return . VStr . concat . intersperse str $ strList879 880 795 vCastStr :: Val -> Eval VStr 881 796 vCastStr = fromVal … … 996 911 EQ -> 0 997 912 GT -> 1 998 999 op1Floating :: (Double -> Double) -> Val -> Eval Val1000 op1Floating f v = do1001 foo <- fromVal v1002 return $ VNum $ f foo1003 1004 op1Numeric :: (forall a. (Num a) => a -> a) -> Val -> Eval Val1005 op1Numeric f VUndef = return . VInt $ f 01006 op1Numeric f (VInt x) = return . VInt $ f x1007 op1Numeric f l@(VList _)= fmap (VInt . f) (fromVal l)1008 op1Numeric f (VRat x) = return . VRat $ f x1009 op1Numeric f (VRef x) = op1Numeric f =<< readRef x1010 op1Numeric f x = fmap (VNum . f) (fromVal x)1011 1012 --- XXX wrong: try num first, then int, then vcast to Rat (I think)1013 op2Numeric :: (forall a. (Num a) => a -> a -> a) -> Val -> Val -> Eval Val1014 op2Numeric f x y1015 | VUndef <- x = op2Numeric f (VInt 0) y1016 | VUndef <- y = op2Numeric f x (VInt 0)1017 | (VInt x', VInt y') <- (x, y) = return $ VInt $ f x' y'1018 | (VRat x', VInt y') <- (x, y) = return $ VRat $ f x' (y' % 1)1019 | (VInt x', VRat y') <- (x, y) = return $ VRat $ f (x' % 1) y'1020 | (VRat x', VRat y') <- (x, y) = return $ VRat $ f x' y'1021 | VRef r <- x = do1022 x' <- readRef r1023 op2Numeric f x' y1024 | VRef r <- y = do1025 y' <- readRef r1026 op2Numeric f x y'1027 | otherwise = do1028 x' <- fromVal x1029 y' <- fromVal y1030 return . VNum $ f x' y'1031 913 1032 914 primOp :: String -> String -> Params -> String -> STM (Pad -> Pad) … … 1121 1003 return $ "(" ++ concat (intersperse ", " vs') ++ ")" 1122 1004 prettyVal _ v = return $ pretty v 1123 1124 sortByM :: (Val -> Val -> Eval Bool) -> [Val] -> Eval [Val]1125 sortByM _ [] = return []1126 sortByM _ [x] = return [x]1127 sortByM f xs = do1128 let (as, bs) = splitAt (length xs `quot` 2) xs1129 aSorted <- sortByM f as1130 bSorted <- sortByM f bs1131 doMerge f aSorted bSorted1132 where1133 doMerge :: (Val -> Val -> Eval Bool) -> [Val] -> [Val] -> Eval [Val]1134 doMerge _ [] ys = return ys1135 doMerge _ xs [] = return xs1136 doMerge f (x:xs) (y:ys) = do1137 isLessOrEqual <- f x y1138 if isLessOrEqual1139 then do1140 rest <- doMerge f xs (y:ys)1141 return (x:rest)1142 else do1143 rest <- doMerge f (x:xs) ys1144 return (y:rest)1145 1005 1146 1006 -- XXX -- Junctive Types -- XXX --
