packages feed

egison 3.0.0 → 3.0.1

raw patch · 12 files changed

+649/−308 lines, 12 filesdep +randomPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: random

API changes (from Hackage documentation)

- Language.Egison.Desugar: class (Applicative m, Monad m) => MonadFresh m
- Language.Egison.Desugar: fresh :: MonadFresh m => m String
- Language.Egison.Desugar: instance MonadState Int DesugarM
- Language.Egison.Types: AlgebraicDataMatcher :: [EgisonExpr] -> EgisonExpr
- Language.Egison.Types: LoopExpr :: String -> String -> EgisonExpr -> EgisonExpr -> EgisonExpr -> EgisonExpr
- Language.Egison.Types: type IOFunc = [WHNFData] -> EgisonM EgisonValue
+ Language.Egison: counter :: IORef Int
+ Language.Egison: evalEgisonTopExprs :: Env -> [EgisonTopExpr] -> IO (Either EgisonError Env)
+ Language.Egison.Core: fromArray :: WHNFData -> EgisonM [ObjectRef]
+ Language.Egison.Core: generateArray :: Env -> String -> EgisonExpr -> EgisonExpr -> EgisonM WHNFData
+ Language.Egison.Desugar: desugarPattern :: EgisonPattern -> DesugarM EgisonPattern
+ Language.Egison.Desugar: desugarTopExpr :: EgisonTopExpr -> DesugarM EgisonTopExpr
+ Language.Egison.Desugar: instance MonadFresh (ReaderT Subst (ErrorT EgisonError Fresh))
+ Language.Egison.Desugar: instance MonadReader Subst DesugarM
+ Language.Egison.Desugar: type Subst = [(String, EgisonExpr)]
+ Language.Egison.Types: AlgebraicDataMatcherExpr :: [EgisonExpr] -> EgisonExpr
+ Language.Egison.Types: Array :: (IntMap EgisonValue) -> EgisonValue
+ Language.Egison.Types: ArrayExpr :: [EgisonExpr] -> EgisonExpr
+ Language.Egison.Types: ArrayRefExpr :: EgisonExpr -> EgisonExpr -> EgisonExpr
+ Language.Egison.Types: ArraySizeExpr :: EgisonExpr -> EgisonExpr
+ Language.Egison.Types: FreshT :: StateT Int m a -> FreshT m a
+ Language.Egison.Types: GenerateArrayExpr :: [String] -> EgisonExpr -> EgisonExpr -> EgisonExpr
+ Language.Egison.Types: IArray :: (IntMap ObjectRef) -> Intermediate
+ Language.Egison.Types: IndexLoopExpr :: String -> String -> String -> EgisonExpr -> EgisonExpr -> EgisonExpr -> EgisonExpr -> EgisonExpr
+ Language.Egison.Types: IndexedExpr :: EgisonExpr -> [EgisonExpr] -> EgisonExpr
+ Language.Egison.Types: IndexedPattern :: EgisonPattern -> EgisonExpr -> EgisonPattern
+ Language.Egison.Types: Undefined :: EgisonValue
+ Language.Egison.Types: class (Applicative m, Monad m) => MonadFresh m
+ Language.Egison.Types: fresh :: MonadFresh m => m String
+ Language.Egison.Types: instance (Applicative m, Monad m) => MonadFresh (FreshT m)
+ Language.Egison.Types: instance (Monad m, Functor m) => Applicative (FreshT m)
+ Language.Egison.Types: instance Functor m => Functor (FreshT m)
+ Language.Egison.Types: instance Monad m => Monad (FreshT m)
+ Language.Egison.Types: instance Monad m => MonadState Int (FreshT m)
+ Language.Egison.Types: instance MonadError e m => MonadError e (FreshT m)
+ Language.Egison.Types: instance MonadIO (FreshT IO)
+ Language.Egison.Types: instance MonadState s m => MonadState s (FreshT m)
+ Language.Egison.Types: instance MonadTrans FreshT
+ Language.Egison.Types: liftEgisonM :: Fresh (Either EgisonError a) -> EgisonM a
+ Language.Egison.Types: newtype FreshT m a
+ Language.Egison.Types: runFresh :: Int -> Fresh a -> (a, Int)
+ Language.Egison.Types: runFreshT :: Monad m => Int -> FreshT m a -> m (a, Int)
+ Language.Egison.Types: type Fresh = FreshT Identity
+ Language.Egison.Types: unFreshT :: FreshT m a -> StateT Int m a
- Language.Egison.Core: applyFunc :: WHNFData -> [ObjectRef] -> EgisonM WHNFData
+ Language.Egison.Core: applyFunc :: WHNFData -> WHNFData -> EgisonM WHNFData
- Language.Egison.Desugar: DesugarM :: StateT Int (ErrorT EgisonError Identity) a -> DesugarM a
+ Language.Egison.Desugar: DesugarM :: ReaderT Subst (ErrorT EgisonError Fresh) a -> DesugarM a
- Language.Egison.Desugar: runDesugarM :: DesugarM a -> Either EgisonError a
+ Language.Egison.Desugar: runDesugarM :: DesugarM a -> Fresh (Either EgisonError a)
- Language.Egison.Desugar: unDesugarM :: DesugarM a -> StateT Int (ErrorT EgisonError Identity) a
+ Language.Egison.Desugar: unDesugarM :: DesugarM a -> ReaderT Subst (ErrorT EgisonError Fresh) a
- Language.Egison.Parser: readExpr :: String -> Either EgisonError EgisonExpr
+ Language.Egison.Parser: readExpr :: String -> Fresh (Either EgisonError EgisonExpr)
- Language.Egison.Parser: readExprs :: String -> Either EgisonError [EgisonExpr]
+ Language.Egison.Parser: readExprs :: String -> Fresh (Either EgisonError [EgisonExpr])
- Language.Egison.Parser: readTopExpr :: String -> Either EgisonError EgisonTopExpr
+ Language.Egison.Parser: readTopExpr :: String -> Fresh (Either EgisonError EgisonTopExpr)
- Language.Egison.Parser: readTopExprs :: String -> Either EgisonError [EgisonTopExpr]
+ Language.Egison.Parser: readTopExprs :: String -> Fresh (Either EgisonError [EgisonTopExpr])
- Language.Egison.Types: EgisonM :: ErrorT EgisonError IO a -> EgisonM a
+ Language.Egison.Types: EgisonM :: ErrorT EgisonError (FreshT IO) a -> EgisonM a
- Language.Egison.Types: IOFunc :: IOFunc -> EgisonValue
+ Language.Egison.Types: IOFunc :: (EgisonM WHNFData) -> EgisonValue
- Language.Egison.Types: PatVar :: String -> [EgisonExpr] -> EgisonPattern
+ Language.Egison.Types: PatVar :: String -> EgisonPattern
- Language.Egison.Types: VarExpr :: String -> [EgisonExpr] -> EgisonExpr
+ Language.Egison.Types: VarExpr :: String -> EgisonExpr
- Language.Egison.Types: runEgisonM :: EgisonM a -> IO (Either EgisonError a)
+ Language.Egison.Types: runEgisonM :: EgisonM a -> FreshT IO (Either EgisonError a)
- Language.Egison.Types: type PrimitiveFunc = [WHNFData] -> Either EgisonError EgisonValue
+ Language.Egison.Types: type PrimitiveFunc = [WHNFData] -> EgisonM EgisonValue
- Language.Egison.Types: type Var = (String, [Integer])
+ Language.Egison.Types: type Var = String
- Language.Egison.Types: unEgisonM :: EgisonM a -> ErrorT EgisonError IO a
+ Language.Egison.Types: unEgisonM :: EgisonM a -> ErrorT EgisonError (FreshT IO) a

Files

egison.cabal view
@@ -1,5 +1,5 @@ Name:                egison-Version:             3.0.0+Version:             3.0.1 Synopsis:            An Interpreter for the Programming Language Egison Description:         An interpreter for the programming language Egison.                      A feature of Egison is the strong pattern match facility.@@ -10,7 +10,7 @@ Homepage:            http://egison.pira.jp License:             MIT License-file:        LICENSE-Author:              Satoshi Egi, Ryo Tanaka, Takahisa Watanabe, Kentaro Honda+Author:              Satoshi Egi, Ryo Tanaka, Takahisa Watanabe Maintainer:          egisatoshi@gmail.com Category:            Compilers/Interpreters Build-type:          Simple@@ -23,7 +23,7 @@                      elisp/egison-mode.el  Library-  Build-Depends:   base >= 4.0 && < 5, array, containers, unordered-containers, haskeline, transformers, mtl, parsec >= 3.0, directory, ghc, ghc-paths, strict-io, bytestring+  Build-Depends:   base >= 4.0 && < 5, array, random, containers, unordered-containers, haskeline, transformers, mtl, parsec >= 3.0, directory, ghc, ghc-paths, strict-io, bytestring   Hs-Source-Dirs:  hs-src   Exposed-Modules:                    Language.Egison
elisp/egison-mode.el view
@@ -22,9 +22,13 @@      "\\<let\\>"      "\\<letrec\\>"      "\\<matcher\\>"+     "\\<algebraic-data-matcher\\>"      "\\<loop\\>"+     "\\<function\\>"      "\\<match\\>"      "\\<match-all\\>"+     "\\<index-loop\\>"+     "\\<pattern-constructor\\>"       "\\<undefined\\>"      "\\<something\\>"@@ -112,6 +116,7 @@ (defun keyword-indent-point (name)   (cond ((equal "define" name) 2)         ((equal "lambda" name) 2)+        ((equal "function" name) 2)         ((equal "macro" name) 2)         ((equal "let" name) 2)         ((equal "letrec" name) 2)@@ -119,7 +124,10 @@         ((equal "match" name) 2)         ((equal "match-all" name) 2)         ((equal "matcher" name) 2)+        ((equal "algebraic-data-matcher" name) 2)         ((equal "generate-array" name) 2)+        ((equal "index-loop" name) 2)+        ((equal "pattern-constructor" name) 2)         ))  (defun egison-indent-line ()
hs-src/Interpreter/egisoni.hs view
@@ -15,17 +15,74 @@ import System.Directory (getHomeDirectory) import System.FilePath ((</>)) import System.Console.Haskeline+import System.Console.GetOpt+import System.Exit (ExitCode (..), exitWith, exitFailure) import Language.Egison  main :: IO () main = do args <- getArgs-          env <- primitiveEnv >>= loadLibraries-          if null args-            then showBanner >> repl env "> "-            else do-              result <- evalEgisonTopExpr env $ (LoadFile $ args !! 0)-              either print (const $ return ()) result+          let (actions, nonOpts, _) = getOpt Permute options args+          let opts = foldl (flip id) defaultOptions actions+          case opts of+            Options {optShowHelp = True} -> printHelp+            Options {optShowVersion = True} -> printVersionNumber+            Options {optPrompt = prompt, optShowBanner = bannerFlag} -> do+                env <- primitiveEnv >>= loadLibraries+                case nonOpts of+                    [] -> when bannerFlag showBanner >> repl env prompt >> when bannerFlag showByebyeMessage+                    (file:args) -> do+                        result <- evalEgisonTopExprs env [LoadFile file, Execute args]+                        either print (const $ return ()) result +data Options = Options {+    optShowVersion :: Bool,+    optShowHelp :: Bool,+    optShowBanner :: Bool,+    optPrompt :: String+    }++defaultOptions :: Options+defaultOptions = Options {+    optShowVersion = False,+    optShowHelp = False,+    optShowBanner = True,+    optPrompt = "> "+    }++options :: [OptDescr (Options -> Options)]+options = [+  Option ['v', 'V'] ["version"]+    (NoArg (\opts -> opts {optShowVersion = True}))+    "show version number",+  Option ['h', '?'] ["help"]+    (NoArg (\opts -> opts {optShowHelp = True}))+    "show usage information",+  Option [] ["no-banner"]+    (NoArg (\opts -> opts {optShowBanner = False}))+    "show usage information",+  Option ['p'] ["prompt"]+    (ReqArg (\prompt opts -> opts {optPrompt = prompt})+            "String")+    "output file to write"+  ]++printHelp :: IO ()+printHelp = do+  putStrLn "Usage: egison [options] file"+  putStrLn ""+  putStrLn "Options:"+  putStrLn "  --help                Display this information"+  putStrLn "  --version             Display egison version information"+  putStrLn "  --no-banner           Don't show banner"+  putStrLn "  --prompt string       Set prompt of the interpreter"+  putStrLn ""+  exitWith ExitSuccess++printVersionNumber :: IO ()+printVersionNumber = do+  putStrLn $ showVersion version +  exitWith ExitSuccess+ showBanner :: IO () showBanner = do   putStrLn $ "Egison Version " ++ showVersion version ++ " (C) 2011-2013 Satoshi Egi"@@ -48,8 +105,8 @@     loop env prompt' rest = do       input <- getInputLine prompt'       case input of-        Nothing -> liftIO showByebyeMessage >> return ()-        Just "quit" -> liftIO showByebyeMessage >> return ()+        Nothing -> return () +        Just "quit" -> return ()          Just "" ->  loop env prompt ""         Just input' -> do           let newInput = rest ++ input'
hs-src/Language/Egison.hs view
@@ -3,16 +3,20 @@        ( module Language.Egison.Types        , module Language.Egison.Parser        , module Language.Egison.Primitives+       , counter --danger        , version        , loadLibraries        , loadPrimitives        , runEgisonTopExpr        , evalEgisonTopExpr+       , evalEgisonTopExprs        ) where  import Control.Applicative ((<$>), (<*>)) import Control.Monad.Error +import System.IO.Unsafe (unsafePerformIO)+import Data.IORef import Data.Version import Data.ByteString.Lazy (ByteString) import Data.ByteString.Lazy.Char8 ()@@ -26,12 +30,19 @@ import Language.Egison.Parser import Language.Egison.Primitives +-- Unsafe+counter :: IORef Int+counter = unsafePerformIO (newIORef 0)++ version :: Version version = P.version  loadLibraries :: Env -> IO Env loadLibraries env = do-  result <- runEgisonM $ foldM evalTopExpr env (map Load libraries)+  seed <- readIORef counter+  (result, seed') <- runFreshT seed $ runEgisonM $ foldM evalTopExpr env (map Load libraries)+  writeIORef counter seed'   case result of     Left err -> do       print . show $ err@@ -49,9 +60,24 @@ loadPrimitives env = (++) <$> return env <*> primitiveEnv  runEgisonTopExpr :: Env -> String -> IO (Either EgisonError Env)-runEgisonTopExpr env input = runEgisonM $ do -  expr <- liftError $ readTopExpr input-  evalTopExpr env expr+runEgisonTopExpr env input = do+  seed <- readIORef counter+  (result, seed') <- runFreshT seed $ runEgisonM $ do +    expr <- liftEgisonM $ readTopExpr input+    evalTopExpr env expr+  writeIORef counter seed'+  return result  evalEgisonTopExpr :: Env -> EgisonTopExpr -> IO (Either EgisonError Env)-evalEgisonTopExpr env expr = runEgisonM $ evalTopExpr env expr+evalEgisonTopExpr env expr = do+  seed <- readIORef counter+  (result, seed') <- runFreshT seed $ runEgisonM $ evalTopExpr env expr+  writeIORef counter seed'+  return result++evalEgisonTopExprs :: Env -> [EgisonTopExpr] -> IO (Either EgisonError Env)+evalEgisonTopExprs env exprs = do+  seed <- readIORef counter+  (result, seed') <- runFreshT seed $ runEgisonM $ foldM evalTopExpr env exprs+  writeIORef counter seed'+  return result
hs-src/Language/Egison/Core.hs view
@@ -10,6 +10,12 @@ import Data.List import Data.Maybe +import Data.HashMap.Strict (HashMap)+import qualified Data.HashMap.Strict as HashMap++import Data.IntMap (IntMap)+import qualified Data.IntMap as IntMap+ import Text.Parsec.ByteString.Lazy (parseFromFile) import System.Directory (doesFileExist) @@ -39,11 +45,11 @@   liftIO $ print val   return env evalTopExpr env (Execute argv) = do-  main <- refVar env ("main", []) >>= evalRef-  argv <- newEvaluatedThunk . Value . Collection $ map String argv-  world <- newEvaluatedThunk $ Value World-  applyFunc main [argv] >>= flip applyFunc [world]-  return env+  main <- refVar env "main" >>= evalRef+  io <- applyFunc main $ Value $ Collection $ map String argv+  case io of+    Value (IOFunc m) -> m >> return env+    _ -> throwError $ TypeMismatch "io" main evalTopExpr env (Load file) = loadLibraryFile file >>= evalTopExprs env evalTopExpr env (LoadFile file) = loadFile file >>= evalTopExprs env @@ -52,7 +58,7 @@   doesExist <- liftIO $ doesFileExist file   unless doesExist $ throwError $ strMsg ("file does not exist: " ++ file)   input <- liftIO $ readFile file-  exprs <- liftError $ readTopExprs input+  exprs <-  liftEgisonM $ readTopExprs input   concat <$> mapM recursiveLoad exprs  where   recursiveLoad (Load file) = loadFile file@@ -69,11 +75,9 @@ evalExpr _ (IntegerExpr i) = return . Value $ Integer i evalExpr _ (FloatExpr d) = return . Value $ Float d -evalExpr env (VarExpr name nums) = do-  var <- (,) name <$> mapM (evalExpr env >=> liftError . fromIntegerValue) nums-  refVar env var >>= evalRef+evalExpr env (VarExpr name) = refVar env name >>= evalRef -evalExpr env (InductiveDataExpr name []) = return . Value $ InductiveData name []+evalExpr _ (InductiveDataExpr name []) = return . Value $ InductiveData name [] evalExpr env (InductiveDataExpr name exprs) =   Intermediate . IInductiveData name <$> mapM (newThunk env) exprs  @@ -82,13 +86,34 @@ evalExpr env (TupleExpr exprs) =   Intermediate . ITuple <$> mapM (newThunk env) exprs  -evalExpr env (CollectionExpr []) = return . Value $ Collection []+evalExpr _ (CollectionExpr []) = return . Value $ Collection [] evalExpr env (CollectionExpr inners) =   Intermediate . ICollection <$> mapM fromInnerExpr inners  where   fromInnerExpr (ElementExpr expr) = IElement <$> newThunk env expr   fromInnerExpr (SubCollectionExpr expr) = ISubCollection <$> newThunk env expr +evalExpr env (ArrayExpr exprs) = do+  ref' <- mapM (newThunk env) exprs+  return . Intermediate . IArray $ IntMap.fromList $ zip (enumFromTo 1 (length exprs)) ref'++evalExpr env (IndexedExpr expr indices) = do+  array <- evalExpr env expr+  indices <- mapM (evalExpr env >=> liftError . liftM fromInteger . fromIntegerValue) indices+  refArray array indices+ where+  refArray :: WHNFData -> [Int] -> EgisonM WHNFData+  refArray val [] = return val +  refArray (Value (Array array)) (index:indices) =+    case IntMap.lookup index array of+      Just val -> refArray (Value val) indices+      Nothing -> return $ Value Undefined+  refArray (Intermediate (IArray array)) (index:indices) =+    case IntMap.lookup index array of+      Just ref -> evalRef ref >>= flip refArray indices+      Nothing -> return $ Value Undefined+  refArray val _ = throwError $ TypeMismatch "array" val+ evalExpr env (LambdaExpr names expr) = return . Value $ Func env names expr   evalExpr env (IfExpr test expr expr') = do@@ -113,21 +138,30 @@   extractBindings (names, expr) = do     var <- genVar     let k = length names-        target = VarExpr var []+        target = VarExpr var         matcher = TupleExpr $ replicate k SomethingExpr         nth n =           let pattern = TupleExpr $ flip map [1..k] $ \i ->                 if i == n-                  then PatternExpr $ PatVar "#_" []+                  then PatternExpr $ PatVar "#_"                   else PatternExpr WildCard-          in MatchExpr target matcher [(pattern, VarExpr "#_" [])]+          in MatchExpr target matcher [(pattern, VarExpr "#_")]     return ((var, expr) : map (second nth) (zip names [1..]))    genVar :: State Int String   genVar = modify (1+) >> gets (('#':) . show) +evalExpr env (DoExpr bindings expr) = return $ Value $ IOFunc $ do+  let body = foldr genLet (TupleExpr [VarExpr "#1", expr]) bindings+  applyFunc (Value $ Func env ["#1"] body) $ Value World+ where+  genLet (names, expr) expr' =+    LetExpr [(["#1", "#2"], ApplyExpr expr $ TupleExpr [VarExpr "#1"])] $+    LetExpr [(names, VarExpr "#2")] expr'+ evalExpr env (MatchAllExpr target matcher (pattern, expr)) = do   target <- newThunk env target+     matcher <- evalExpr env matcher   result <- patternMatch env pattern target matcher   mmap (flip evalExpr expr . extendEnv env) result >>= fromMList@@ -150,19 +184,33 @@   foldr tryMatchClause (throwError $ strMsg "failed pattern match") clauses  evalExpr env (FunctionExpr matcher clauses) =-  return . Value $ Func env ["#_"] (MatchExpr (VarExpr "#_" []) matcher clauses)+  return . Value $ Func env ["#_"] (MatchExpr (VarExpr "#_") matcher clauses) -evalExpr env (ApplyExpr func args) = do+evalExpr env (ApplyExpr func arg) = do   func <- evalExpr env func-  args <- evalExpr env args >>= fromTuple -  applyFunc func args+  arg <- evalExpr env arg+  applyFunc func arg  evalExpr env (MatcherExpr info) = return $ Value $ Matcher (env, info) +evalExpr env (GenerateArrayExpr (name:[]) (TupleExpr (size:[])) expr) =+  generateArray env name size expr+evalExpr env (GenerateArrayExpr (name:xs) (TupleExpr (size:ys)) expr) = +  generateArray env name size (GenerateArrayExpr xs (TupleExpr ys) expr)+evalExpr _ (GenerateArrayExpr _ _ _) = throwError $ strMsg "invalid generate-array expression"++evalExpr env (ArraySizeExpr expr) = +  evalExpr env expr >>= arraySize+  where+    arraySize :: WHNFData -> EgisonM WHNFData+    arraySize (Intermediate (IArray vals)) = return . Value . Integer . toInteger $ IntMap.size vals+    arraySize (Value (Array vals))         = return . Value . Integer . toInteger $ IntMap.size vals+    arraySize val                          = throwError $ TypeMismatch "array" val+ evalExpr _ (PatternExpr pattern) = return $ Value $ Pattern pattern  evalExpr _ SomethingExpr = return $ Value Something-evalExpr _ UndefinedExpr = throwError $ strMsg "undefined"+evalExpr _ UndefinedExpr = return $ Value Undefined evalExpr _ expr = throwError $ NotImplemented ("evalExpr for " ++ show expr)  evalExpr' :: Env -> EgisonExpr -> EgisonM EgisonValue@@ -196,21 +244,45 @@ evalDeep (Value val) = return val evalDeep (Intermediate (IInductiveData name refs)) =   InductiveData name <$> mapM evalRef' refs+evalDeep (Intermediate (IArray refs)) = do+  refs' <- mapM evalRef' $ IntMap.elems refs+  return $ Array $ IntMap.fromList $ zip (enumFromTo 1 (IntMap.size refs)) refs' evalDeep (Intermediate (ITuple refs)) = Tuple <$> mapM evalRef' refs evalDeep coll = Collection <$> (fromCollection coll >>= fromMList >>= mapM evalRef') -applyFunc :: WHNFData -> [ObjectRef] -> EgisonM WHNFData-applyFunc (Value (Func env names body)) args-  | length names == length args =-    let env' = extendEnv env $ makeBindings names args-    in evalExpr env' body-  | otherwise = throwError $ ArgumentsNum (length names) (length args)-applyFunc (Value (PrimitiveFunc func)) args =-  mapM evalRef args >>= liftM Value . liftError . func-applyFunc (Value (IOFunc func)) args =-  mapM evalRef args >>= liftM Value . func+applyFunc :: WHNFData -> WHNFData -> EgisonM WHNFData+applyFunc (Value (Func env [name] body)) arg = do+  ref <- newEvaluatedThunk arg+  evalExpr (extendEnv env $ makeBindings [name] [ref]) body+applyFunc (Value (Func env names body)) arg = do+  refs <- fromTuple arg+  if length names == length refs+    then evalExpr (extendEnv env $ makeBindings names refs) body+    else throwError $ ArgumentsNum (length names) (length refs)+applyFunc (Value (PrimitiveFunc func)) arg =+  fromTuple arg >>= mapM evalRef >>= liftM Value . func+applyFunc (Value (IOFunc m)) arg = do+  case arg of+     Value World -> m+     _ -> throwError $ TypeMismatch "world" arg applyFunc val _ = throwError $ TypeMismatch "function" val +generateArray :: Env -> String -> EgisonExpr -> EgisonExpr -> EgisonM WHNFData+generateArray env name size expr = do  +  size' <- evalExpr env size >>= either throwError (return . fromInteger) . fromIntegerValue+  elems <- mapM genElem (enumFromTo 1 size')+  return $ Intermediate $ IArray $ IntMap.fromList elems+  where+    genElem :: Int -> EgisonM (Int, ObjectRef)+    genElem i = do env <- bindEnv env name $ toInteger i+                   val <- evalExpr env expr >>= newEvaluatedThunk                   +                   return (i, val)+    +    bindEnv :: Env -> String -> Integer -> EgisonM Env+    bindEnv env name i = do+      ref <- liftIO $ newIORef (WHNF . Value . Integer $ i)+      return $ extendEnv env [(name, ref)]+ newThunk :: Env -> EgisonExpr -> EgisonM ObjectRef newThunk env expr = liftIO . newIORef . Thunk $ evalExpr env expr @@ -221,7 +293,7 @@ newEvaluatedThunk = liftIO . newIORef . WHNF  makeBindings :: [String] -> [ObjectRef] -> [Binding]-makeBindings = zip . map (flip (,) [])+makeBindings = zip  recursiveBind :: Env -> [(String, EgisonExpr)] -> EgisonM Env recursiveBind env bindings = do@@ -231,6 +303,11 @@   zipWithM_ (\ref expr -> liftIO . writeIORef ref . Thunk $ evalExpr env' expr) refs exprs   return env' +fromArray :: WHNFData -> EgisonM [ObjectRef]+fromArray (Intermediate (IArray refs)) = return $ IntMap.elems refs+fromArray (Value (Array vals)) = mapM (newEvaluatedThunk . Value) $ IntMap.elems vals+fromArray val = throwError $ TypeMismatch "array" val+ fromTuple :: WHNFData -> EgisonM [ObjectRef] fromTuple (Intermediate (ITuple refs)) = return refs fromTuple (Value (Tuple vals)) = mapM (newEvaluatedThunk . Value) vals@@ -279,14 +356,44 @@   let env' = extendEnv env bindings   pattern <- evalPattern env' pattern   case pattern of-    VarExpr _ _ -> throwError $ strMsg "cannot use variable in pattern"-    ApplyExpr func (TupleExpr args) -> do+    VarExpr _ -> throwError $ strMsg "cannot use variable in pattern"+    ApplyExpr func arg -> do       func <- evalExpr env' func       case func of+        Value (Func env [name] expr) -> do+          penv <- (:[]) . (,) name <$> evalPattern env' arg+          return $ msingleton $ MState env bindings (MNode penv (MState env [] [MAtom expr target matcher]) : trees)         Value (Func env names expr) -> do-          penv <- zip (map (flip (,) []) names) <$> mapM (evalPattern env') args+          let args = case arg of+                       TupleExpr exprs -> exprs+                       expr -> [expr]+          penv <- zip names <$> mapM (evalPattern env') args           return $ msingleton $ MState env bindings (MNode penv (MState env [] [MAtom expr target matcher]) : trees)         _ -> throwError $ TypeMismatch "pattern constructor" func+    IndexedExpr (PatternExpr (PatVar name)) indices -> do+      indices <- mapM (evalExpr env' >=> liftError . liftM fromInteger . fromIntegerValue) indices+      let (index:_) = indices +      case lookup name bindings of+        Just ref -> do+          val <- evalRef ref+          case val of+            Intermediate (IArray val) -> do+              obj <- newEvaluatedThunk $ Intermediate . IArray $ IntMap.insert index target val+              return $ msingleton $ MState env (subst name obj bindings) trees+            Value (Array val) -> do+              keys' <- return $ IntMap.keys val+              vals' <- mapM (newEvaluatedThunk . Value) $ IntMap.elems val+              obj <- newEvaluatedThunk $ Intermediate . IArray $ IntMap.insert index target (IntMap.fromList $ zip keys' vals')+              return $ msingleton $ MState env (subst name obj bindings) trees+        Nothing  -> do+          obj <- newEvaluatedThunk $ Intermediate . IArray $ IntMap.singleton index target +          return $ msingleton $ MState env ((name, obj):bindings) trees+       where+        subst :: (Eq a) => a -> b -> [(a, b)] -> [(a, b)]+        subst k nv ((k', v'):xs) | k == k'   = (k', nv):(subst k nv xs)+                                 | otherwise = (k', v'):(subst k nv xs)+        subst _ _ [] = []+    IndexedExpr expr index -> throwError $ strMsg ("invalid indexed-pattern: " ++ show expr)      TupleExpr patterns -> do       matchers <- fromTuple matcher >>= mapM evalRef       targets <- evalRef target >>= fromTuple@@ -307,16 +414,17 @@     PatternExpr (CutPat pattern) -> -- TEMPORARY ignoring cut patterns       return $ msingleton (MState env bindings ((MAtom pattern target matcher):trees))     PatternExpr (PredPat pred) -> do-      result <- evalExpr env' pred >>= flip applyFunc [target] >>= liftError . fromBoolValue+      func <- evalExpr env' pred+      arg <- evalRef target+      result <- applyFunc func arg >>= liftError . fromBoolValue       if result then return $ msingleton $ (MState env bindings trees)                 else return MNil     PatternExpr pattern' ->       case matcher of         Value Something ->            case pattern' of-            PatVar name nums -> do-              var <- (,) name <$> mapM (evalExpr env' >=> liftError . fromIntegerValue) nums-              return $ msingleton $ MState env ((var, target):bindings) trees+            PatVar name -> do+              return $ msingleton $ MState env ((name, target):bindings) trees             _ -> throwError $ strMsg "something can only match with a pattern variable"         Value (Matcher matcher) -> do           (patterns, targetss, matchers) <- inductiveMatch env' pattern target matcher@@ -325,32 +433,40 @@             let trees' = zipWith3 MAtom patterns targets matchers ++ trees             return $ MState env bindings trees'         _ -> throwError $ TypeMismatch "matcher" matcher+    _ -> throwError $ strMsg "should not reach here" processMState (MState env bindings ((MNode penv (MState _ _ [])):trees)) =   return $ msingleton $ MState env bindings trees processMState (MState env bindings ((MNode penv state@(MState env' bindings' (tree:trees')):trees))) = do+  let env'' = extendEnv env' bindings   case tree of     MAtom pattern target matcher -> do-      pattern <- evalPattern env' pattern+      pattern <- evalPattern env'' pattern       case pattern of-        VarExpr name nums -> do-          var <- (,) name <$> mapM (evalExpr env' >=> liftError . fromIntegerValue) nums-          case lookup var penv of-            Just pattern -> do+        VarExpr name ->+          case lookup name penv of+            Just pattern ->               return $ msingleton $ MState env bindings (MAtom pattern target matcher:MNode penv (MState env' bindings' trees'):trees)-            Nothing -> throwError $ UnboundVariable var+            Nothing -> throwError $ UnboundVariable name+        IndexedExpr (VarExpr name) (index:_) ->+          case lookup name penv of+            Just pattern -> do+              index <- evalExpr env'' index >>= liftError . fromIntegerValue+              let pattern' = IndexedExpr pattern [IntegerExpr index]+              return $ msingleton $ MState env bindings (MAtom pattern' target matcher:MNode penv (MState env' bindings' trees'):trees)+            Nothing -> throwError $ UnboundVariable name         _ -> processMState state >>= mmap (return . MState env bindings . (: trees) . MNode penv)     _ -> processMState state >>= mmap (return . MState env bindings . (: trees) . MNode penv)  evalPattern :: Env -> EgisonExpr -> EgisonM EgisonExpr+evalPattern _ (TupleExpr [expr]) = return expr evalPattern _ expr@(TupleExpr _) = return expr evalPattern _ expr@(PatternExpr _) = return expr-evalPattern _ expr@(VarExpr _ _) = return expr+evalPattern _ expr@(VarExpr _) = return expr+evalPattern _ expr@(IndexedExpr _ _) = return expr evalPattern _ expr@(ApplyExpr _ _) = return expr evalPattern env (IfExpr test expr expr') = do   test <- evalExpr env test >>= liftError . fromBoolValue   evalPattern env $ if test then expr else expr'  -evalPattern env (LetExpr _ _) = undefined-evalPattern env (LetRecExpr _ _) = undefined evalPattern _ _ = throwError $ strMsg "pattern expression required"  inductiveMatch :: Env -> EgisonExpr -> ObjectRef -> Matcher ->@@ -382,22 +498,22 @@ primitivePatPatternMatch _ PPWildCard _ = return ([], []) primitivePatPatternMatch _ PPPatVar pattern = return ([pattern], []) primitivePatPatternMatch env (PPValuePat name) pattern = do-  pattern <- lift $ evalExpr env pattern+  pattern <- lift $ evalPattern env pattern   case pattern of-    Value (Pattern (ValuePat expr)) -> do+    PatternExpr (ValuePat expr) -> do       ref <- lift $ newThunk env expr-      return ([], [((name, []), ref)])+      return ([], [(name, ref)])     _ -> matchFail primitivePatPatternMatch env (PPInductivePat name patterns) pattern = do-  pattern <- lift $ evalExpr env pattern+  pattern <- lift $ evalPattern env pattern   case pattern of-    Value (Pattern (InductivePattern name' exprs)) | name == name' ->+    PatternExpr (InductivePattern name' exprs) | name == name' ->       (concat *** concat) . unzip <$> zipWithM (primitivePatPatternMatch env) patterns exprs     _ -> matchFail  primitiveDataPatternMatch :: PrimitiveDataPattern -> ObjectRef -> MatchM [Binding] primitiveDataPatternMatch PDWildCard _ = return []-primitiveDataPatternMatch (PDPatVar name) ref = return [((name, []), ref)]+primitiveDataPatternMatch (PDPatVar name) ref = return [(name, ref)] primitiveDataPatternMatch (PDInductivePat name patterns) ref = do   val <- lift $ evalRef ref   case val of@@ -449,15 +565,15 @@   unconsCollection' (Value (Collection (val:vals))) =     lift $ (,) <$> newEvaluatedThunk (Value val)                <*> newEvaluatedThunk (Value $ Collection vals)-  unconsCollection' (Intermediate (ICollection ((IElement ref):inners))) =-    lift $ (,) ref <$> newEvaluatedThunk (Intermediate $ ICollection inners)+  unconsCollection' (Intermediate (ICollection ((IElement ref'):inners))) =+    lift $ (,) ref' <$> newEvaluatedThunk (Intermediate $ ICollection inners)   unconsCollection' (Intermediate (ICollection ((ISubCollection ref'):inners))) = do     inners' <- lift $ evalRef ref' >>= expandCollection     let coll = Intermediate (ICollection (inners' ++ inners))     lift $ writeThunk ref coll     unconsCollection' coll   unconsCollection' _ = matchFail-  + unsnocCollection :: ObjectRef -> MatchM (ObjectRef, ObjectRef) unsnocCollection ref = lift (evalRef ref) >>= unsnocCollection'   where@@ -469,11 +585,11 @@     unsnocCollection' (Intermediate (ICollection [])) = matchFail     unsnocCollection' (Intermediate (ICollection inners)) =       case last inners of-        IElement ref ->+        IElement ref' ->           lift $ (,) <$> newEvaluatedThunk (Intermediate . ICollection $ init inners)-                     <*> pure ref-        ISubCollection ref -> do-          inners' <- lift $ evalRef ref >>= expandCollection+                     <*> pure ref'+        ISubCollection ref' -> do+          inners' <- lift $ evalRef ref' >>= expandCollection           let coll = Intermediate (ICollection (init inners ++ inners'))           lift $ writeThunk ref coll           unsnocCollection' coll
hs-src/Language/Egison/Desugar.hs view
@@ -5,29 +5,35 @@ import Data.Char (toUpper) import Control.Monad.Error import Control.Monad.State+import Control.Monad.Reader import Control.Monad.Identity import Language.Egison.Types -newtype DesugarM a = DesugarM { unDesugarM :: StateT Int (ErrorT EgisonError Identity) a }-  deriving (Functor, Applicative, Monad, MonadState Int, MonadError EgisonError)-           -class (Applicative m, Monad m) => MonadFresh m where-  fresh :: m String-           -instance MonadFresh DesugarM where-  fresh = do counter <- get; modify (+ 1) -             return $ genFreshName counter-    where-      genFreshName :: Int -> String-      genFreshName n = "$_" ++ show n+type Subst = [(String, EgisonExpr)] -runDesugarM :: DesugarM a -> Either EgisonError a-runDesugarM d =runIdentity $ runErrorT $ flip evalStateT 0 $ unDesugarM d+newtype DesugarM a = DesugarM { unDesugarM :: ReaderT Subst (ErrorT EgisonError Fresh) a }+  deriving (Functor, Applicative, Monad, MonadError EgisonError, MonadFresh, MonadReader Subst) +instance MonadFresh (ReaderT Subst (ErrorT EgisonError Fresh)) where+  fresh = lift $ lift $ fresh++runDesugarM :: DesugarM a -> Fresh (Either EgisonError a)+runDesugarM = runErrorT . flip runReaderT [] . unDesugarM++desugarTopExpr :: EgisonTopExpr -> DesugarM EgisonTopExpr+desugarTopExpr (Define name expr) = do+  expr' <- desugar expr+  return (Define name expr')+desugarTopExpr (Test expr) = do+  expr' <- desugar expr+  return (Test expr')+desugarTopExpr expr = return expr++ desugar :: EgisonExpr -> DesugarM EgisonExpr-desugar (AlgebraicDataMatcher patterns) = do+desugar (AlgebraicDataMatcherExpr patterns) = do   matcherName <- fresh-  matcherRef <- return $ VarExpr matcherName []+  matcherRef <- return $ VarExpr matcherName   matcher <- genMatcherClauses patterns matcherRef   return $ LetRecExpr [([matcherName], matcher)] matcherRef     where@@ -43,7 +49,7 @@       genMainClause patterns matcher = do         clauses <- genClauses patterns         return (PPValuePat "val", TupleExpr [],-                 [(PDPatVar "tgt", (MatchExpr (TupleExpr [(VarExpr "val" []), (VarExpr "tgt" [])]) +                 [(PDPatVar "tgt", (MatchExpr (TupleExpr [(VarExpr "val"), (VarExpr "tgt")])                                                (TupleExpr [matcher, matcher])                                                clauses))])         where@@ -59,8 +65,8 @@           genMatchingPattern :: EgisonExpr -> DesugarM (EgisonExpr, EgisonExpr)           genMatchingPattern (PatternExpr (InductivePattern name patterns)) = do             names <- mapM (const fresh) patterns-            return $ ((PatternExpr $ InductivePattern name (map (PatternExpr . flip PatVar []) names))  -                     ,(PatternExpr $ InductivePattern name (map (PatternExpr . ValuePat . (flip VarExpr [])) names)))+            return $ ((PatternExpr $ InductivePattern name (map (PatternExpr . PatVar) names))  +                     ,(PatternExpr $ InductivePattern name (map (PatternExpr . ValuePat . VarExpr) names)))                  genMatcherClause :: EgisonExpr -> DesugarM (PrimitivePatPattern, EgisonExpr, [(PrimitiveDataPattern, EgisonExpr)])       genMatcherClause pattern = do@@ -78,7 +84,7 @@           genPrimitiveDataPat :: EgisonExpr -> DesugarM (PrimitiveDataPattern, [EgisonExpr])           genPrimitiveDataPat (PatternExpr (InductivePattern name patterns)) = do             patterns' <- mapM (const fresh) patterns -            return (PDInductivePat (capitalize name) $ map PDPatVar patterns', map (flip VarExpr []) patterns')+            return (PDInductivePat (capitalize name) $ map PDPatVar patterns', map VarExpr patterns')           genPrimitiveDataPatr _ = throwError $ Desugar "invalid algebraic-data-matcher"            capitalize :: String -> String@@ -87,7 +93,7 @@              genSomethingClause :: DesugarM (PrimitivePatPattern, EgisonExpr, [(PrimitiveDataPattern, EgisonExpr)])       genSomethingClause = -        return (PPPatVar, (TupleExpr [SomethingExpr]), [(PDPatVar "tgt", CollectionExpr $ [ElementExpr (VarExpr "tgt" [])])])+        return (PPPatVar, (TupleExpr [SomethingExpr]), [(PDPatVar "tgt", CollectionExpr $ [ElementExpr (VarExpr "tgt")])])            matchingSuccess :: EgisonExpr       matchingSuccess = CollectionExpr $ [ElementExpr $ TupleExpr []]@@ -99,12 +105,17 @@   name <- fresh   matcher' <- desugar matcher   clauses' <- desugarMatchClauses clauses-  desugar (LambdaExpr [name] (MatchExpr (VarExpr name []) matcher' clauses'))+  desugar (LambdaExpr [name] (MatchExpr (VarExpr name) matcher' clauses')) -desugar (VarExpr name exprs) = do-  exprs' <- mapM desugar exprs-  return $ VarExpr name exprs'+desugar (ArrayRefExpr (VarExpr name) (TupleExpr nums)) =+  desugar $ IndexedExpr (VarExpr name) nums+  +desugar (ArrayRefExpr expr nums) =+  desugar $ ArrayRefExpr expr (TupleExpr [nums]) +desugar (IndexedExpr expr indices) = +  IndexedExpr <$> desugar expr <*> (mapM desugar indices)+ desugar (InductiveDataExpr name exprs) = do    exprs' <- mapM desugar exprs   return $ InductiveDataExpr name exprs'@@ -145,11 +156,25 @@   expr' <- desugar expr   return $ LetRecExpr binds' expr'   -desugar (LoopExpr s0 s1 expr0 expr1 expr2) = do-  expr0' <- desugar expr0-  expr1' <- desugar expr1-  expr2' <- desugar expr2-  return $ LoopExpr s0 s1 expr0' expr1' expr2'+desugar (IndexLoopExpr n0 n1 n2 expr0 expr1 expr2 expr3) = do+  name <- fresh+  helper <- genHelper name+  return $ ApplyExpr (LetRecExpr [([name], helper)] (ApplyExpr (VarExpr name) expr1)) expr0+ where+  genHelper :: String -> DesugarM EgisonExpr+  genHelper name = do+    indicesName <- fresh+    patName <- fresh+    let subst = [(n0, ApplyExpr (ApplyExpr (VarExpr name) (VarExpr indicesName)) (VarExpr patName)), (n1, VarExpr patName)]+    bodyExpr <- local (subst ++) $ desugar expr2+    initExpr <- desugar expr3+    let matchClauses = [ (PatternExpr $ InductivePattern "nil" [], LambdaExpr [patName] $ initExpr)+                       , (PatternExpr $ InductivePattern "cons" [PatternExpr (PatVar n2), PatternExpr (PatVar indicesName)], LambdaExpr [patName] $ bodyExpr)]+    return $ LambdaExpr [indicesName] $ MatchExpr (VarExpr indicesName) matcher matchClauses++  matcher :: EgisonExpr+  matcher = ApplyExpr (VarExpr "list") SomethingExpr+         desugar (MatchExpr expr0 expr1 clauses) = do     expr0' <- desugar expr0@@ -163,6 +188,9 @@   clause' <- desugarMatchClause clause   return $ MatchAllExpr expr0' expr1' clause'   +desugar (PatternExpr pattern) =+  PatternExpr <$> desugarPattern pattern+   desugar (DoExpr binds expr) = do   binds' <- desugarBindings binds   expr' <- desugar expr@@ -172,9 +200,25 @@   expr0' <- desugar expr0   expr1' <- desugar expr1   return $ ApplyExpr expr0' expr1'++desugar (VarExpr name) = do+  asks $ maybe (VarExpr name) id . lookup name    desugar expr = return expr +desugarPattern :: EgisonPattern -> DesugarM EgisonPattern+desugarPattern (ValuePat expr) = ValuePat <$> desugar expr+desugarPattern (PredPat expr) = PredPat <$> desugar expr+desugarPattern (CutPat expr) = CutPat <$> desugar expr+desugarPattern (NotPat expr) = NotPat <$> desugar expr+desugarPattern (AndPat exprs) = AndPat <$> mapM desugar exprs+desugarPattern (OrPat exprs)  = OrPat <$> mapM desugar exprs+desugarPattern (IndexedPattern pat expr) = +  IndexedPattern <$> desugarPattern pat <*> desugar expr+desugarPattern (InductivePattern name exprs) =+  InductivePattern name <$> mapM desugar exprs+desugarPattern pattern = return pattern+ desugarBinding :: BindingExpr -> DesugarM BindingExpr desugarBinding (name, expr) = do   expr' <- desugar expr@@ -199,5 +243,4 @@   clause' <- desugarMatchClause clause   rest'   <- desugarMatchClauses rest   return $ clause : rest'-   desugarMatchClauses [] = return []
hs-src/Language/Egison/Parser.hs view
@@ -25,34 +25,20 @@ import Language.Egison.Types import Language.Egison.Desugar   -runParser' :: Parser a -> String -> Either EgisonError a-runParser' parser input = either (throwError . Parser) return $ parse parser "egison" (B.pack input)-  -readTopExprs :: String -> Either EgisonError [EgisonTopExpr]-readTopExprs input = either throwError (mapM desugarTopExpr) $ runParser' (whiteSpace >> parseTopExprs) input--readTopExpr :: String -> Either EgisonError EgisonTopExpr-readTopExpr input = either throwError desugarTopExpr $ runParser' (whiteSpace >> parseTopExpr) input--readExprs :: String -> Either EgisonError [EgisonExpr]-readExprs input = either throwError (mapM desugarExpr) $ runParser' (whiteSpace >> parseExprs) input+doParse :: Parser a -> String -> Either EgisonError a+doParse p input = either (throwError . Parser) return $ parse p "egison" $ B.pack input -readExpr :: String -> Either EgisonError EgisonExpr-readExpr input = either throwError desugarExpr $ runParser' (whiteSpace >> parseExpr) input+readTopExprs :: String -> Fresh (Either EgisonError [EgisonTopExpr])+readTopExprs input = runDesugarM $ either throwError (mapM desugarTopExpr) $ doParse (whiteSpace >> parseTopExprs) input -desugarTopExpr :: EgisonTopExpr -> Either EgisonError EgisonTopExpr-desugarTopExpr (Define name expr) = do-  expr' <- desugarExpr expr-  return (Define name expr')-  -desugarTopExpr (Test expr) = do-  expr' <- desugarExpr expr-  return (Test expr')+readTopExpr :: String -> Fresh (Either EgisonError EgisonTopExpr)+readTopExpr input = runDesugarM $ either throwError desugarTopExpr $ doParse (whiteSpace >> parseTopExpr) input -desugarTopExpr expr = return expr+readExprs :: String -> Fresh (Either EgisonError [EgisonExpr])+readExprs input = runDesugarM $ either throwError (mapM desugar) $ doParse (whiteSpace >> parseExprs) input -desugarExpr :: EgisonExpr -> Either EgisonError EgisonExpr-desugarExpr expr = either throwError return $ runDesugarM $ desugar expr+readExpr :: String -> Fresh (Either EgisonError EgisonExpr)+readExpr input = runDesugarM $ either throwError desugar $ doParse (whiteSpace >> parseExpr) input  -- Expressions @@ -86,7 +72,11 @@ parseExprs = endBy parseExpr whiteSpace  parseExpr :: Parser EgisonExpr-parseExpr = (try parseConstantExpr+parseExpr = do expr <- parseExpr'+               option expr $ IndexedExpr expr <$> many1 (try $ char '_' >> parseExpr')++parseExpr' :: Parser EgisonExpr+parseExpr' = (try parseConstantExpr              <|> try parseVarExpr --           <|> parseOmitExpr              <|> try parsePatVarExpr@@ -100,6 +90,7 @@                                       <|> try parseInductiveDataExpr              <|> parseInductivePatternExpr+             <|> try parseArrayExpr              <|> parseTupleExpr              <|> parseCollectionExpr              <|> parens (parseAndPatExpr @@ -109,29 +100,20 @@                          <|> parseFunctionExpr                          <|> parseLetRecExpr                          <|> parseLetExpr-                         <|> parseLoopExpr+                         <|> parseIndexLoopExpr                          <|> parseDoExpr                          <|> parseMatchAllExpr                          <|> parseMatchExpr                          <|> parseMatcherExpr                          <|> parseApplyExpr-                         <|> parseAlgebraicDataMatcherExpr)+                         <|> parseAlgebraicDataMatcherExpr+                         <|> parseGenerateArrayExpr+                         <|> parseArraySizeExpr+                         <|> parseArrayRefExpr)                          <?> "expression")  parseVarExpr :: Parser EgisonExpr-parseVarExpr = VarExpr <$> ident <*> parseIndexNums--parseIndexNums :: Parser [EgisonExpr]-parseIndexNums = ((:) <$> try (prefix >> parseExpr) <*> parseIndexNums)-              <|> pure []-  where-    prefix :: Parser Char-    prefix = do result <- char '_' >> isConsumed whiteSpace-                if result then parserFail "unexpected whiteSpace"-                          else return '_'-    -    isConsumed :: Parser a -> Parser Bool-    isConsumed p = (/=) <$> getPosition <*> (p >> getPosition)+parseVarExpr = VarExpr <$> ident  parseInductiveDataExpr :: Parser EgisonExpr parseInductiveDataExpr = angles $ InductiveDataExpr <$> upperName <*> sepEndBy parseExpr whiteSpace@@ -149,6 +131,12 @@   parseInnerExpr = (char '@' >> SubCollectionExpr <$> parseExpr)                <|> ElementExpr <$> parseExpr +parseArrayExpr :: Parser EgisonExpr+parseArrayExpr = between lp rp $ ArrayExpr <$> sepEndBy parseExpr whiteSpace+  where+    lp = P.lexeme lexer (string "[|")+    rp = P.lexeme lexer (string "|]")+ parseMatchAllExpr :: Parser EgisonExpr parseMatchAllExpr = keywordMatchAll >> MatchAllExpr <$> parseExpr <*> parseExpr <*> parseMatchClause @@ -236,9 +224,9 @@ parseVarName :: Parser String parseVarName = char '$' >> ident -parseLoopExpr :: Parser EgisonExpr-parseLoopExpr = keywordLoop >> LoopExpr <$> parseVarName <*> parseVarName-                                        <*> parseExpr <*> parseExpr <*> parseExpr+parseIndexLoopExpr :: Parser EgisonExpr+parseIndexLoopExpr = keywordIndexLoop >> IndexLoopExpr <$> parseVarName <*> parseVarName <*> parseVarName+                                                       <*> parseExpr <*> parseExpr <*> parseExpr <*> parseExpr  parseApplyExpr :: Parser EgisonExpr parseApplyExpr = (keywordApply >> ApplyExpr <$> parseExpr <*> parseExpr) @@ -252,7 +240,7 @@   case vars of     [] -> return . ApplyExpr func . TupleExpr $ rights args     _ | all null vars ->-        let genVar = modify (1+) >> gets (flip VarExpr [] . ('#':) . show)+        let genVar = modify (1+) >> gets (VarExpr . ('#':) . show)             args' = evalState (mapM (either (const genVar) return) args) 0         in return . LambdaExpr (annonVars $ length vars) . ApplyExpr func $ TupleExpr args'       | all (not . null) vars ->@@ -260,7 +248,7 @@             n = Set.size ns         in if Set.findMin ns == 1 && Set.findMax ns == n              then-               let args' = map (either (flip VarExpr [] . ('#':)) id) args+               let args' = map (either (VarExpr . ('#':)) id) args                in return . LambdaExpr (annonVars n) . ApplyExpr func $ TupleExpr args'              else fail "invalid partial application"       | otherwise -> fail "invalid partial application"@@ -284,7 +272,7 @@ parseValuePatExpr = reservedOp "," >> PatternExpr . ValuePat <$> parseExpr  parsePatVarExpr :: Parser EgisonExpr-parsePatVarExpr = P.lexeme lexer $ (PatternExpr .) . PatVar <$> parseVarName <*> parseIndexNums+parsePatVarExpr = P.lexeme lexer $ PatternExpr . PatVar <$> parseVarName  parsePredPatExpr :: Parser EgisonExpr parsePredPatExpr = reservedOp "?" >> PatternExpr . PredPat <$> parseExpr@@ -297,11 +285,20 @@  parseAlgebraicDataMatcherExpr :: Parser EgisonExpr parseAlgebraicDataMatcherExpr = keywordAlgebraicDataMatcher -                                >> (parens $ AlgebraicDataMatcher <$> parseAlgebraicDataMatcherBody)+                                >> (parens $ AlgebraicDataMatcherExpr <$> parseAlgebraicDataMatcherBody)   where     parseAlgebraicDataMatcherBody :: Parser [EgisonExpr]     parseAlgebraicDataMatcherBody = reservedOp "|" >> sepEndBy1 parseInductivePatternExpr whiteSpace +parseGenerateArrayExpr :: Parser EgisonExpr+parseGenerateArrayExpr = keywordGenerateArray >> GenerateArrayExpr <$> parseVarNames <*> parseExpr <*> parseExpr++parseArraySizeExpr :: Parser EgisonExpr+parseArraySizeExpr = keywordArraySize >> ArraySizeExpr <$> parseExpr++parseArrayRefExpr :: Parser EgisonExpr+parseArrayRefExpr = keywordArrayRef >> ArrayRefExpr <$> parseExpr <*> parseExpr+ --parseOmitExpr :: Parser EgisonExpr --parseOmitExpr = prefixChar '`' >> OmitExpr <$> ident <*> parseIndexNums @@ -368,13 +365,16 @@   , "pattern-constructor"   , "letrec"   , "let"-  , "loop"+  , "index-loop"   , "match-all"   , "match"   , "matcher"   , "do"   , "function"   , "algebraic-data-matcher"+  , "generate-array"+  , "array-size"+  , "array-ref"   , "something"   , "undefined"]   @@ -408,7 +408,7 @@ keywordPatternConstructor   = reserved "pattern-constructor" keywordLetRec               = reserved "letrec" keywordLet                  = reserved "let"-keywordLoop                 = reserved "loop"+keywordIndexLoop            = reserved "index-loop" keywordMatchAll             = reserved "match-all" keywordMatch                = reserved "match" keywordMatcher              = reserved "matcher"@@ -417,6 +417,9 @@ keywordSomething            = reserved "something" keywordUndefined            = reserved "undefined" keywordAlgebraicDataMatcher = reserved "algebraic-data-matcher"+keywordGenerateArray        = reserved "generate-array"+keywordArraySize            = reserved "array-size"+keywordArrayRef             = reserved "array-ref"  sign :: Num a => Parser (a -> a) sign = (char '-' >> return negate)@@ -464,6 +467,8 @@  ident :: Parser String ident = P.identifier lexer+    <|> try ((:) <$> char '+' <*> ident)+    <|> try ((:) <$> char '-' <*> ident)     <|> (P.lexeme lexer $ string "+")     <|> (P.lexeme lexer $ string "-") 
hs-src/Language/Egison/Primitives.hs view
@@ -6,19 +6,20 @@ import Control.Monad.Error  import Data.IORef+import qualified Data.Array as A  import System.IO+import System.Random  import Language.Egison.Types import Language.Egison.Core  primitiveEnv :: IO Env primitiveEnv = do-  let ops = map (second PrimitiveFunc) (primitives ++ ioPrimitives) ++-            map (second IOFunc) assertions+  let ops = map (second PrimitiveFunc) (primitives ++ ioPrimitives)   bindings <- forM (constants ++ ops) $ \(name, op) -> do     ref <- newIORef . WHNF $ Value op-    return ((name, []), ref)+    return (name, ref)   return $ extendEnv nullEnv bindings  {-# INLINE noArg #-}@@ -35,6 +36,7 @@           [WHNFData] -> m EgisonValue oneArg f = \vals -> case vals of                        [val] -> f val+                      [] -> f $ Value $ Tuple []                       _ -> throwError $ ArgumentsNum 1 $ length vals  {-# INLINE twoArgs #-}@@ -69,7 +71,7 @@              , ("-", integerBinaryOp (-))              , ("*", integerBinaryOp (*))              , ("modulo",    integerBinaryOp mod)-             , ("qutient",   integerBinaryOp quot)+             , ("quotient",   integerBinaryOp quot)              , ("remainder", integerBinaryOp rem)              , ("eq-n?",  integerBinaryPred (==))              , ("lt-n?",  integerBinaryPred (<))@@ -111,47 +113,49 @@              , ("lte?", lte)              , ("gt?",  gt)              , ("gte?", gte)-             , ("string-append", stringAppend) ]-             +             , ("string-append", stringAppend)+             , ("assert", assert)+             , ("assert-equal", assertEqual) ]+ integerUnaryOp :: (Integer -> Integer) -> PrimitiveFunc-integerUnaryOp op = oneArg $ \val ->+integerUnaryOp op = (liftError .) $ oneArg $ \val ->   Integer . op <$> fromIntegerValue val  integerBinaryOp :: (Integer -> Integer -> Integer) -> PrimitiveFunc-integerBinaryOp op = twoArgs $ \val val' ->+integerBinaryOp op = (liftError .) $ twoArgs $ \val val' ->   (Integer .) . op <$> fromIntegerValue val                    <*> fromIntegerValue val'  integerBinaryPred :: (Integer -> Integer -> Bool) -> PrimitiveFunc-integerBinaryPred pred = twoArgs $ \val val' ->+integerBinaryPred pred = (liftError .) $ twoArgs $ \val val' ->   (Bool .) . pred <$> fromIntegerValue val                   <*> fromIntegerValue val'  floatUnaryOp :: (Double -> Double) -> PrimitiveFunc-floatUnaryOp op = oneArg $ \val ->+floatUnaryOp op = (liftError .) $ oneArg $ \val ->   Float . op <$> fromFloatValue val  floatBinaryOp :: (Double -> Double -> Double) -> PrimitiveFunc-floatBinaryOp op = twoArgs $ \val val' ->+floatBinaryOp op = (liftError .) $ twoArgs $ \val val' ->   (Float .) . op <$> fromFloatValue val                  <*> fromFloatValue val'  floatBinaryPred :: (Double -> Double -> Bool) -> PrimitiveFunc-floatBinaryPred pred = twoArgs $ \val val' ->+floatBinaryPred pred = (liftError .) $ twoArgs $ \val val' ->   (Bool .) . pred <$> fromFloatValue val                   <*> fromFloatValue val'  floatToIntegerOp :: (Double -> Integer) -> PrimitiveFunc-floatToIntegerOp op = oneArg $ \val ->+floatToIntegerOp op = (liftError .) $ oneArg $ \val ->   Integer . op <$> fromFloatValue val  eq :: PrimitiveFunc-eq = twoArgs $ \val val' ->+eq = (liftError .) $ twoArgs $ \val val' ->   (Bool .) . (==) <$> fromPrimitiveValue val                   <*> fromPrimitiveValue val'  lt :: PrimitiveFunc-lt = twoArgs lt'+lt = (liftError .) $ twoArgs lt'  where   lt' (Value (Integer i)) (Value (Integer i')) = return $ Bool $ i < i'   lt' (Value (Integer i)) (Value (Float f)) = return $ Bool $ fromInteger i < f@@ -162,7 +166,7 @@   lt' val _ = throwError $ TypeMismatch "number" val  lte :: PrimitiveFunc-lte = twoArgs lte'+lte = (liftError .) $ twoArgs lte'  where   lte' (Value (Integer i)) (Value (Integer i')) = return $ Bool $ i <= i'   lte' (Value (Integer i)) (Value (Float f)) = return $ Bool $ fromInteger i <= f@@ -173,7 +177,7 @@   lte' val _ = throwError $ TypeMismatch "number" val  gt :: PrimitiveFunc-gt = twoArgs gt'+gt = (liftError .) $ twoArgs gt'  where   gt' (Value (Integer i)) (Value (Integer i')) = return $ Bool $ i > i'   gt' (Value (Integer i)) (Value (Float f)) = return $ Bool $ fromInteger i > f@@ -184,7 +188,7 @@   gt' val _ = throwError $ TypeMismatch "number" val  gte :: PrimitiveFunc-gte = twoArgs gte'+gte = (liftError .) $ twoArgs gte'  where   gte' (Value (Integer i)) (Value (Integer i')) = return $ Bool $ i >= i'   gte' (Value (Integer i)) (Value (Float f)) = return $ Bool $ fromInteger i >= f@@ -194,17 +198,36 @@   gte' (Value (Float _)) val = throwError $ TypeMismatch "number" val   gte' val _ = throwError $ TypeMismatch "number" val ++ stringAppend :: PrimitiveFunc-stringAppend = twoArgs $ \val val' ->+stringAppend = (liftError .) $ twoArgs $ \val val' ->   (String .) . (++) <$> fromStringValue val                     <*> fromStringValue val' +assert ::  PrimitiveFunc+assert = (liftError .) $ twoArgs $ \label test -> do+  test <- fromBoolValue test+  if test+    then return $ Bool True+    else throwError $ Assertion $ show label++assertEqual :: PrimitiveFunc+assertEqual = threeArgs $ \label actual expected -> do+  actual <- evalDeep actual+  expected <- evalDeep expected+  if actual == expected+    then return $ Bool True+    else throwError $ Assertion $ show label ++ "\n expected: " ++ show expected +++                                  "\n but found: " ++ show actual+ -- -- IO Primitives --  ioPrimitives :: [(String, PrimitiveFunc)]-ioPrimitives = [ ("open-input-file", makePort ReadMode)+ioPrimitives = [ ("return", return')+               , ("open-input-file", makePort ReadMode)                , ("open-output-file", makePort WriteMode)                , ("close-input-port", closePort)                , ("close-output-port", closePort)@@ -215,6 +238,7 @@                , ("write-string", writeString)                , ("write", write) --             , ("print", writeStringLine)+               , ("eof?", isEOFStdin)                , ("flush", flushStdout)                , ("read-char-from-port", readCharFromPort)                , ("read-line-from-port", readLineFromPort)@@ -222,92 +246,88 @@                , ("write-char-to-port", writeCharToPort)                , ("write-string-to-port", writeStringToPort)                , ("write-to-port", writeToPort)+               , ("eof-port?", isEOFPort) --             , ("print-to-port", writeStringLineToPort)-               , ("flush-port", flushPort) ]+               , ("flush-port", flushPort) +--               , ("rand", rand)+--               , ("rand-range", randRange) ]+               , ("rand", randRange) ]                  --             , ("get-lib-dir-name", getLibDirName) ] -makeIO :: IO EgisonValue -> EgisonValue-makeIO io = IOFunc . oneArg $ \val ->-  case val of-    Value World -> Tuple . (:) World . return <$> liftIO io-    _ -> throwError $ TypeMismatch "world" val+makeIO :: EgisonM EgisonValue -> EgisonValue+makeIO m = IOFunc $ liftM (Value . Tuple . (World :) . (:[])) m -makeIO' :: IO () -> EgisonValue-makeIO' io = IOFunc . oneArg $ \val ->-  case val of-    Value World -> liftIO io >> return World-    _ -> throwError $ TypeMismatch "world" val+makeIO' :: EgisonM () -> EgisonValue+makeIO' m = IOFunc $ m >> return (Value $ Tuple [World, Tuple []]) +return' :: PrimitiveFunc+return' = oneArg $ return . makeIO . evalDeep+ makePort :: IOMode -> PrimitiveFunc-makePort mode = oneArg $ \val -> do+makePort mode = (liftError .) $ oneArg $ \val -> do   filename <- fromStringValue val -  return . makeIO $ Port <$> openFile filename mode+  return . makeIO . liftIO $ Port <$> openFile filename mode  closePort :: PrimitiveFunc-closePort = oneArg $ \val -> makeIO' . hClose <$> fromPortValue val+closePort = (liftError .) $ oneArg $ \val ->+  makeIO' . liftIO . hClose <$> fromPortValue val  writeChar :: PrimitiveFunc-writeChar = oneArg $ \val -> makeIO' . putChar <$> fromCharValue val+writeChar = (liftError .) $ oneArg $ \val ->+  makeIO' . liftIO . putChar <$> fromCharValue val  writeString :: PrimitiveFunc-writeString = oneArg $ \val -> makeIO' . putStr <$> fromStringValue val+writeString = (liftError .) $ oneArg $ \val ->+  makeIO' . liftIO . putStr <$> fromStringValue val  write :: PrimitiveFunc-write = oneArg $ Right . makeIO' . putStr . show+write = oneArg $ \val ->+  makeIO' . liftIO . putStr . show <$> evalDeep val  readChar :: PrimitiveFunc-readChar = noArg $ Right $ makeIO (liftM Char getChar)+readChar = noArg $ return $ makeIO $ liftIO $ liftM Char getChar  readLine :: PrimitiveFunc-readLine = noArg $ Right $ makeIO (liftM String getLine)+readLine = noArg $ return $ makeIO $ liftIO $ liftM String getLine  flushStdout :: PrimitiveFunc-flushStdout = noArg $ Right $ makeIO' $ hFlush stdout+flushStdout = noArg $ return $ makeIO' $ liftIO $ hFlush stdout +isEOFStdin :: PrimitiveFunc+isEOFStdin = noArg $ return $ makeIO $ liftIO $ liftM Bool isEOF+ writeCharToPort :: PrimitiveFunc-writeCharToPort = twoArgs $ \val val' ->-  (makeIO' .) . hPutChar <$> fromPortValue val <*> fromCharValue val'+writeCharToPort = (liftError .) $ twoArgs $ \val val' ->+  ((makeIO' . liftIO) .) . hPutChar <$> fromPortValue val <*> fromCharValue val'  writeStringToPort :: PrimitiveFunc-writeStringToPort = twoArgs $ \val val' ->-  (makeIO' .) . hPutStr <$> fromPortValue val <*> fromStringValue val'+writeStringToPort = (liftError .) $ twoArgs $ \val val' ->+  ((makeIO' . liftIO) .) . hPutStr <$> fromPortValue val <*> fromStringValue val'  writeToPort :: PrimitiveFunc-writeToPort = twoArgs $ \val val' ->-  makeIO' . flip hPutStr (show val') <$> fromPortValue val+writeToPort = twoArgs $ \val val' -> do+  ((makeIO' . liftIO) .) . hPutStr <$> liftError (fromPortValue val)+                                   <*> (show <$> evalDeep val')  readCharFromPort :: PrimitiveFunc-readCharFromPort = oneArg $ \val ->-  makeIO . liftM Char . hGetChar <$> fromPortValue val+readCharFromPort = (liftError .) $ oneArg $ \val ->+  makeIO . liftIO . liftM Char . hGetChar <$> fromPortValue val  readLineFromPort :: PrimitiveFunc-readLineFromPort = oneArg $ \val ->-  makeIO . liftM String . hGetLine <$> fromPortValue val+readLineFromPort = (liftError .) $ oneArg $ \val ->+  makeIO . liftIO . liftM String . hGetLine <$> fromPortValue val  flushPort :: PrimitiveFunc-flushPort = oneArg $ \val ->-  makeIO' . hFlush <$> fromPortValue val------- Assertions---+flushPort = (liftError .) $ oneArg $ \val ->+  makeIO' . liftIO . hFlush <$> fromPortValue val -assertions :: [(String, IOFunc)]-assertions = [ ("assert", assert)-             , ("assert-equal", assertEqual) ]+isEOFPort :: PrimitiveFunc+isEOFPort = (liftError .) $ oneArg $ \val ->+  makeIO . liftIO . liftM Bool . hIsEOF <$> fromPortValue val -assert :: IOFunc -assert = twoArgs $ \label test -> do-  test <- liftError $ fromBoolValue test-  if test-    then return $ Bool True-    else throwError $ Assertion $ show label+--rand :: PrimitiveFunc+--rand = noArg $ return $ makeIO $ liftIO $ liftM Integer $ getStdRandom random -assertEqual :: IOFunc -assertEqual = threeArgs $ \label actual expected -> do-  actual <- evalDeep actual-  expected <- evalDeep expected-  if actual == expected-    then return $ Bool True-    else throwError $ Assertion $ show label ++ "\n expected: " ++ show expected ++-                                  "\n but found: " ++ show actual+randRange :: PrimitiveFunc+randRange = (liftError .) $ twoArgs $ \val val' ->+  return . makeIO . liftIO . liftM Integer . getStdRandom . randomR =<< liftM2 (,) (fromIntegerValue val) (fromIntegerValue val')
hs-src/Language/Egison/Types.hs view
@@ -1,8 +1,11 @@-{-# Language TypeSynonymInstances, FlexibleInstances, GeneralizedNewtypeDeriving #-}+{-# Language TypeSynonymInstances, FlexibleInstances, GeneralizedNewtypeDeriving,+             MultiParamTypeClasses, UndecidableInstances  #-} module Language.Egison.Types where  import Control.Applicative import Control.Monad.Error+import Control.Monad.State+import Control.Monad.Identity import Control.Monad.Trans.Maybe  import Data.IORef@@ -12,6 +15,9 @@ import System.IO import Text.Parsec (ParseError) +import Data.IntMap (IntMap)+import qualified Data.IntMap as IntMap+ -- -- Expressions --@@ -31,11 +37,12 @@   | BoolExpr Bool   | IntegerExpr Integer   | FloatExpr Double-  | VarExpr String [EgisonExpr]-+  | VarExpr String+  | IndexedExpr EgisonExpr [EgisonExpr]   | InductiveDataExpr String [EgisonExpr]   | TupleExpr [EgisonExpr]   | CollectionExpr [InnerExpr]+  | ArrayExpr [EgisonExpr]    | PatternExpr EgisonPattern @@ -45,7 +52,7 @@   | LetExpr [BindingExpr] EgisonExpr   | LetRecExpr [BindingExpr] EgisonExpr -  | LoopExpr String String EgisonExpr EgisonExpr EgisonExpr+  | IndexLoopExpr String String String EgisonExpr EgisonExpr EgisonExpr EgisonExpr        | MatchExpr EgisonExpr EgisonExpr [MatchClause]   | MatchAllExpr EgisonExpr EgisonExpr MatchClause@@ -58,7 +65,10 @@        | ApplyExpr EgisonExpr EgisonExpr -  | AlgebraicDataMatcher [EgisonExpr]+  | AlgebraicDataMatcherExpr [EgisonExpr]+  | GenerateArrayExpr [String] EgisonExpr EgisonExpr+  | ArraySizeExpr EgisonExpr+  | ArrayRefExpr EgisonExpr EgisonExpr    | SomethingExpr   | UndefinedExpr@@ -70,13 +80,14 @@  data EgisonPattern =     WildCard-  | PatVar String [EgisonExpr]+  | PatVar String   | ValuePat EgisonExpr   | PredPat EgisonExpr   | CutPat EgisonExpr   | NotPat EgisonExpr   | AndPat [EgisonExpr]   | OrPat [EgisonExpr]+  | IndexedPattern EgisonPattern EgisonExpr   | InductivePattern String [EgisonExpr]  deriving (Show) @@ -116,18 +127,19 @@   | InductiveData String [EgisonValue]   | Tuple [EgisonValue]   | Collection [EgisonValue]+  | Array (IntMap EgisonValue)   | Pattern EgisonPattern   | Matcher Matcher   | Func Env [String] EgisonExpr   | PrimitiveFunc PrimitiveFunc-  | IOFunc IOFunc+  | IOFunc (EgisonM WHNFData)   | Port Handle   | Something+  | Undefined   | EOF  type Matcher = (Env, MatcherInfo)-type PrimitiveFunc = [WHNFData] -> Either EgisonError EgisonValue-type IOFunc = [WHNFData] -> EgisonM EgisonValue+type PrimitiveFunc = [WHNFData] -> EgisonM EgisonValue  instance Show EgisonValue where   show (Char c) = return c@@ -140,6 +152,7 @@   show (InductiveData name vals) = "<" ++ name ++ " " ++ unwords (map show vals) ++ ">"   show (Tuple vals) = "[" ++ unwords (map show vals) ++ "]"   show (Collection vals) = "{" ++ unwords (map show vals) ++ "}"+  show (Array vals) = "[|" ++ unwords (map show $ IntMap.elems vals) ++ "|]"   show (Pattern _) = "#<pattern>"   show (Matcher _) = "#<matcher>"   show (Func _ names _) = "(lambda [" ++ unwords names ++ "] ...)"@@ -147,6 +160,7 @@   show (IOFunc _) = "#<io>"   show (Port _) = "#<port>"   show Something = "something"+  show Undefined = "undefined"   show World = "#<world>"   show EOF = "#<eof>" @@ -158,6 +172,7 @@  (Float f) == (Float f') = f == f'  (InductiveData name vals) == (InductiveData name' vals') = name == name' && vals == vals'  (Tuple vals) == (Tuple vals') = vals == vals'+ (Array vals) == (Array vals') = vals == vals'  (Collection vals) == (Collection vals') = vals == vals'  _ == _ = False @@ -179,6 +194,7 @@     IInductiveData String [ObjectRef]   | ITuple [ObjectRef]   | ICollection [Inner]+  | IArray (IntMap ObjectRef)  data Inner =     IElement ObjectRef@@ -189,6 +205,7 @@   show (Intermediate (IInductiveData name _)) = "<" ++ name ++ " ...>"   show (Intermediate (ITuple _)) = "[...]"   show (Intermediate (ICollection _)) = "{...}"+  show (Intermediate (IArray _)) = "[|...|]"   fromCharValue :: WHNFData -> Either EgisonError Char fromCharValue (Value (Char c)) = return c@@ -234,7 +251,7 @@ -- Environment -- -type Var = (String, [Integer])+type Var = String type Env = [HashMap Var ObjectRef] type Binding = (Var, ObjectRef) @@ -277,8 +294,7 @@      instance Show EgisonError where   show (Parser error) = "Parse error at: " ++ show error-  show (UnboundVariable (var, nums)) = "Unbound variable: " ++ var ++-                                      concatMap (('_':) . show) nums+  show (UnboundVariable var) = "Unbound variable: " ++ var   show (TypeMismatch expected found) = "Expected " ++  expected ++                                         ", but found: " ++ show found   show (ArgumentsNum expected got) = "Wrong number of arguments: expected " ++@@ -299,13 +315,49 @@ -- Monads -- +newtype FreshT m a = FreshT { unFreshT :: StateT Int m a }+  deriving (Functor, Applicative, Monad, MonadState Int, MonadTrans)++type Fresh = FreshT Identity++class (Applicative m, Monad m) => MonadFresh m where+  fresh :: m String++instance (Applicative m, Monad m) => MonadFresh (FreshT m) where+  fresh = FreshT $ do counter <- get; modify (+ 1)+                      return $ "$_" ++ show counter++instance (MonadError e m) => MonadError e (FreshT m) where+  throwError = lift . throwError+  catchError m h = FreshT $ catchError (unFreshT m) (unFreshT . h)++instance (MonadState s m) => MonadState s (FreshT m) where+  get = lift $ get+  put s = lift $ put s+  +instance MonadIO (FreshT IO) where+  liftIO = lift++runFreshT :: Monad m => Int -> FreshT m a -> m (a, Int)+runFreshT seed = flip (runStateT . unFreshT) seed++runFresh :: Int -> Fresh a -> (a, Int)+runFresh seed m = runIdentity $ flip runStateT seed $ unFreshT m+ newtype EgisonM a = EgisonM {-    unEgisonM :: ErrorT EgisonError IO a+    unEgisonM :: ErrorT EgisonError (FreshT IO) a   } deriving (Functor, Applicative, Monad, MonadIO, MonadError EgisonError) -runEgisonM :: EgisonM a -> IO (Either EgisonError a)+runEgisonM :: EgisonM a -> FreshT IO (Either EgisonError a) runEgisonM = runErrorT . unEgisonM +liftEgisonM :: Fresh (Either EgisonError a) -> EgisonM a+liftEgisonM m = EgisonM $ ErrorT $ FreshT $ do+  s <- get+  (a, s') <- return $ runFresh s m+  put s'+  return $ either throwError return $ a   +   type MatchM = MaybeT EgisonM  matchFail :: MatchM a
lib/core/base.egi view
@@ -36,7 +36,7 @@       {[$tgt (if (eq? tgt c)                  {[]}                  {})]}]-     [_ [something]+     [$ [something]       {[$tgt {tgt}]}]      })) @@ -46,28 +46,13 @@       {[$tgt (if (eq? tgt s)                  {[]}                  {})]}]-     [_ [something]+     [$ [something]       {[$tgt {tgt}]}]      }))  (define $ordering-  (matcher-    {[,$val []-      {[$tgt (if (eq? val tgt)-                 {[]}-                 {})]}]-     [<less> []-      {[<Less> {[]}]-       [_ {}]}]-     [<equal> []-      {[<Equal> {[]}]-       [_ {}]}]-     [<greater> []-      {[<Greater> {[]}]-       [_ {}]}]-     [_ [something]-      {[$tgt {tgt}]}]-     }))+  (algebraic-data-matcher +    (| <less> <equal> <greater>)))  (define $match?   (lambda [$a]
lib/core/collection.egi view
@@ -33,7 +33,12 @@                                       [<cons $z $zs> {[xs ys] @(helper {@xs z} zs)}]}))]}                  (helper {} tgt))]}]        [<nioj ,$pxs $> [(list a)]-        {[$tgt (match-all tgt (list a) [<join $ys ,pxs> ys])]}]+        {[$tgt (letrec {[$helper (lambda [$pxs $tgt]+                                   (match [pxs tgt] [(list a) (list a)]+                                     {[[<nil> _] {tgt}]+                                      [[<snoc $x $xs> <snoc ,x $ys>] (helper xs ys)]+                                      [[_ _] {}]}))]}+                 (helper pxs tgt))]}]        [<nioj $ $> [(list a) (list a)]         {[$tgt (letrec {[$helper (lambda [$xs $ys]                                    (match ys (list a)@@ -78,6 +83,15 @@             {x @(filter pred xs)}             (filter pred xs))]}))) +(define $split+  (lambda [$pred $ls]+    (letrec {[$helper (lambda [$ls $xs $ys]+                        (match ls (list something)+                          {[<nil> [xs ys]]+                           [<cons (& ?pred $l) $rs> (helper rs {l @xs} ys)]+                           [<cons $l $rs> (helper rs xs {l @ys})]}))]}+      (helper ls {} {}))))+ (define $remove   (lambda [$a]     (lambda [$xs $x]@@ -102,42 +116,47 @@          [<cons $y $rs> ((remove-collection a) ((remove a) xs y) rs)]}))))  (define $add-  (lambda [$xs $x]-    (if (member? x xs)-        xs-        {@xs x})))+  (lambda [$a]+    (lambda [$xs $x]+      (if ((member? a) x xs)+          xs+          {@xs x}))))  (define $union-  (lambda [$xs $ys]-    (match ys (list something)-      {[<nil> xs]-       [<cons $y $rs> ((union a) ((add a) xs y) rs)]})))+  (lambda [$a]+    (lambda [$xs $ys]+      (match ys (list something)+        {[<nil> xs]+         [<cons $y $rs> ((union a) ((add a) xs y) rs)]}))))  (define $occurrence-  (lambda [$xs]-    (letrec {[$remove-and-count-              (lambda [$x $xs]-                (match xs (list something)-                  {[<nil> [{} 1]]-                   [<cons ,x $ys> (let {[[$r $i] (remove-and-count x ys)]}-                                    [r (+ i 1)])]-                   [<cons $y $ys> (let {[[$r $i] (remove-and-count x ys)]}-                                    [{y @r} i])]}))]}-      (match xs (list something)-        {[<nil> {}]-         [<cons $x $ys> (let {[[$rs $i] (remove-and-count x ys)]}-                          {[x i] @(occurrence rs)})]}))))+  (lambda [$a]+    (lambda [$xs]+      (letrec {[$remove-and-count+                (lambda [$x $xs]+                  (match xs (list a)+                    {[<nil> [{} 1]]+                     [<cons ,x $ys> (let {[[$r $i] (remove-and-count x ys)]}+                                      [r (+ i 1)])]+                     [<cons $y $ys> (let {[[$r $i] (remove-and-count x ys)]}+                                      [{y @r} i])]}))]}+        (match xs (list something)+          {[<nil> {}]+           [<cons $x $ys> (let {[[$rs $i] (remove-and-count x ys)]}+                            {[x i] @((occurrence a) rs)})]}))))) +#| (define $subcollections   (lambda [$xs]     (foldr (lambda [$x $rs]              (let {[[$y $i] x]}                 (map-and-concat (lambda [$sub] -                                 (match-all (loop $l $j (between 1 i) {y @l} {}) (list something)+                                 (match-all (index-loop $l $j (between 1 i) {y @l} {}) (list something)                                    [<join $ys _> {@ys @sub}]))                                rs)))            {{}}            ((occurrence a) xs))))+|#  (define $size   (lambda [$xs]@@ -194,38 +213,46 @@         {@(reverse rs) x}]})))  (define $member?-  (lambda [$x $ys]-    (match ys (list something)-      {[<nil> #f]-       [<cons ,x $ys> #t]-       [<cons $y $ys> ((member? a) x ys)]})))+  (lambda [$a]+    (lambda [$x $ys]+      (match ys (list a)+        {[<nil> #f]+         [<cons ,x $ys> #t]+         [<cons $y $ys> ((member? a) x ys)]}))))  (define $unique-  (lambda [$xs]-    (letrec {[$loop-fn-              (lambda [$xs $ys]-                (match xs (list something)-                  {[<nil> ys]-                   [<cons $x $rs>-                    (if (member? x ys)-                        (loop-fn rs ys)-                        (loop-fn rs {@ys x}))]}))]}-      (loop-fn xs {}))))+  (lambda [$a]+    (lambda [$xs]+      (letrec {[$loop-fn+                (lambda [$xs $ys]+                  (match xs (list something)+                    {[<nil> ys]+                     [<cons $x $rs>+                      (if ((member? a) x ys)+                          (loop-fn rs ys)+                          (loop-fn rs {@ys x}))]}))]}+        (loop-fn xs {})))))  (define $subcollection?-  (lambda [$xs $ys]-    (match xs (list something)-      {[<nil> #t]-       [<cons $x $rest>-        (if (member? x ys)-            (subcollection? rest ys)-            #f)]})))+  (lambda [$a]+    (lambda [$xs $ys]+      (match xs (list something)+        {[<nil> #t]+         [<cons $x $rest>+          (if ((member? a) x ys)+              ((subcollection? a) rest ys)+              #f)]}))))  (define $concat   (lambda [$xs]     (match xs (list something)       {[<nil> {}]        [<cons $x $rs> {@x @(concat rs)}]})))++(define $empty?+  (function (list something)+   {[<nil>      #t]+    [<cons _ _> #f]}))  (define $multiset   (lambda [$a]
test/UnitTest.hs view
@@ -2,7 +2,7 @@  import Control.Applicative import Control.Monad-+import Data.IORef  import Test.Framework (defaultMain) import Test.Framework.Providers.HUnit (hUnitTestToTests)@@ -21,7 +21,9 @@ runTestCase :: FilePath -> Test runTestCase file = TestLabel file . TestCase $ do    env <- primitiveEnv >>= loadLibraries-  result <- runEgisonM $ loadFile file >>= evalTopExprs' env+  seed <- readIORef counter+  (result, seed') <- runFreshT seed $ runEgisonM $ loadFile file >>= evalTopExprs' env+  writeIORef counter seed'   assertString $ either show (const "") result  evalTopExprs' :: Env -> [EgisonTopExpr] -> EgisonM ()