packages feed

egison 3.2.13 → 3.2.14

raw patch · 27 files changed

+1697/−602 lines, 27 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Language.Egison: counter :: IORef Int
- Language.Egison: fromEgisonM :: EgisonM a -> IO (Either EgisonError a)
- Language.Egison: loadLibraries :: Env -> IO Env
- Language.Egison: loadPrimitives :: Env -> IO Env
- Language.Egison.Core: evalDeep :: WHNFData -> EgisonM EgisonValue
- Language.Egison.Core: evalExpr' :: Env -> EgisonExpr -> EgisonM EgisonValue
- Language.Egison.Core: evalRef' :: ObjectRef -> EgisonM EgisonValue
- Language.Egison.Core: expandCollection :: WHNFData -> EgisonM (Seq Inner)
- Language.Egison.Core: fromArray :: WHNFData -> EgisonM [ObjectRef]
- Language.Egison.Core: fromCollection :: WHNFData -> EgisonM (MList EgisonM ObjectRef)
- Language.Egison.Core: fromTuple :: WHNFData -> EgisonM [ObjectRef]
- Language.Egison.Core: generateArray :: Env -> String -> EgisonExpr -> EgisonExpr -> EgisonM WHNFData
- Language.Egison.Core: inductiveMatch :: Env -> EgisonPattern -> ObjectRef -> Matcher -> EgisonM ([EgisonPattern], MList EgisonM ObjectRef, [WHNFData])
- Language.Egison.Core: isEmptyCollection :: ObjectRef -> EgisonM Bool
- Language.Egison.Core: makeBindings :: [String] -> [ObjectRef] -> [Binding]
- Language.Egison.Core: newEvaluatedThunk :: WHNFData -> EgisonM ObjectRef
- Language.Egison.Core: newThunk :: Env -> EgisonExpr -> EgisonM ObjectRef
- Language.Egison.Core: primitiveDataPatternMatch :: PrimitiveDataPattern -> ObjectRef -> MatchM [Binding]
- Language.Egison.Core: primitivePatPatternMatch :: Env -> PrimitivePatPattern -> EgisonPattern -> MatchM ([EgisonPattern], [Binding])
- Language.Egison.Core: processMState :: PMMode -> MatchingState -> EgisonM (MList EgisonM MatchingState)
- Language.Egison.Core: processMState' :: MatchingState -> EgisonM (MList EgisonM MatchingState)
- Language.Egison.Core: processMStates :: PMMode -> [MList EgisonM MatchingState] -> EgisonM (MList EgisonM [Binding])
- Language.Egison.Core: processMStates' :: PMMode -> MList EgisonM MatchingState -> (Maybe [Binding], [EgisonM (MList EgisonM MatchingState)])
- Language.Egison.Core: unconsCollection :: ObjectRef -> MatchM (ObjectRef, ObjectRef)
- Language.Egison.Core: unsnocCollection :: ObjectRef -> MatchM (ObjectRef, ObjectRef)
- Language.Egison.Core: writeThunk :: ObjectRef -> WHNFData -> EgisonM ()
- Language.Egison.Desugar: DesugarM :: ReaderT Subst (ErrorT EgisonError Fresh) a -> DesugarM a
- Language.Egison.Desugar: desugarBinding :: BindingExpr -> DesugarM BindingExpr
- Language.Egison.Desugar: desugarBindings :: [BindingExpr] -> DesugarM [BindingExpr]
- Language.Egison.Desugar: desugarLoopRange :: LoopRange -> DesugarM LoopRange
- Language.Egison.Desugar: desugarMatchClause :: MatchClause -> DesugarM MatchClause
- Language.Egison.Desugar: desugarMatchClauses :: [MatchClause] -> DesugarM [MatchClause]
- Language.Egison.Desugar: desugarPattern :: EgisonPattern -> DesugarM EgisonPattern
- Language.Egison.Desugar: desugarPattern' :: EgisonPattern -> DesugarM EgisonPattern
- Language.Egison.Desugar: newtype DesugarM a
- Language.Egison.Desugar: type Subst = [(String, EgisonExpr)]
- Language.Egison.Desugar: unDesugarM :: DesugarM a -> ReaderT Subst (ErrorT EgisonError Fresh) a
- Language.Egison.Parser: parseExpr :: String -> Either EgisonError EgisonExpr
- Language.Egison.Parser: parseExprs :: String -> Either EgisonError [EgisonExpr]
- Language.Egison.Parser: parseTopExpr :: String -> Either EgisonError EgisonTopExpr
- Language.Egison.Parser: parseTopExprs :: String -> Either EgisonError [EgisonTopExpr]
- Language.Egison.Types: CutPat :: EgisonPattern -> EgisonPattern
- Language.Egison.Types: extractInteger :: EgisonValue -> EgisonM Integer
- Language.Egison.Types: fromBoolValue :: WHNFData -> Either EgisonError Bool
- Language.Egison.Types: fromCharValue :: WHNFData -> Either EgisonError Char
- Language.Egison.Types: fromFloatValue :: WHNFData -> Either EgisonError Double
- Language.Egison.Types: fromIntegerValue :: WHNFData -> Either EgisonError Integer
- Language.Egison.Types: fromPortValue :: WHNFData -> Either EgisonError Handle
- Language.Egison.Types: fromPrimitiveValue :: WHNFData -> Either EgisonError EgisonValue
- Language.Egison.Types: fromRationalValue :: WHNFData -> Either EgisonError Rational
- Language.Egison.Types: fromStringValue :: WHNFData -> Either EgisonError String
- Language.Egison.Types: makeKey :: EgisonValue -> Either EgisonError EgisonHashKey
- Language.Egison.Types: makeStringValue :: String -> EgisonValue
- Language.Egison.Types: runFresh :: Int -> Fresh a -> (a, Int)
+ Language.Egison: loadCoreLibraries :: Env -> IO Env
+ Language.Egison: runEgisonExpr :: Env -> String -> IO (Either EgisonError EgisonValue)
+ Language.Egison.Core: evalExprDeep :: Env -> EgisonExpr -> EgisonM EgisonValue
+ Language.Egison.Core: evalRefDeep :: ObjectRef -> EgisonM EgisonValue
+ Language.Egison.Core: evalTopExpr' :: Env -> EgisonTopExpr -> EgisonM Env
+ Language.Egison.Core: evalWHNF :: WHNFData -> EgisonM EgisonValue
+ Language.Egison.Core: fromStringValue :: EgisonValue -> EgisonM String
+ Language.Egison.Core: fromStringWHNF :: WHNFData -> EgisonM String
+ Language.Egison.Desugar: data DesugarM a
+ Language.Egison.Types: class Egison a
+ Language.Egison.Types: class EgisonWHNF a
+ Language.Egison.Types: fromBuiltinWHNF :: WHNFData -> Either EgisonError EgisonValue
+ Language.Egison.Types: fromEgison :: Egison a => EgisonValue -> EgisonM a
+ Language.Egison.Types: fromEgisonM :: EgisonM a -> IO (Either EgisonError a)
+ Language.Egison.Types: fromWHNF :: EgisonWHNF a => WHNFData -> EgisonM a
+ Language.Egison.Types: instance (Egison a, Egison b) => Egison (a, b)
+ Language.Egison.Types: instance (Egison a, Egison b, Egison c) => Egison (a, b, c)
+ Language.Egison.Types: instance (Egison a, Egison b, Egison c, Egison d) => Egison (a, b, c, d)
+ Language.Egison.Types: instance Egison ()
+ Language.Egison.Types: instance Egison Bool
+ Language.Egison.Types: instance Egison Char
+ Language.Egison.Types: instance Egison Double
+ Language.Egison.Types: instance Egison Handle
+ Language.Egison.Types: instance Egison Integer
+ Language.Egison.Types: instance Egison Rational
+ Language.Egison.Types: instance Egison a => Egison [a]
+ Language.Egison.Types: instance EgisonWHNF Bool
+ Language.Egison.Types: instance EgisonWHNF Char
+ Language.Egison.Types: instance EgisonWHNF Double
+ Language.Egison.Types: instance EgisonWHNF Handle
+ Language.Egison.Types: instance EgisonWHNF Integer
+ Language.Egison.Types: instance EgisonWHNF Matcher
+ Language.Egison.Types: instance EgisonWHNF Rational
+ Language.Egison.Types: toEgison :: Egison a => a -> EgisonValue
+ Language.Egison.Util: completeEgison :: Monad m => CompletionFunc m
- Language.Egison.Types: fromMatcherValue :: WHNFData -> Either EgisonError Matcher
+ Language.Egison.Types: fromMatcherValue :: EgisonValue -> Either EgisonError Matcher
- Language.Egison.Types: type PrimitiveFunc = [WHNFData] -> EgisonM EgisonValue
+ Language.Egison.Types: type PrimitiveFunc = EgisonValue -> EgisonM EgisonValue

Files

egison.cabal view
@@ -1,5 +1,5 @@ Name:                egison-Version:             3.2.13+Version:             3.2.14 Synopsis:            Programming language with non-linear pattern-matching against unfree data types Description:         An interpreter for Egison, the programming langugage that realized non-linear pattern-matching with unfree data types.                      With Egison, you can represent pattern-matching with unfree data types intuitively,@@ -19,6 +19,7 @@  Data-files:          lib/core/base.egi lib/core/collection.egi lib/core/order.egi lib/core/number.egi lib/core/natural-number.egi lib/core/string.egi lib/core/database.egi lib/core/io.egi                      lib/tree/xml.egi lib/math/prime.egi+                     sample/*.egi sample/io/*.egi sample/io/*.egi                      elisp/egison-mode.el  source-repository head@@ -37,6 +38,7 @@                    Language.Egison.Types                    Language.Egison.Parser                    Language.Egison.Primitives+                   Language.Egison.Util   Other-modules:   Paths_egison  Test-Suite test
hs-src/Interpreter/egisoni.hs view
@@ -27,6 +27,7 @@ import System.Exit (ExitCode (..), exitWith, exitFailure) import System.IO import Language.Egison+import Language.Egison.Util  main :: IO () main = do args <- getArgs@@ -36,20 +37,20 @@             Options {optShowHelp = True} -> printHelp             Options {optShowVersion = True} -> printVersionNumber             Options {optPrompt = prompt, optShowBanner = bannerFlag} -> do-                case nonOpts of-                    [] -> do-                        env <- primitiveEnv >>= loadLibraries-                        when bannerFlag showBanner >> repl env prompt >> when bannerFlag showByebyeMessage-                    (file:args) -> do-                        case opts of-                          Options {optLoadOnly = True} -> do-                            env <- primitiveEnvNoIO >>= loadLibraries-                            result <- evalEgisonTopExprs env [LoadFile file]-                            either print (const $ return ()) result-                          Options {optLoadOnly = False} -> do-                            env <- primitiveEnv >>= loadLibraries-                            result <- evalEgisonTopExprs env [LoadFile file, Execute (ApplyExpr (VarExpr "main") (CollectionExpr (Sq.fromList (map (ElementExpr . StringExpr) args))))]-                            either print (const $ return ()) result+              case nonOpts of+                [] -> do+                  env <- primitiveEnv >>= loadCoreLibraries+                  when bannerFlag showBanner >> repl env prompt >> when bannerFlag showByebyeMessage+                (file:args) -> do+                  case opts of+                    Options {optLoadOnly = True} -> do+                      env <- primitiveEnvNoIO >>= loadCoreLibraries+                      result <- evalEgisonTopExprs env [LoadFile file]+                      either print (const $ return ()) result+                    Options {optLoadOnly = False} -> do+                      env <- primitiveEnv >>= loadCoreLibraries+                      result <- evalEgisonTopExprs env [LoadFile file, Execute (ApplyExpr (VarExpr "main") (CollectionExpr (Sq.fromList (map (ElementExpr . StringExpr) args))))]+                      either print (const $ return ()) result  data Options = Options {     optShowVersion :: Bool,@@ -128,7 +129,7 @@   where     settings :: MonadIO m => FilePath -> Settings m     settings home = do-      setComplete completeParen $ defaultSettings { historyFile = Just (home </> ".egison_history") }+      setComplete completeEgison $ defaultSettings { historyFile = Just (home </> ".egison_history") }          loop :: Env -> String -> String -> InputT IO ()     loop env prompt' rest = do@@ -150,7 +151,7 @@             Left err | show err =~ "unexpected end of input" -> do               loop env (take (length prompt) (repeat ' ')) $ newInput ++ "\n"             Left err | show err =~ "expecting (top-level|\"define\")" -> do-              result <- liftIO $ handle onAbort $ fromEgisonM (readExpr newInput) >>= either (return . Left) (evalEgisonExpr env)+              result <- liftIO $ handle onAbort $ runEgisonExpr env newInput               case result of                 Left err | show err =~ "unexpected end of input" -> do                   loop env (take (length prompt) (repeat ' ')) $ newInput ++ "\n"@@ -165,73 +166,3 @@               loop env prompt ""             Right env' ->               loop env' prompt ""--completeParen :: Monad m => CompletionFunc m-completeParen arg@((')':_), _) = completeParen' arg-completeParen arg@(('>':_), _) = completeParen' arg-completeParen arg@((']':_), _) = completeParen' arg-completeParen arg@(('}':_), _) = completeParen' arg-completeParen arg@(('(':_), _) = (completeWord Nothing " \t<>[]{}$," completeAfterOpenParen) arg-completeParen arg@(('<':_), _) = (completeWord Nothing " \t()[]{}$," completeAfterOpenCons) arg-completeParen arg@((' ':_), _) = (completeWord Nothing "" completeNothing) arg-completeParen arg@([], _) = (completeWord Nothing "" completeNothing) arg-completeParen arg@(_, _) = (completeWord Nothing " \t[]{}$," completeEgisonKeyword) arg--completeAfterOpenParen :: Monad m => String -> m [Completion]-completeAfterOpenParen str = return $ map (\kwd -> Completion kwd kwd False) $ filter (isPrefixOf str) egisonKeywordsAfterOpenParen--completeAfterOpenCons :: Monad m => String -> m [Completion]-completeAfterOpenCons str = return $ map (\kwd -> Completion kwd kwd False) $ filter (isPrefixOf str) egisonKeywordsAfterOpenCons--completeNothing :: Monad m => String -> m [Completion]-completeNothing _ = return []--completeEgisonKeyword :: Monad m => String -> m [Completion]-completeEgisonKeyword str = return $ map (\kwd -> Completion kwd kwd False) $ filter (isPrefixOf str) egisonKeywords--egisonKeywordsAfterOpenParen = map ((:) '(') $ ["define", "let", "letrec", "do", "lambda", "match-lambda", "match", "match-all", "pattern-function", "matcher", "algebraic-data-matcher", "if", "loop", "io"]-                            ++ ["id", "or", "and", "not", "char", "eq?/m", "compose", "compose3", "list", "map", "between", "repeat1", "repeat", "filter", "separate", "concat", "foldr", "foldl", "map2", "zip", "empty?", "member?", "member?/m", "include?", "include?/m", "any", "all", "length", "count", "count/m", "car", "cdr", "rac", "rdc", "nth", "take", "drop", "while", "reverse", "multiset", "add", "add/m", "delete-first", "delete-first/m", "delete", "delete/m", "difference", "difference/m", "union", "union/m", "intersect", "intersect/m", "set", "unique", "unique/m", "simple-select", "print", "print-to-port", "each", "pure-rand", "fib", "fact", "divisor?", "gcd", "primes", "find-factor", "prime-factorization", "p-f", "pfs", "pfs-n", "min", "max", "min-and-max", "power", "mod", "float", "ordering", "qsort", "intersperse", "intercalate", "split", "split/m"]-egisonKeywordsAfterOpenCons = map ((:) '<') ["nil", "cons", "join", "snoc", "nioj"]-egisonKeywordsInNeutral = ["something"]-                       ++ ["bool", "string", "integer", "nat", "nats", "nats0"]-egisonKeywords = egisonKeywordsAfterOpenParen ++ egisonKeywordsAfterOpenCons ++ egisonKeywordsInNeutral--completeParen' :: Monad m => CompletionFunc m-completeParen' (lstr, _) = case (closeParen lstr) of-                             Nothing -> return (lstr, [])-                             Just paren -> return (lstr, [(Completion paren paren False)])--closeParen :: String -> Maybe String-closeParen str = closeParen' 0 $ removeCharAndStringLiteral str--removeCharAndStringLiteral :: String -> String-removeCharAndStringLiteral [] = []-removeCharAndStringLiteral ('"':'\\':str) = '"':'\\':(removeCharAndStringLiteral str)-removeCharAndStringLiteral ('"':str) = removeCharAndStringLiteral' str-removeCharAndStringLiteral ('\'':'\\':str) = '\'':'\\':(removeCharAndStringLiteral str)-removeCharAndStringLiteral ('\'':str) = removeCharAndStringLiteral' str-removeCharAndStringLiteral (c:str) = c:(removeCharAndStringLiteral str)--removeCharAndStringLiteral' :: String -> String-removeCharAndStringLiteral' [] = []-removeCharAndStringLiteral' ('"':'\\':str) = removeCharAndStringLiteral' str-removeCharAndStringLiteral' ('"':str) = removeCharAndStringLiteral str-removeCharAndStringLiteral' ('\'':'\\':str) = removeCharAndStringLiteral' str-removeCharAndStringLiteral' ('\'':str) = removeCharAndStringLiteral str-removeCharAndStringLiteral' (_:str) = removeCharAndStringLiteral' str--closeParen' :: Integer -> String -> Maybe String-closeParen' _ [] = Nothing-closeParen' 0 ('(':_) = Just ")"-closeParen' 0 ('<':_) = Just ">"-closeParen' 0 ('[':_) = Just "]"-closeParen' 0 ('{':_) = Just "}"-closeParen' n ('(':str) = closeParen' (n - 1) str-closeParen' n ('<':str) = closeParen' (n - 1) str-closeParen' n ('[':str) = closeParen' (n - 1) str-closeParen' n ('{':str) = closeParen' (n - 1) str-closeParen' n (')':str) = closeParen' (n + 1) str-closeParen' n ('>':str) = closeParen' (n + 1) str-closeParen' n (']':str) = closeParen' (n + 1) str-closeParen' n ('}':str) = closeParen' (n + 1) str-closeParen' n (_:str) = closeParen' n str
hs-src/Language/Egison.hs view
@@ -1,26 +1,33 @@+{- |+Module      : Language.Egison+Copyright   : Satoshi Egi+Licence     : MIT +This is the top module of Egison.+-}+ module Language.Egison        ( module Language.Egison.Types        , module Language.Egison.Parser        , module Language.Egison.Primitives-       , version-       , counter --danger-       , fromEgisonM-       , loadLibraries-       , loadPrimitives-       , loadEgisonFile-       , loadEgisonLibrary+       -- * Eval Egison expressions        , evalEgisonExpr        , evalEgisonTopExpr        , evalEgisonTopExprs+       , runEgisonExpr        , runEgisonTopExpr        , runEgisonTopExprs+       -- * Load Egison files+       , loadCoreLibraries+       , loadEgisonLibrary+       , loadEgisonFile+       -- * Information+       , version        ) where  import Control.Applicative ((<$>), (<*>)) import Control.Monad.Error -import System.IO.Unsafe (unsafePerformIO) import Data.IORef import Data.Version import qualified Paths_egison as P@@ -30,37 +37,42 @@ import Language.Egison.Primitives import Language.Egison.Core +-- |Version number version :: Version version = P.version --- Unsafe-counter :: IORef Int-counter = unsafePerformIO (newIORef 0)+-- |eval an Egison expression+evalEgisonExpr :: Env -> EgisonExpr -> IO (Either EgisonError EgisonValue)+evalEgisonExpr env expr = fromEgisonM $ evalExprDeep env expr -readCounter :: IO Int-readCounter = readIORef counter+-- |eval an Egison top expression+evalEgisonTopExpr :: Env -> EgisonTopExpr -> IO (Either EgisonError Env)+evalEgisonTopExpr env exprs = fromEgisonM $ evalTopExpr env exprs -updateCounter :: Int -> IO ()-updateCounter = writeIORef counter+-- |eval Egison top expressions+evalEgisonTopExprs :: Env -> [EgisonTopExpr] -> IO (Either EgisonError Env)+evalEgisonTopExprs env exprs = fromEgisonM $ evalTopExprs env exprs -modifyCounter :: FreshT IO a -> IO a-modifyCounter m = do-  seed <- readCounter-  (result, seed) <- runFreshT seed m -  updateCounter seed-  return result  +-- |eval an Egison expression. Input is a Haskell string.+runEgisonExpr :: Env -> String -> IO (Either EgisonError EgisonValue)+runEgisonExpr env input = fromEgisonM $ readExpr input >>= evalExprDeep env -loadLibraries :: Env -> IO Env-loadLibraries env = do-  seed <- readIORef counter-  (result, seed') <- runFreshT seed $ runEgisonM $ foldM evalTopExpr env (map Load libraries)-  writeIORef counter seed'-  case result of+-- |eval an Egison top expression. Input is a Haskell string.+runEgisonTopExpr :: Env -> String -> IO (Either EgisonError Env)+runEgisonTopExpr env input = fromEgisonM $ readTopExpr input >>= evalTopExpr env++-- |eval Egison top expressions. Input is a Haskell string.+runEgisonTopExprs :: Env -> String -> IO (Either EgisonError Env)+runEgisonTopExprs env input = fromEgisonM $ readTopExprs input >>= evalTopExprs env++loadCoreLibraries :: Env -> IO Env+loadCoreLibraries env = do+  ret <- evalEgisonTopExprs env $ map Load libraries+  case ret of     Left err -> do       print . show $ err       return env-    Right env' -> -      return env'+    Right env' -> return env'   where     libraries :: [String]     libraries = [ "lib/core/base.egi"@@ -73,29 +85,9 @@                 , "lib/core/io.egi"                  ] -fromEgisonM :: EgisonM a -> IO (Either EgisonError a)-fromEgisonM = modifyCounter . runEgisonM--loadPrimitives :: Env -> IO Env-loadPrimitives env = (++) <$> return env <*> primitiveEnv-   loadEgisonFile :: Env -> FilePath -> IO (Either EgisonError Env)-loadEgisonFile env path = modifyCounter $ runEgisonM $ loadFile path >>= evalTopExprs env+loadEgisonFile env path = evalEgisonTopExpr env (LoadFile path)  loadEgisonLibrary :: Env -> FilePath -> IO (Either EgisonError Env)-loadEgisonLibrary env path = modifyCounter $ runEgisonM $ loadLibraryFile path >>= evalTopExprs env--evalEgisonExpr :: Env -> EgisonExpr -> IO (Either EgisonError EgisonValue)-evalEgisonExpr env expr = modifyCounter $ runEgisonM $ evalExpr' env expr--evalEgisonTopExpr :: Env -> EgisonTopExpr -> IO (Either EgisonError Env)-evalEgisonTopExpr env exprs = modifyCounter $ runEgisonM $ evalTopExpr env exprs--evalEgisonTopExprs :: Env -> [EgisonTopExpr] -> IO (Either EgisonError Env)-evalEgisonTopExprs env exprs = modifyCounter $ runEgisonM $ evalTopExprs env exprs--runEgisonTopExpr :: Env -> String -> IO (Either EgisonError Env)-runEgisonTopExpr env input = modifyCounter $ runEgisonM $ readTopExpr input >>= evalTopExpr env+loadEgisonLibrary env path = evalEgisonTopExpr env (Load path) -runEgisonTopExprs :: Env -> String -> IO (Either EgisonError Env)-runEgisonTopExprs env input = modifyCounter $ runEgisonM $ readTopExprs input >>= evalTopExprs env
hs-src/Language/Egison/Core.hs view
@@ -1,6 +1,34 @@ {-# Language TupleSections #-}-module Language.Egison.Core where +{- |+Module      : Language.Egison.Core+Copyright   : Satoshi Egi+Licence     : MIT++This module provides functions to evaluate various objects.+-}++module Language.Egison.Core+    (+    -- * Egison code evaluation+      evalTopExprs+    , evalTopExpr+    , evalTopExpr'+    , evalExpr+    , evalExprDeep+    , evalRef+    , evalRefDeep+    , evalWHNF+    , applyFunc+    -- * Environment+    , recursiveBind+    -- * Pattern matching+    , patternMatch+    -- * Utiltiy functions+    , fromStringWHNF+    , fromStringValue+    ) where+ import Prelude hiding (mapM)  import Control.Arrow@@ -11,6 +39,7 @@  import Data.Sequence (Seq, ViewL(..), ViewR(..), (><)) import qualified Data.Sequence as Sq+import Data.Foldable (toList) import Data.Traversable (mapM) import Data.IORef import Data.List@@ -40,7 +69,7 @@ evalTopExprs env exprs = do   (bindings, rest) <- collectDefs exprs [] []   env <- recursiveBind env bindings-  forM_ rest $ evalTopExpr env+  forM_ rest $ evalTopExpr' env   return env  where   collectDefs (expr:exprs) bindings rest =@@ -56,22 +85,30 @@   collectDefs [] bindings rest = return (bindings, reverse rest)  evalTopExpr :: Env -> EgisonTopExpr -> EgisonM Env-evalTopExpr env (Define name expr) = recursiveBind env [(name, expr)]-evalTopExpr env (Test expr) = do-  val <- evalExpr' env expr-  liftIO $ print val-  return env-evalTopExpr env (Execute expr) = do+evalTopExpr env topExpr = evalTopExpr'' env topExpr >>= return . snd++evalTopExpr' :: Env -> EgisonTopExpr -> EgisonM Env+evalTopExpr' env topExpr = do+  ret <- evalTopExpr'' env topExpr+  liftIO $ putStrLn $ fst ret+  return $ snd ret++evalTopExpr'' :: Env -> EgisonTopExpr -> EgisonM (String, Env)+evalTopExpr'' env (Define name expr) = recursiveBind env [(name, expr)] >>= return . ((,) "")+evalTopExpr'' env (Test expr) = do+  val <- evalExprDeep env expr+  return ((show val), env)+evalTopExpr'' env (Execute expr) = do   io <- evalExpr env expr   case io of-    Value (IOFunc m) -> m >> return env+    Value (IOFunc m) -> m >> return ("", env)     _ -> throwError $ TypeMismatch "io" io-evalTopExpr env (Load file) = loadLibraryFile file >>= evalTopExprs env-evalTopExpr env (LoadFile file) = loadFile file >>= evalTopExprs env+evalTopExpr'' env (Load file) = loadLibraryFile file >>= evalTopExprs env >>= return . ((,) "")+evalTopExpr'' env (LoadFile file) = loadFile file >>= evalTopExprs env >>= return . ((,) "")  evalExpr :: Env -> EgisonExpr -> EgisonM WHNFData evalExpr _ (CharExpr c) = return . Value $ Char c-evalExpr _ (StringExpr s) = return $ Value $ makeStringValue s+evalExpr _ (StringExpr s) = return $ Value $ toEgison s evalExpr _ (BoolExpr b) = return . Value $ Bool b evalExpr _ (RationalExpr x) = return . Value $ Rational x evalExpr _ (IntegerExpr i) = return . Value $ Integer i@@ -85,8 +122,7 @@  evalExpr _ (TupleExpr []) = return . Value $ Tuple [] evalExpr env (TupleExpr [expr]) = evalExpr env expr-evalExpr env (TupleExpr exprs) =-  Intermediate . ITuple <$> mapM (newThunk env) exprs +evalExpr env (TupleExpr exprs) = Intermediate . ITuple <$> mapM (newThunk env) exprs  evalExpr env (CollectionExpr inners) =   if Sq.null inners then@@ -103,8 +139,8 @@  evalExpr env (HashExpr assocs) = do   let (keyExprs, exprs) = unzip assocs-  keyVals <- mapM (evalExpr' env) keyExprs-  keys <- liftError $ mapM makeKey keyVals+  keyWhnfs <- mapM (evalExpr env) keyExprs+  keys <- mapM makeHashKey keyWhnfs   refs <- mapM (newThunk env) exprs   case head keys of     IntKey _ -> do@@ -115,41 +151,53 @@       let keys' = map (\key -> case key of                                  StrKey s -> s) keys       return . Intermediate . IStrHash $ HL.fromList $ zip keys' refs+ where+  makeHashKey :: WHNFData -> EgisonM EgisonHashKey+  makeHashKey (Value val) =+    case val of+      Integer i -> return (IntKey i)+      Collection _ -> do+        str <- fromStringWHNF $ Value val+        return $ StrKey $ B.pack str+      _ -> throwError $ TypeMismatch "integer or string" $ Value val+  makeHashKey whnf = do+    str <- fromStringWHNF whnf+    return $ StrKey $ B.pack str  evalExpr env (IndexedExpr expr indices) = do   array <- evalExpr env expr-  indices <- mapM (evalExpr' env) indices+  indices <- mapM (evalExprDeep env) indices   refArray array indices  where   refArray :: WHNFData -> [EgisonValue] -> EgisonM WHNFData   refArray val [] = return val    refArray (Value (Array array)) (index:indices) = do-    i <- (liftError . liftM fromInteger . fromIntegerValue) (Value index)+    i <- (liftM fromInteger . fromEgison) index     case IntMap.lookup i array of       Just val -> refArray (Value val) indices       Nothing -> return $ Value Undefined   refArray (Intermediate (IArray array)) (index:indices) = do-    i <- (liftError . liftM fromInteger . fromIntegerValue) (Value index)+    i <- (liftM fromInteger . fromEgison) index     case IntMap.lookup i array of       Just ref -> evalRef ref >>= flip refArray indices       Nothing -> return $ Value Undefined   refArray (Value (IntHash hash)) (index:indices) = do-    key <- liftError $ fromIntegerValue $ Value index+    key <- fromEgison index     case HL.lookup key hash of       Just val -> refArray (Value val) indices       Nothing -> return $ Value Undefined   refArray (Intermediate (IIntHash hash)) (index:indices) = do-    key <- liftError $ fromIntegerValue $ Value index+    key <- fromEgison index     case HL.lookup key hash of       Just ref -> evalRef ref >>= flip refArray indices       Nothing -> return $ Value Undefined   refArray (Value (StrHash hash)) (index:indices) = do-    key <- liftError $ fromStringValue $ Value index+    key <- fromStringWHNF $ Value index     case HL.lookup (B.pack key) hash of       Just val -> refArray (Value val) indices       Nothing -> return $ Value Undefined   refArray (Intermediate (IStrHash hash)) (index:indices) = do-    key <- liftError $ fromStringValue $ Value index+    key <- fromStringWHNF $ Value index     case HL.lookup (B.pack key) hash of       Just ref -> evalRef ref >>= flip refArray indices       Nothing -> return $ Value Undefined@@ -159,7 +207,7 @@ evalExpr env (PatternFunctionExpr names pattern) = return . Value $ PatternFunc env names pattern  evalExpr env (IfExpr test expr expr') = do-  test <- evalExpr env test >>= liftError . fromBoolValue+  test <- evalExpr env test >>= fromWHNF   evalExpr env $ if test then expr else expr'  evalExpr env (LetExpr bindings expr) =@@ -203,7 +251,7 @@   io <- evalExpr env expr   case io of     Value (IOFunc m) -> do-      val <- m >>= evalDeep+      val <- m >>= evalWHNF       case val of         Tuple [_, val'] -> return $ Value val'     _ -> throwError $ TypeMismatch "io" io@@ -258,8 +306,8 @@ evalExpr _ UndefinedExpr = return $ Value Undefined evalExpr _ expr = throwError $ NotImplemented ("evalExpr for " ++ show expr) -evalExpr' :: Env -> EgisonExpr -> EgisonM EgisonValue-evalExpr' env expr = evalExpr env expr >>= evalDeep+evalExprDeep :: Env -> EgisonExpr -> EgisonM EgisonValue+evalExprDeep env expr = evalExpr env expr >>= evalWHNF  evalRef :: ObjectRef -> EgisonM WHNFData evalRef ref = do@@ -271,35 +319,36 @@       writeThunk ref val       return val -evalRef' :: ObjectRef -> EgisonM EgisonValue-evalRef' ref = do+evalRefDeep :: ObjectRef -> EgisonM EgisonValue+evalRefDeep ref = do   obj <- liftIO $ readIORef ref   case obj of     WHNF (Value val) -> return val     WHNF val -> do-      val <- evalDeep val+      val <- evalWHNF val       writeThunk ref $ Value val       return val     Thunk thunk -> do-      val <- thunk >>= evalDeep+      val <- thunk >>= evalWHNF       writeThunk ref $ Value val       return val -evalDeep :: WHNFData -> EgisonM EgisonValue-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+evalWHNF :: WHNFData -> EgisonM EgisonValue+evalWHNF (Value val) = return val+evalWHNF (Intermediate (IInductiveData name refs)) =+  InductiveData name <$> mapM evalRefDeep refs+evalWHNF (Intermediate (IArray refs)) = do+  refs' <- mapM evalRefDeep $ IntMap.elems refs   return $ Array $ IntMap.fromList $ zip (enumFromTo 1 (IntMap.size refs)) refs'-evalDeep (Intermediate (IIntHash refs)) = do-  refs' <- mapM evalRef' refs+evalWHNF (Intermediate (IIntHash refs)) = do+  refs' <- mapM evalRefDeep refs   return $ IntHash refs'-evalDeep (Intermediate (IStrHash refs)) = do-  refs' <- mapM evalRef' refs+evalWHNF (Intermediate (IStrHash refs)) = do+  refs' <- mapM evalRefDeep refs   return $ StrHash refs'-evalDeep (Intermediate (ITuple refs)) = Tuple <$> mapM evalRef' refs-evalDeep coll = Collection <$> (fromCollection coll >>= fromMList >>= mapM evalRef' . Sq.fromList)+evalWHNF (Intermediate (ITuple [ref])) = evalRefDeep ref+evalWHNF (Intermediate (ITuple refs)) = Tuple <$> mapM evalRefDeep refs+evalWHNF coll = Collection <$> (fromCollection coll >>= fromMList >>= mapM evalRefDeep . Sq.fromList)  applyFunc :: WHNFData -> WHNFData -> EgisonM WHNFData applyFunc (Value (Func env [name] body)) arg = do@@ -311,9 +360,8 @@     then evalExpr (extendEnv env $ makeBindings names refs) body     else throwError $ ArgumentsNum (length names) (length refs) applyFunc (Value (PrimitiveFunc func)) arg = do---  fromTuple arg >>= mapM evalRef >>= liftM Value . func-  arg' <- fromTuple arg >>= mapM evalRef'-  liftM Value . func $ map Value arg'+  arg' <- evalWHNF arg+  liftM Value . func $ arg' applyFunc (Value (IOFunc m)) arg = do   case arg of      Value World -> m@@ -322,7 +370,7 @@  generateArray :: Env -> String -> EgisonExpr -> EgisonExpr -> EgisonM WHNFData generateArray env name size expr = do  -  size' <- evalExpr env size >>= either throwError (return . fromInteger) . fromIntegerValue+  size' <- evalExpr env size >>= fromWHNF >>= return . fromInteger   elems <- mapM genElem (enumFromTo 1 size')   return $ Intermediate $ IArray $ IntMap.fromList elems   where@@ -356,32 +404,6 @@   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-fromTuple val = return <$> newEvaluatedThunk val--fromCollection :: WHNFData -> EgisonM (MList EgisonM ObjectRef)-fromCollection (Value (Collection vals)) =-  if Sq.null vals then return MNil-                  else fromSeq <$> mapM (newEvaluatedThunk . Value) vals-fromCollection coll@(Intermediate (ICollection _)) =-  newEvaluatedThunk coll >>= fromCollection'- where-  fromCollection' ref = do-    isEmpty <- isEmptyCollection ref-    if isEmpty-      then return MNil-      else do-        (head, tail) <- fromJust <$> runMaybeT (unconsCollection ref)-        return $ MCons head (fromCollection' tail)-fromCollection val = throwError $ TypeMismatch "collection" val- -- -- Pattern Match --@@ -448,10 +470,10 @@         _ -> throwError $ TypeMismatch "pattern constructor" func          LoopPat name (LoopRangeConstant start end) pat pat' -> do-      startNum' <- evalExpr' env' start-      startNum <- extractInteger startNum'-      endNum' <- evalExpr' env' end-      endNum <- extractInteger endNum'+      startNum' <- evalExpr env' start+      startNum <- fromWHNF startNum'+      endNum' <- evalExpr env' end+      endNum <- fromWHNF endNum'       if startNum > endNum         then do           return $ msingleton $ MState env loops bindings (MAtom pat' target matcher : trees)@@ -460,8 +482,8 @@           let loops' = LoopContextConstant (name, startNumRef) endNum pat pat' : loops           return $ msingleton $ MState env loops' bindings (MAtom pat target matcher : trees)     LoopPat name (LoopRangeVariable start lastNumPat) pat pat' -> do-      startNum' <- evalExpr' env' start-      startNum <- extractInteger startNum'+      startNum' <- evalExpr env' start+      startNum <- fromWHNF startNum'       startNumRef <- liftIO . newIORef . WHNF $ Value $ Integer startNum       lastNumRef <- liftIO . newIORef . WHNF $ Value $ Integer (startNum - 1)       return $ fromList [MState env loops bindings (MAtom lastNumPat lastNumRef (Value Something) : MAtom pat' target matcher : trees),@@ -470,8 +492,8 @@       case loops of         [] -> throwError $ strMsg "cannot use cont pattern except in loop pattern"         LoopContextConstant (name, startNumRef) endNum pat pat' : loops -> do-          startNum' <- evalRef' startNumRef-          startNum <- extractInteger startNum'+          startNum' <- evalRef startNumRef+          startNum <- fromWHNF startNum'           let nextNum = startNum + 1           if nextNum > endNum             then return $ msingleton $ MState env loops bindings (MAtom pat' target matcher : trees)@@ -480,8 +502,8 @@               let loops' = LoopContextConstant (name, nextNumRef) endNum pat pat' : loops                return $ msingleton $ MState env loops' bindings (MAtom pat target matcher : trees)         LoopContextVariable (name, startNumRef) lastNumPat pat pat' : loops -> do-          startNum' <- evalRef' startNumRef-          startNum <- extractInteger startNum'+          startNum' <- evalRef startNumRef+          startNum <- fromWHNF startNum'           let nextNum = startNum + 1           nextNumRef <- liftIO . newIORef . WHNF $ Value $ Integer nextNum           let loops' = LoopContextVariable (name, nextNumRef) lastNumPat pat pat' : loops @@ -500,12 +522,10 @@       return $ fromList $ flip map patterns $ \pattern ->         MState env loops bindings (MAtom pattern target matcher : trees)     NotPat pattern -> throwError $ strMsg "should not reach here (cut pattern)"-    CutPat pattern -> -- TEMPORARY ignoring cut patterns-      return $ msingleton (MState env loops bindings ((MAtom pattern target matcher):trees))     PredPat pred -> do       func <- evalExpr env' pred       arg <- evalRef target-      result <- applyFunc func arg >>= liftError . fromBoolValue+      result <- applyFunc func arg >>= fromWHNF       if result then return $ msingleton $ (MState env loops bindings trees)                 else return MNil     LetPat bindings' pattern ->@@ -528,15 +548,15 @@         _ -> -- Value Something -> -- for tupple patterns           case pattern of             ValuePat valExpr -> do-              val <- evalExpr' env' valExpr-              tgtVal <- evalRef' target+              val <- evalExprDeep env' valExpr+              tgtVal <- evalRefDeep target               if val == tgtVal                 then return $ msingleton $ MState env loops bindings trees                 else return MNil             WildCard -> return $ msingleton $ MState env loops bindings trees             PatVar name -> return $ msingleton $ MState env loops ((name, target):bindings) trees             IndexedPat (PatVar name) indices -> do-              indices <- mapM (evalExpr env' >=> liftError . liftM fromInteger . fromIntegerValue) indices+              indices <- mapM (evalExpr env' >=> liftM fromInteger . fromWHNF) indices               case lookup name bindings of                 Just ref -> do                   obj <- evalRef ref >>= flip updateArray indices >>= newEvaluatedThunk@@ -589,7 +609,7 @@               let env'' = extendEnv env' (bindings' ++ map (\lc -> case lc of                                                                      (LoopContextConstant binding _ _ _) -> binding                                                                      (LoopContextVariable binding _ _ _) -> binding) loops')-              indices <- mapM (evalExpr env'' >=> liftError . liftM fromInteger . fromIntegerValue) indices+              indices <- mapM (evalExpr env'' >=> liftM fromInteger . fromWHNF) indices               let pattern' = IndexedPat pattern $ map IntegerExpr indices               return $ msingleton $ MState env loops bindings (MAtom pattern' target matcher:MNode penv (MState env' loops' bindings' trees'):trees)             Nothing -> throwError $ UnboundVariable name@@ -657,8 +677,8 @@   (++) <$> primitiveDataPatternMatch pattern init        <*> primitiveDataPatternMatch pattern' last primitiveDataPatternMatch (PDConstantPat expr) ref = do-  target <- lift (evalRef ref) >>= either (const matchFail) return . fromPrimitiveValue-  isEqual <- lift $ (==) <$> evalExpr' nullEnv expr <*> pure target+  target <- lift (evalRef ref) >>= either (const matchFail) return . fromBuiltinWHNF+  isEqual <- lift $ (==) <$> evalExprDeep nullEnv expr <*> pure target   if isEqual then return [] else matchFail  expandCollection :: WHNFData -> EgisonM (Seq Inner)@@ -726,3 +746,51 @@        lift $ writeThunk ref coll        unsnocCollection' coll   unsnocCollection' _ = matchFail++--+-- Util+--+fromTuple :: WHNFData -> EgisonM [ObjectRef]+fromTuple (Intermediate (ITuple refs)) = return refs+fromTuple (Value (Tuple vals)) = mapM (newEvaluatedThunk . Value) vals+fromTuple val = return <$> newEvaluatedThunk val++fromCollection :: WHNFData -> EgisonM (MList EgisonM ObjectRef)+fromCollection (Value (Collection vals)) =+  if Sq.null vals then return MNil+                  else fromSeq <$> mapM (newEvaluatedThunk . Value) vals+fromCollection coll@(Intermediate (ICollection _)) =+  newEvaluatedThunk coll >>= fromCollection'+ where+  fromCollection' ref = do+    isEmpty <- isEmptyCollection ref+    if isEmpty+      then return MNil+      else do+        (head, tail) <- fromJust <$> runMaybeT (unconsCollection ref)+        return $ MCons head (fromCollection' tail)+fromCollection val = throwError $ TypeMismatch "collection" val++--+-- String+--+fromStringWHNF :: WHNFData -> EgisonM String+fromStringWHNF (Value (Collection seq)) = do+  let ls = toList seq+  mapM (\val -> case val of+                  Char c -> return c+                  _ -> throwError $ TypeMismatch "char" (Value val))+       ls+fromStringWHNF (Value (Tuple [val])) = fromStringWHNF (Value val)+fromStringWHNF whnf@(Intermediate (ICollection _)) = evalWHNF whnf >>= fromStringWHNF . Value+fromStringWHNF whnf = throwError $ TypeMismatch "string" whnf++fromStringValue :: EgisonValue -> EgisonM String+fromStringValue (Collection seq) = do+  let ls = toList seq+  mapM (\val -> case val of+                  Char c -> return c+                  _ -> throwError $ TypeMismatch "char" (Value val))+       ls+fromStringValue (Tuple [val]) = fromStringValue val+fromStringValue val = throwError $ TypeMismatch "string" (Value val)
hs-src/Language/Egison/Desugar.hs view
@@ -1,5 +1,21 @@ {-# Language FlexibleInstances, GeneralizedNewtypeDeriving #-}-module Language.Egison.Desugar where++{- |+Module      : Language.Egison.Desugar+Copyright   : Satoshi Egi+Licence     : MIT++This module provide desugar functions.+-}++module Language.Egison.Desugar+    (+      DesugarM+    , runDesugarM+    , desugarTopExpr+    , desugar+    ) where+ import Control.Applicative (Applicative) import Control.Applicative ((<$>), (<*>), (<*), (*>), pure) import qualified Data.Sequence as Sq@@ -193,7 +209,6 @@    collectNames patterns = S.unions $ map collectName patterns     collectName :: EgisonPattern -> Set String-   collectName (CutPat pattern) = collectName pattern     collectName (NotPat pattern) = collectName pattern    collectName (AndPat patterns) = collectNames patterns    collectName (TuplePat patterns) = collectNames patterns@@ -211,7 +226,6 @@ desugarPattern' :: EgisonPattern -> DesugarM EgisonPattern desugarPattern' (ValuePat expr) = ValuePat <$> desugar expr desugarPattern' (PredPat expr) = PredPat <$> desugar expr-desugarPattern' (CutPat pattern) = CutPat <$> desugarPattern' pattern desugarPattern' (NotPat pattern) = NotPat <$> desugarPattern' pattern desugarPattern' (AndPat patterns) = AndPat <$> mapM desugarPattern' patterns desugarPattern' (TuplePat patterns)  = TuplePat <$> mapM desugarPattern' patterns
hs-src/Language/Egison/Parser.hs view
@@ -1,15 +1,24 @@ {-# LANGUAGE TupleSections #-}++{- |+Module      : Language.Egison.Parser+Copyright   : Satoshi Egi+Licence     : MIT++This module provide Egison parser.+-}+ module Language.Egison.Parser -       ( readTopExprs+       (+       -- * Parse a string+         readTopExprs        , readTopExpr        , readExprs        , readExpr-       , loadFile+       -- * Parse a file        , loadLibraryFile-       , parseTopExprs-       , parseTopExpr-       , parseExprs-       , parseExpr ) where+       , loadFile+       ) where  import Prelude hiding (mapM) import Control.Monad.Identity hiding (mapM)@@ -36,12 +45,6 @@ import Language.Egison.Types import Language.Egison.Desugar import Paths_egison (getDataFileName)-  -doParse :: Parser a -> String -> Either EgisonError a-doParse p input = either (throwError . fromParsecError) return $ parse p "egison" input-  where-    fromParsecError :: ParseError -> EgisonError-    fromParsecError = Parser . show  readTopExprs :: String -> EgisonM [EgisonTopExpr] readTopExprs = liftEgisonM . runDesugarM . either throwError (mapM desugarTopExpr) . parseTopExprs@@ -55,6 +58,11 @@ readExpr :: String -> EgisonM EgisonExpr readExpr = liftEgisonM . runDesugarM . either throwError desugar . parseExpr +-- |Load a libary file+loadLibraryFile :: FilePath -> EgisonM [EgisonTopExpr]+loadLibraryFile file = liftIO (getDataFileName file) >>= loadFile++-- |Load a file loadFile :: FilePath -> EgisonM [EgisonTopExpr] loadFile file = do   doesExist <- liftIO $ doesFileExist file@@ -70,9 +78,15 @@   shebang ('#':'!':cs) = ';':'#':'!':cs   shebang cs = cs +--+-- Parser+-- -loadLibraryFile :: FilePath -> EgisonM [EgisonTopExpr]-loadLibraryFile file = liftIO (getDataFileName file) >>= loadFile+doParse :: Parser a -> String -> Either EgisonError a+doParse p input = either (throwError . fromParsecError) return $ parse p "egison" input+  where+    fromParsecError :: ParseError -> EgisonError+    fromParsecError = Parser . show  parseTopExprs :: String -> Either EgisonError [EgisonTopExpr] parseTopExprs = doParse $ whiteSpace >> endBy topExpr whiteSpace@@ -89,7 +103,6 @@ -- -- Expressions --- topExpr :: Parser EgisonTopExpr topExpr = parens (defineExpr               <|> testExpr@@ -334,7 +347,6 @@             <|> varPat             <|> valuePat             <|> predPat-            <|> cutPat             <|> notPat             <|> tuplePat             <|> inductivePat@@ -363,9 +375,6 @@ letPat :: Parser EgisonPattern letPat = keywordLet >> LetPat <$> bindings <*> pattern -cutPat :: Parser EgisonPattern-cutPat = reservedOp "!" >> CutPat <$> pattern- notPat :: Parser EgisonPattern notPat = reservedOp "^" >> NotPat <$> pattern @@ -487,7 +496,6 @@   , "&"   , "|"   , "^"-  , "!"   , ","   , "@"   , "..."]
hs-src/Language/Egison/Primitives.hs view
@@ -1,4 +1,13 @@ {-# Language FlexibleContexts #-}++{- |+Module      : Language.Egison.Primitives+Copyright   : Satoshi Egi+Licence     : MIT++This module provides primitive functions in Egison.+-}+ module Language.Egison.Primitives (primitiveEnv, primitiveEnvNoIO) where  import Control.Arrow@@ -51,38 +60,37 @@   return $ extendEnv nullEnv bindings  {-# INLINE noArg #-}-noArg :: (MonadError EgisonError m) =>-         m EgisonValue ->-         [WHNFData] -> m EgisonValue-noArg f = \vals -> case vals of +noArg :: EgisonM EgisonValue ->+         EgisonValue -> EgisonM EgisonValue+noArg f = \args -> case tupleToList args of                       [] -> f-                     _ -> throwError $ ArgumentsNum 0 $ length vals+                     vals -> throwError $ ArgumentsNum 0 $ length vals  {-# INLINE oneArg #-}-oneArg :: (MonadError EgisonError m) =>-          (WHNFData -> m EgisonValue) ->-          [WHNFData] -> m EgisonValue-oneArg f = \vals -> case vals of -                      [val] -> f val-                      [] -> f $ Value $ Tuple []-                      _ -> throwError $ ArgumentsNum 1 $ length vals+oneArg :: (EgisonValue -> EgisonM EgisonValue) ->+          EgisonValue -> EgisonM EgisonValue+oneArg f = \args -> case args of+                      (Tuple [val]) -> f val+                      _ -> f args  {-# INLINE twoArgs #-}-twoArgs :: (MonadError EgisonError m) =>-           (WHNFData -> WHNFData -> m EgisonValue) ->-           [WHNFData] -> m EgisonValue-twoArgs f = \vals -> case vals of +twoArgs :: (EgisonValue -> EgisonValue -> EgisonM EgisonValue) ->+           EgisonValue -> EgisonM EgisonValue+twoArgs f = \args -> case tupleToList args of                         [val, val'] -> f val val'-                       _ -> throwError $ ArgumentsNum 2 $ length vals+                       vals -> throwError $ ArgumentsNum 2 $ length vals  {-# INLINE threeArgs #-}-threeArgs :: (MonadError EgisonError m) =>-             (WHNFData -> WHNFData -> WHNFData -> m EgisonValue) ->-             [WHNFData] -> m EgisonValue-threeArgs f = \vals -> case vals of +threeArgs :: (EgisonValue -> EgisonValue -> EgisonValue -> EgisonM EgisonValue) ->+             EgisonValue -> EgisonM EgisonValue+threeArgs f = \args -> case tupleToList args of                           [val, val', val''] -> f val val' val''-                         _ -> throwError $ ArgumentsNum 3 $ length vals+                         vals -> throwError $ ArgumentsNum 3 $ length vals +tupleToList :: EgisonValue -> [EgisonValue]+tupleToList (Tuple vals) = vals+tupleToList val = [val]+ -- -- Constants --@@ -95,28 +103,29 @@ --  primitives :: [(String, PrimitiveFunc)]-primitives = [ ("+i", integerBinaryOp (+)) -             , ("-i", integerBinaryOp (-))-             , ("*i", integerBinaryOp (*))+primitives = [ ("+", plus)+             , ("-", minus)+             , ("*", multiply)+             , ("/", divide)+             , ("/-inverse", divideInverse)+                             , ("modulo",    integerBinaryOp mod)              , ("quotient",   integerBinaryOp quot)              , ("remainder", integerBinaryOp rem)-             , ("eq-i?",  integerBinaryPred (==))-             , ("lt-i?",  integerBinaryPred (<))-             , ("lte-i?", integerBinaryPred (<=))-             , ("gt-i?",  integerBinaryPred (>))-             , ("gte-i?", integerBinaryPred (>=))-             , ("+f", floatBinaryOp (+))-             , ("-f", floatBinaryOp (-))-             , ("*f", floatBinaryOp (*))-             , ("/f", floatBinaryOp (/))-             , ("eq-f?",  floatBinaryPred (==))-             , ("lt-f?",  floatBinaryPred (<))-             , ("lte-f?", floatBinaryPred (<=))-             , ("gt-f?",  floatBinaryPred (>))-             , ("gte-f?", floatBinaryPred (>=))              , ("neg", integerUnaryOp negate)              , ("abs", integerUnaryOp abs)+               +             , ("eq?",  eq)+             , ("lt?",  lt)+             , ("lte?", lte)+             , ("gt?",  gt)+             , ("gte?", gte)+               +             , ("round",    floatToIntegerOp round)+             , ("floor",    floatToIntegerOp floor)+             , ("ceiling",  floatToIntegerOp ceiling)+             , ("truncate", floatToIntegerOp truncate)+                             , ("sqrt", floatUnaryOp sqrt)              , ("exp", floatUnaryOp exp)              , ("log", floatUnaryOp log)@@ -132,24 +141,15 @@              , ("asinh", floatUnaryOp asinh)              , ("acosh", floatUnaryOp acosh)              , ("atanh", floatUnaryOp atanh)-             , ("round",    floatToIntegerOp round)-             , ("floor",    floatToIntegerOp floor)-             , ("ceiling",  floatToIntegerOp ceiling)-             , ("truncate", floatToIntegerOp truncate)+                             , ("itof", integerToFloat)              , ("rtof", rationalToFloat)-             , ("itos", integerToString)+                             , ("stoi", stringToInteger)-             , ("eq?",  eq)-             , ("lt?",  lt)-             , ("lte?", lte)-             , ("gt?",  gt)-             , ("gte?", gte)-             , ("+", plus)-             , ("-", minus)-             , ("*", multiply)-             , ("/", divide)-             , ("/-inverse", divideInverse)+               +             , ("read", read')+             , ("show", show')+                             , ("assert", assert)              , ("assert-equal", assertEqual) @@ -163,194 +163,224 @@              ]  integerUnaryOp :: (Integer -> Integer) -> PrimitiveFunc-integerUnaryOp op = (liftError .) $ oneArg $ \val ->-  Integer . op <$> fromIntegerValue val-+integerUnaryOp op = oneArg $ \val -> do+  i <- fromEgison val+  return $ Integer $ op i+   integerBinaryOp :: (Integer -> Integer -> Integer) -> PrimitiveFunc-integerBinaryOp op = (liftError .) $ twoArgs $ \val val' ->-  (Integer .) . op <$> fromIntegerValue val-                   <*> fromIntegerValue val'+integerBinaryOp op = twoArgs $ \val val' -> do+  i <- fromEgison val+  i' <- fromEgison val'+  return $ Integer $ op i i'  integerBinaryPred :: (Integer -> Integer -> Bool) -> PrimitiveFunc-integerBinaryPred pred = (liftError .) $ twoArgs $ \val val' ->-  (Bool .) . pred <$> fromIntegerValue val-                  <*> fromIntegerValue val'+integerBinaryPred pred = twoArgs $ \val val' -> do+  i <- fromEgison val+  i' <- fromEgison val'+  return $ Bool $ pred i i'  floatUnaryOp :: (Double -> Double) -> PrimitiveFunc-floatUnaryOp op = (liftError .) $ oneArg $ \val ->-  Float . op <$> fromFloatValue val+floatUnaryOp op = oneArg $ \val -> do+  f <- fromEgison val+  return $ Float $ op f  floatBinaryOp :: (Double -> Double -> Double) -> PrimitiveFunc-floatBinaryOp op = (liftError .) $ twoArgs $ \val val' ->-  (Float .) . op <$> fromFloatValue val-                 <*> fromFloatValue val'+floatBinaryOp op = twoArgs $ \val val' -> do+  f <- fromEgison val+  f' <- fromEgison val'+  return $ Float $ op f f'  floatBinaryPred :: (Double -> Double -> Bool) -> PrimitiveFunc-floatBinaryPred pred = (liftError .) $ twoArgs $ \val val' ->-  (Bool .) . pred <$> fromFloatValue val-                  <*> fromFloatValue val'+floatBinaryPred pred = twoArgs $ \val val' -> do+  f <- fromEgison val+  f' <- fromEgison val'+  return $ Bool $ pred f f' -floatToIntegerOp :: (Double -> Integer) -> PrimitiveFunc-floatToIntegerOp op = (liftError .) $ oneArg $ \val ->-  Integer . op <$> fromFloatValue val+--+-- Arith+--+plus :: PrimitiveFunc+plus = twoArgs $ \val val' -> numberBinaryOp' val val'+ where+  numberBinaryOp' (Integer i)  (Integer i')  = return $ Integer $ (+) i  i'+  numberBinaryOp' (Integer i)  val           = numberBinaryOp' (Rational (i % 1)) val+  numberBinaryOp' val          (Integer i)   = numberBinaryOp' val (Rational (i % 1)) +  numberBinaryOp' (Rational r) (Rational r') = let y = (+) r r' in+                                                 if denominator y == 1+                                                   then return $ Integer $ numerator y+                                                   else return $ Rational y+  numberBinaryOp' (Rational r) (Float f)     = numberBinaryOp' (Float (fromRational r)) (Float f)+  numberBinaryOp' (Float f)    (Rational r)  = numberBinaryOp' (Float f) (Float (fromRational r))+  numberBinaryOp' (Float f)    (Float f')    = return $ Float $ (+) f f'+  numberBinaryOp' (Rational _) val           = throwError $ TypeMismatch "number" (Value val)+  numberBinaryOp' (Float _)    val           = throwError $ TypeMismatch "number" (Value val)+  numberBinaryOp' val          _             = throwError $ TypeMismatch "number" (Value val) -integerToFloat :: PrimitiveFunc-integerToFloat = (liftError .) $ oneArg $ \val ->-  Float . fromInteger <$> fromIntegerValue val+minus :: PrimitiveFunc+minus = twoArgs $ \val val' -> numberBinaryOp' val val'+ where+  numberBinaryOp' (Integer i)  (Integer i')  = return $ Integer $ (-) i  i'+  numberBinaryOp' (Integer i)  val           = numberBinaryOp' (Rational (i % 1)) val+  numberBinaryOp' val          (Integer i)   = numberBinaryOp' val (Rational (i % 1)) +  numberBinaryOp' (Rational r) (Rational r') = let y = (-) r r' in+                                                 if denominator y == 1+                                                   then return $ Integer $ numerator y+                                                   else return $ Rational y+  numberBinaryOp' (Rational r) (Float f)     = numberBinaryOp' (Float (fromRational r)) (Float f)+  numberBinaryOp' (Float f)    (Rational r)  = numberBinaryOp' (Float f) (Float (fromRational r))+  numberBinaryOp' (Float f)    (Float f')    = return $ Float $ (-) f f'+  numberBinaryOp' (Rational _) val           = throwError $ TypeMismatch "number" (Value val)+  numberBinaryOp' (Float _)    val           = throwError $ TypeMismatch "number" (Value val)+  numberBinaryOp' val          _             = throwError $ TypeMismatch "number" (Value val) -rationalToFloat :: PrimitiveFunc-rationalToFloat = (liftError .) $ oneArg $ \val ->-  Float . fromRational <$> fromRationalValue val+multiply :: PrimitiveFunc+multiply = twoArgs $ \val val' -> numberBinaryOp' val val'+ where+  numberBinaryOp' (Integer i)  (Integer i')  = return $ Integer $ (*) i  i'+  numberBinaryOp' (Integer i)  val           = numberBinaryOp' (Rational (i % 1)) val+  numberBinaryOp' val          (Integer i)   = numberBinaryOp' val (Rational (i % 1)) +  numberBinaryOp' (Rational r) (Rational r') = let y = (*) r r' in+                                                 if denominator y == 1+                                                   then return $ Integer $ numerator y+                                                   else return $ Rational y+  numberBinaryOp' (Rational r) (Float f)     = numberBinaryOp' (Float (fromRational r)) (Float f)+  numberBinaryOp' (Float f)    (Rational r)  = numberBinaryOp' (Float f) (Float (fromRational r))+  numberBinaryOp' (Float f)    (Float f')    = return $ Float $ (*) f f'+  numberBinaryOp' (Rational _) val           = throwError $ TypeMismatch "number" (Value val)+  numberBinaryOp' (Float _)    val           = throwError $ TypeMismatch "number" (Value val)+  numberBinaryOp' val          _             = throwError $ TypeMismatch "number" (Value val) -integerToString :: PrimitiveFunc-integerToString = (liftError .) $ oneArg $ \val ->-   makeStringValue . show <$> fromIntegerValue val+divide :: PrimitiveFunc+divide = twoArgs $ \val val' -> numberBinaryOp' val val'+ where+  numberBinaryOp' (Integer i)  (Integer i')  = return $ Rational $ (%) i  i'+  numberBinaryOp' (Integer i)  val           = numberBinaryOp' (Rational (i % 1)) val+  numberBinaryOp' val          (Integer i)   = numberBinaryOp' val (Rational (i % 1)) +  numberBinaryOp' (Rational r) (Rational r') =+    let m = numerator r' in+    let n = denominator r' in+    let y = (r * (n % m)) in+      if denominator y == 1+        then return $ Integer $ numerator y+        else return $ Rational y+  numberBinaryOp' (Rational r) (Float f)    = numberBinaryOp' (Float (fromRational r)) (Float f)+  numberBinaryOp' (Float f)    (Rational r) = numberBinaryOp' (Float f) (Float (fromRational r))+  numberBinaryOp' (Float f)    (Float f')   = return $ Float $ (/) f f'+  numberBinaryOp' (Rational _) val          = throwError $ TypeMismatch "number" (Value val)+  numberBinaryOp' (Float _)    val          = throwError $ TypeMismatch "number" (Value val)+  numberBinaryOp' val          _            = throwError $ TypeMismatch "number" (Value val) -stringToInteger :: PrimitiveFunc-stringToInteger = (liftError .) $ oneArg $ \val -> do-   numStr <- fromStringValue val-   return $ Integer (read numStr :: Integer)+divideInverse :: PrimitiveFunc+divideInverse =  oneArg $ divideInverse'+ where+  divideInverse' (Rational rat) = do+    return $ Tuple [Integer (numerator rat), Integer (denominator rat)]+  divideInverse' (Integer x) = do+    return $ Tuple [Integer x, Integer 1]+  divideInverse' val = throwError $ TypeMismatch "rational" (Value val) +--+-- Pred+-- eq :: PrimitiveFunc-eq = (liftError .) $ twoArgs $ \val val' ->-  (Bool .) . (==) <$> fromPrimitiveValue val-                  <*> fromPrimitiveValue val'+eq = twoArgs $ \val val' ->+  return $ Bool $ val == val'  lt :: PrimitiveFunc-lt = (liftError .) $ twoArgs lt'+lt = twoArgs $ \val val' -> numberBinaryPred' val val'  where-  lt' (Value (Integer i)) (Value (Integer i')) = return $ Bool $ i < i'-  lt' (Value (Integer i)) (Value (Float f)) = return $ Bool $ fromInteger i < f-  lt' (Value (Float f)) (Value (Integer i)) = return $ Bool $ f < fromInteger i-  lt' (Value (Float f)) (Value (Float f')) = return $ Bool $ f < f'-  lt' (Value (Integer _)) val = throwError $ TypeMismatch "number" val-  lt' (Value (Float _)) val = throwError $ TypeMismatch "number" val-  lt' val _ = throwError $ TypeMismatch "number" val-+  numberBinaryPred' (Integer i)  (Integer i')  = return $ Bool $ (<) i  i'+  numberBinaryPred' (Integer i)  val           = numberBinaryPred' (Rational (i % 1)) val+  numberBinaryPred' val          (Integer i)   = numberBinaryPred' val (Rational (i % 1)) +  numberBinaryPred' (Rational r) (Rational r') = return $ Bool $ (<) r r'+  numberBinaryPred' (Rational r) (Float f)     = numberBinaryPred' (Float (fromRational r)) (Float f)+  numberBinaryPred' (Float f)    (Rational r)  = numberBinaryPred' (Float f) (Float (fromRational r))+  numberBinaryPred' (Float f)    (Float f')    = return $ Bool $ (<) f f'+  numberBinaryPred' (Rational _) val           = throwError $ TypeMismatch "number" (Value val)+  numberBinaryPred' (Float _)    val           = throwError $ TypeMismatch "number" (Value val)+  numberBinaryPred' val          _             = throwError $ TypeMismatch "number" (Value val)+   lte :: PrimitiveFunc-lte = (liftError .) $ twoArgs lte'+lte = twoArgs $ \val val' -> numberBinaryPred' val val'  where-  lte' (Value (Integer i)) (Value (Integer i')) = return $ Bool $ i <= i'-  lte' (Value (Integer i)) (Value (Float f)) = return $ Bool $ fromInteger i <= f-  lte' (Value (Float f)) (Value (Integer i)) = return $ Bool $ f <= fromInteger i-  lte' (Value (Float f)) (Value (Float f')) = return $ Bool $ f <= f'-  lte' (Value (Integer _)) val = throwError $ TypeMismatch "number" val-  lte' (Value (Float _)) val = throwError $ TypeMismatch "number" val-  lte' val _ = throwError $ TypeMismatch "number" val-+  numberBinaryPred' (Integer i)  (Integer i')  = return $ Bool $ (<=) i  i'+  numberBinaryPred' (Integer i)  val           = numberBinaryPred' (Rational (i % 1)) val+  numberBinaryPred' val          (Integer i)   = numberBinaryPred' val (Rational (i % 1)) +  numberBinaryPred' (Rational r) (Rational r') = return $ Bool $ (<=) r r'+  numberBinaryPred' (Rational r) (Float f)     = numberBinaryPred' (Float (fromRational r)) (Float f)+  numberBinaryPred' (Float f)    (Rational r)  = numberBinaryPred' (Float f) (Float (fromRational r))+  numberBinaryPred' (Float f)    (Float f')    = return $ Bool $ (<=) f f'+  numberBinaryPred' (Rational _) val           = throwError $ TypeMismatch "number" (Value val)+  numberBinaryPred' (Float _)    val           = throwError $ TypeMismatch "number" (Value val)+  numberBinaryPred' val          _             = throwError $ TypeMismatch "number" (Value val)+   gt :: PrimitiveFunc-gt = (liftError .) $ twoArgs gt'+gt = twoArgs $ \val val' -> numberBinaryPred' val val'  where-  gt' (Value (Integer i)) (Value (Integer i')) = return $ Bool $ i > i'-  gt' (Value (Integer i)) (Value (Float f)) = return $ Bool $ fromInteger i > f-  gt' (Value (Float f)) (Value (Integer i)) = return $ Bool $ f > fromInteger i-  gt' (Value (Float f)) (Value (Float f')) = return $ Bool $ f > f'-  gt' (Value (Integer _)) val = throwError $ TypeMismatch "number" val-  gt' (Value (Float _)) val = throwError $ TypeMismatch "number" val-  gt' val _ = throwError $ TypeMismatch "number" val-+  numberBinaryPred' (Integer i)  (Integer i')  = return $ Bool $ (>) i  i'+  numberBinaryPred' (Integer i)  val           = numberBinaryPred' (Rational (i % 1)) val+  numberBinaryPred' val          (Integer i)   = numberBinaryPred' val (Rational (i % 1)) +  numberBinaryPred' (Rational r) (Rational r') = return $ Bool $ (>) r r'+  numberBinaryPred' (Rational r) (Float f)     = numberBinaryPred' (Float (fromRational r)) (Float f)+  numberBinaryPred' (Float f)    (Rational r)  = numberBinaryPred' (Float f) (Float (fromRational r))+  numberBinaryPred' (Float f)    (Float f')    = return $ Bool $ (>) f f'+  numberBinaryPred' (Rational _) val           = throwError $ TypeMismatch "number" (Value val)+  numberBinaryPred' (Float _)    val           = throwError $ TypeMismatch "number" (Value val)+  numberBinaryPred' val          _             = throwError $ TypeMismatch "number" (Value val)+   gte :: PrimitiveFunc-gte = (liftError .) $ twoArgs gte'+gte = twoArgs $ \val val' -> numberBinaryPred' val val'  where-  gte' (Value (Integer i)) (Value (Integer i')) = return $ Bool $ i >= i'-  gte' (Value (Integer i)) (Value (Float f)) = return $ Bool $ fromInteger i >= f-  gte' (Value (Float f)) (Value (Integer i)) = return $ Bool $ f >= fromInteger i-  gte' (Value (Float f)) (Value (Float f')) = return $ Bool $ f >= f'-  gte' (Value (Integer _)) val = throwError $ TypeMismatch "number" val-  gte' (Value (Float _)) val = throwError $ TypeMismatch "number" val-  gte' val _ = throwError $ TypeMismatch "number" val+  numberBinaryPred' (Integer i)  (Integer i')  = return $ Bool $ (>=) i  i'+  numberBinaryPred' (Integer i)  val           = numberBinaryPred' (Rational (i % 1)) val+  numberBinaryPred' val          (Integer i)   = numberBinaryPred' val (Rational (i % 1)) +  numberBinaryPred' (Rational r) (Rational r') = return $ Bool $ (>=) r r'+  numberBinaryPred' (Rational r) (Float f)     = numberBinaryPred' (Float (fromRational r)) (Float f)+  numberBinaryPred' (Float f)    (Rational r)  = numberBinaryPred' (Float f) (Float (fromRational r))+  numberBinaryPred' (Float f)    (Float f')    = return $ Bool $ (>=) f f'+  numberBinaryPred' (Rational _) val           = throwError $ TypeMismatch "number" (Value val)+  numberBinaryPred' (Float _)    val           = throwError $ TypeMismatch "number" (Value val)+  numberBinaryPred' val          _             = throwError $ TypeMismatch "number" (Value val)+  +--+-- Transform+--+integerToFloat :: PrimitiveFunc+integerToFloat = oneArg $ \val -> do+  i <- fromEgison val+  return $ Float $ fromInteger i -plus :: PrimitiveFunc-plus = (liftError .) $ twoArgs plus'- where-  plus' (Value (Integer x)) (Value (Integer x')) = return $ Integer $ (x + x')-  plus' (Value (Integer i)) val = plus' (Value (Rational (i % 1))) val-  plus' val (Value (Integer i)) = plus' val (Value (Rational (i % 1)))-  plus' (Value (Rational x)) (Value (Rational x')) = let y = (x + x') in-                                                      if denominator y == 1-                                                        then return $ Integer $ numerator y-                                                        else return $ Rational y-  plus' (Value (Float f)) (Value (Float f')) = return $ Float $ f + f'-  plus' (Value (Rational i)) (Value (Float f)) = return $ Float $ (fromRational i) + f-  plus' (Value (Float f)) (Value (Rational i)) = return $ Float $ f + (fromRational i)-  plus' (Value (Rational _)) val = throwError $ TypeMismatch "number" val-  plus' (Value (Float _)) val = throwError $ TypeMismatch "number" val-  plus' val _ = throwError $ TypeMismatch "number" val+rationalToFloat :: PrimitiveFunc+rationalToFloat = oneArg $ \val -> do+  r <- fromEgison val+  return $ Float $ fromRational r -minus :: PrimitiveFunc-minus = (liftError .) $ twoArgs minus'- where-  minus' (Value (Integer x)) (Value (Integer x')) = return $ Integer $ (x - x')-  minus' (Value (Integer i)) val = minus' (Value (Rational (i % 1))) val-  minus' val (Value (Integer i)) = minus' val (Value (Rational (i % 1)))-  minus' (Value (Rational x)) (Value (Rational x')) = let y = (x - x') in-                                                      if denominator y == 1-                                                        then return $ Integer $ numerator y-                                                        else return $ Rational y-  minus' (Value (Float f)) (Value (Float f')) = return $ Float $ f - f'-  minus' (Value (Rational i)) (Value (Float f)) = return $ Float $ (fromRational i) - f-  minus' (Value (Float f)) (Value (Rational i)) = return $ Float $ f - (fromRational i)-  minus' (Value (Rational _)) val = throwError $ TypeMismatch "number" val-  minus' (Value (Float _)) val = throwError $ TypeMismatch "number" val-  minus' val _ = throwError $ TypeMismatch "number" val+floatToIntegerOp :: (Double -> Integer) -> PrimitiveFunc+floatToIntegerOp op = oneArg $ \val -> do+  f <- fromEgison val+  return $ Integer $ op f -multiply :: PrimitiveFunc-multiply = (liftError .) $ twoArgs multiply'- where-  multiply' (Value (Integer x)) (Value (Integer x')) = return $ Integer $ (x * x')-  multiply' (Value (Integer i)) val = multiply' (Value (Rational (i % 1))) val-  multiply' val (Value (Integer i)) = multiply' val (Value (Rational (i % 1)))-  multiply' (Value (Rational x)) (Value (Rational x')) = let y = (x * x') in-                                                      if denominator y == 1-                                                        then return $ Integer $ numerator y-                                                        else return $ Rational y-  multiply' (Value (Float f)) (Value (Float f')) = return $ Float $ f * f'-  multiply' (Value (Rational i)) (Value (Float f)) = return $ Float $ (fromRational i) * f-  multiply' (Value (Float f)) (Value (Rational i)) = return $ Float $ f * (fromRational i)-  multiply' (Value (Rational _)) val = throwError $ TypeMismatch "number" val-  multiply' (Value (Float _)) val = throwError $ TypeMismatch "number" val-  multiply' val _ = throwError $ TypeMismatch "number" val+read' :: PrimitiveFunc+read'= oneArg $ \val -> fromStringValue val >>= readExpr >>= evalExprDeep nullEnv -divide :: PrimitiveFunc-divide = (liftError .) $ twoArgs divide'- where-  divide' (Value (Integer x)) (Value (Integer x')) = return $ Rational $ (x % x')-  divide' (Value (Integer i)) val = divide' (Value (Rational (i % 1))) val-  divide' val (Value (Integer i)) = divide' val (Value (Rational (i % 1)))-  divide' (Value (Rational x)) (Value (Rational x')) =-    let m = numerator x' in-    let n = denominator x' in-    let y = (x * (n % m)) in-      if denominator y == 1-        then return $ Integer $ numerator y-        else return $ Rational y-  divide' (Value (Rational x)) (Value (Float f)) = return $ Float $ (fromRational x) / f-  divide' (Value (Float f)) (Value (Rational x)) = return $ Float $ f / (fromRational x)-  divide' (Value (Rational _)) val = throwError $ TypeMismatch "number" val-  divide' (Value (Float f)) (Value (Float f')) = return $ Float $ f / f'-  divide' (Value (Float _)) val = throwError $ TypeMismatch "number" val-  divide' val _ = throwError $ TypeMismatch "number" val+show' :: PrimitiveFunc+show'= oneArg $ \val -> return $ toEgison $ show val -divideInverse :: PrimitiveFunc-divideInverse = (liftError .) $ oneArg $ divideInverse'- where-  divideInverse' (Value (Rational rat)) = do-    return $ Tuple [Integer (numerator rat), Integer (denominator rat)]-  divideInverse' (Value (Integer x)) = do-    return $ Tuple [Integer x, Integer 1]-  divideInverse' val = throwError $ TypeMismatch "rational" val+stringToInteger :: PrimitiveFunc+stringToInteger = oneArg $ \val -> do+  numStr <- fromEgison val+  return $ Integer (read numStr :: Integer) + assert ::  PrimitiveFunc-assert = (liftError .) $ twoArgs $ \label test -> do-  test <- fromBoolValue test+assert = twoArgs $ \label test -> do+  test <- fromEgison 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 ++@@ -361,7 +391,7 @@   dbName <- fromStringValue val   qStr <- fromStringValue val'   let ret = unsafePerformIO $ query' (T.pack dbName) $ T.pack qStr-  return $ Collection $ Sq.fromList $ map (\r -> Tuple (map makeStringValue r)) ret+  return $ Collection $ Sq.fromList $ map (\r -> Tuple (map makeEgisonString r)) ret  where   query' :: T.Text -> T.Text -> IO [[String]]   query' dbName q = do@@ -384,7 +414,7 @@   dbName <- fromStringValue val   qStr <- fromStringValue val'   let ret = unsafePerformIO $ query' dbName $ BC.pack qStr-  return $ Collection $ Sq.fromList $ map (\r -> Tuple (map makeStringValue r)) ret+  return $ Collection $ Sq.fromList $ map (\r -> Tuple (map makeEgisonString r)) ret  where   query' :: String -> ByteString -> IO [[String]]   query' dbName q = do@@ -409,23 +439,21 @@ --  ioPrimitives :: [(String, PrimitiveFunc)]-ioPrimitives = [ ("return", return')+ioPrimitives = [+                 ("return", return')                , ("open-input-file", makePort ReadMode)                , ("open-output-file", makePort WriteMode)                , ("close-input-port", closePort)                , ("close-output-port", closePort)                , ("read-char", readChar)                , ("read-line", readLine)-               , ("read", readFromStdin)                , ("write-char", writeChar)                , ("write-string", writeString)-               , ("write", writeToStdout)+                                 , ("read-char-from-port", readCharFromPort)                , ("read-line-from-port", readLineFromPort)---             , ("read-from-port", readFromPort)                , ("write-char-to-port", writeCharToPort)                , ("write-string-to-port", writeStringToPort)-               , ("write-to-port", writeToPort)                                  , ("eof?", isEOFStdin)                , ("flush", flushStdout)@@ -434,8 +462,6 @@                , ("read-file", readFile')                                  , ("rand", randRange)-                 ---             , ("get-lib-dir-name", getLibDirName)                ]  makeIO :: EgisonM EgisonValue -> EgisonValue@@ -445,77 +471,85 @@ makeIO' m = IOFunc $ m >> return (Value $ Tuple [World, Tuple []])  return' :: PrimitiveFunc-return' = oneArg $ return . makeIO . evalDeep+return' = oneArg $ \val -> return $ makeIO $ return val  makePort :: IOMode -> PrimitiveFunc-makePort mode = (liftError .) $ oneArg $ \val -> do-  filename <- fromStringValue val -  return . makeIO . liftIO $ Port <$> openFile filename mode+makePort mode = oneArg $ \val -> do+  filename <- fromEgison val+  port <- liftIO $ openFile filename mode+  return $ makeIO $ return (Port port)  closePort :: PrimitiveFunc-closePort = (liftError .) $ oneArg $ \val ->-  makeIO' . liftIO . hClose <$> fromPortValue val+closePort = oneArg $ \val -> do+  port <- fromEgison val+  return $ makeIO' $ liftIO $ hClose port  writeChar :: PrimitiveFunc-writeChar = (liftError .) $ oneArg $ \val ->-  makeIO' . liftIO . putChar <$> fromCharValue val--writeString :: PrimitiveFunc-writeString = (liftError .) $ oneArg $ \val ->-  makeIO' . liftIO . putStr <$> fromStringValue val--writeToStdout :: PrimitiveFunc-writeToStdout = oneArg $ \val ->-  makeIO' . liftIO . putStr . show <$> evalDeep val--readChar :: PrimitiveFunc-readChar = noArg $ return $ makeIO $ liftIO $ liftM Char getChar+writeChar = oneArg $ \val -> do+  c <- fromEgison val+  return $ makeIO' $ liftIO $ putChar c -readLine :: PrimitiveFunc-readLine = noArg $ return $ makeIO $ liftIO $ liftM makeStringValue getLine+writeCharToPort :: PrimitiveFunc+writeCharToPort = twoArgs $ \val val' -> do+  port <- fromEgison val+  c <- fromEgison val'+  return $ makeIO' $ liftIO $ hPutChar port c -readFromStdin :: PrimitiveFunc-readFromStdin = noArg $ return $ makeIO $ (liftIO getLine) >>= readExpr >>= evalExpr' nullEnv+writeString :: PrimitiveFunc+writeString = oneArg $ \val -> do+  s <- fromEgison val+  return $ makeIO' $ liftIO $ putStr s+  +writeStringToPort :: PrimitiveFunc+writeStringToPort = twoArgs $ \val val' -> do+  port <- fromEgison val+  s <- fromEgison val'+  return $ makeIO' $ liftIO $ hPutStr port s  flushStdout :: PrimitiveFunc flushStdout = noArg $ return $ makeIO' $ liftIO $ hFlush stdout -isEOFStdin :: PrimitiveFunc-isEOFStdin = noArg $ return $ makeIO $ liftIO $ liftM Bool isEOF--writeCharToPort :: PrimitiveFunc-writeCharToPort = (liftError .) $ twoArgs $ \val val' ->-  ((makeIO' . liftIO) .) . hPutChar <$> fromPortValue val <*> fromCharValue val'--writeStringToPort :: PrimitiveFunc-writeStringToPort = (liftError .) $ twoArgs $ \val val' ->-  ((makeIO' . liftIO) .) . hPutStr <$> fromPortValue val <*> fromStringValue val'+flushPort :: PrimitiveFunc+flushPort = oneArg $ \val -> do+  port <- fromEgison val+  return $ makeIO' $ liftIO $ hFlush port -writeToPort :: PrimitiveFunc-writeToPort = twoArgs $ \val val' -> do-  ((makeIO' . liftIO) .) . hPutStr <$> liftError (fromPortValue val)-                                   <*> (show <$> evalDeep val')+readChar :: PrimitiveFunc+readChar = noArg $ return $ makeIO $ liftIO $ liftM Char getChar  readCharFromPort :: PrimitiveFunc-readCharFromPort = (liftError .) $ oneArg $ \val ->-  makeIO . liftIO . liftM Char . hGetChar <$> fromPortValue val+readCharFromPort = oneArg $ \val -> do+  port <- fromEgison val+  c <- liftIO $ hGetChar port+  return $ makeIO $ return (Char c) +readLine :: PrimitiveFunc+readLine = noArg $ return $ makeIO $ liftIO $ liftM toEgison getLine+ readLineFromPort :: PrimitiveFunc-readLineFromPort = (liftError .) $ oneArg $ \val ->-  makeIO . liftIO . liftM makeStringValue . hGetLine <$> fromPortValue val+readLineFromPort = oneArg $ \val -> do+  port <- fromEgison val+  s <- liftIO $ hGetLine port+  return $ makeIO $ return $ toEgison s -flushPort :: PrimitiveFunc-flushPort = (liftError .) $ oneArg $ \val ->-  makeIO' . liftIO . hFlush <$> fromPortValue val+readFile' :: PrimitiveFunc+readFile' =  oneArg $ \val -> do+  filename <- fromEgison val+  s <- liftIO $ readFile filename+  return $ makeIO $ return $ toEgison s+  +isEOFStdin :: PrimitiveFunc+isEOFStdin = noArg $ return $ makeIO $ liftIO $ liftM Bool isEOF  isEOFPort :: PrimitiveFunc-isEOFPort = (liftError .) $ oneArg $ \val ->-  makeIO . liftIO . liftM Bool . hIsEOF <$> fromPortValue val+isEOFPort = oneArg $ \val -> do+  port <- fromEgison val+  b <- liftIO $ hIsEOF port+  return $ makeIO $ return (Bool b) -readFile' :: PrimitiveFunc-readFile' =  (liftError .) $ oneArg $ \val ->-  makeIO . liftIO . liftM makeStringValue . readFile <$> fromStringValue val-   randRange :: PrimitiveFunc-randRange = (liftError .) $ twoArgs $ \val val' ->-  return . makeIO . liftIO . liftM Integer . getStdRandom . randomR =<< liftM2 (,) (fromIntegerValue val) (fromIntegerValue val')+randRange = twoArgs $ \val val' -> do+  i <- fromEgison val+  i' <- fromEgison val'+  n <- liftIO $ getStdRandom $ randomR (i, i')+  return $ makeIO $ return (Integer n)
hs-src/Language/Egison/Types.hs view
@@ -1,7 +1,81 @@ {-# Language TypeSynonymInstances, FlexibleInstances, GeneralizedNewtypeDeriving,-             MultiParamTypeClasses, UndecidableInstances, DeriveDataTypeable #-}-module Language.Egison.Types where+             MultiParamTypeClasses, UndecidableInstances, DeriveDataTypeable,+             TypeFamilies #-}+{- |+Module      : Language.Egison.Types+Copyright   : Satoshi Egi+Licence     : MIT +This module contains type definitions of Egison Data.+-}++module Language.Egison.Types+    (+    -- * Egison expressions+      EgisonTopExpr (..)+    , EgisonExpr (..)+    , EgisonPattern (..)+    , InnerExpr (..)+    , BindingExpr (..)+    , MatchClause (..)+    , MatcherInfo (..)+    , LoopRange (..)+    , PrimitivePatPattern (..)+    , PrimitiveDataPattern (..)+    -- * Egison values+    , EgisonValue (..)+    , Matcher (..)+    , PrimitiveFunc (..)+    , EgisonHashKey  (..) -- TODO ?+    , Egison (..)+    , fromMatcherValue+    -- * Internal data+    , Object (..)+    , ObjectRef (..)+    , WHNFData (..)+    , Intermediate (..)+    , Inner (..)+    , EgisonWHNF (..)+    , fromBuiltinWHNF -- TODO ?+    -- * Environment+    , Env (..)+    , Var (..)+    , Binding (..)+    , nullEnv+    , extendEnv+    , refVar+    -- * Pattern matching+    , PMMode (..)+    , MatchingState (..)+    , MatchingTree (..)+    , PatternBinding (..)+    , LoopContext (..)+    -- * Errors+    , EgisonError (..)+    , liftError+    -- * Monads+    , EgisonM (..)+    , runEgisonM+    , liftEgisonM+    , fromEgisonM+    , FreshT (..)+    , Fresh (..)+    , MonadFresh (..)+    , runFreshT+    , MatchM (..)+    , matchFail+    , MList (..)+    , fromList+    , fromSeq+    , fromMList+    , msingleton+    , mfoldr+    , mappend+    , mconcat+    , mmap+    , mfor+    ) where+ import Prelude hiding (foldr)  import Control.Exception@@ -16,9 +90,9 @@ import Control.Monad.Trans.Maybe  import Data.Monoid (Monoid)-import Data.Foldable (foldr, toList) import qualified Data.Sequence as Sq import Data.Sequence (Seq)+import Data.Foldable (foldr, toList) import Data.IORef import Data.HashMap.Strict (HashMap) import qualified Data.HashMap.Strict as HashMap@@ -33,6 +107,8 @@ import qualified Data.IntMap as IntMap import Data.Ratio +import System.IO.Unsafe (unsafePerformIO)+ -- -- Expressions --@@ -89,6 +165,11 @@   | UndefinedExpr  deriving (Show) +data InnerExpr =+    ElementExpr EgisonExpr+  | SubCollectionExpr EgisonExpr+ deriving (Show)+ type BindingExpr = ([String], EgisonExpr) type MatchClause = (EgisonPattern, EgisonExpr) type MatcherInfo = [(PrimitivePatPattern, EgisonExpr, [(PrimitiveDataPattern, EgisonExpr)])]@@ -101,7 +182,6 @@   | PredPat EgisonExpr   | IndexedPat EgisonPattern [EgisonExpr]   | LetPat [BindingExpr] EgisonPattern-  | CutPat EgisonPattern   | NotPat EgisonPattern   | AndPat [EgisonPattern]   | OrPat [EgisonPattern]@@ -134,11 +214,6 @@   | PDConstantPat EgisonExpr  deriving (Show) -data InnerExpr =-    ElementExpr EgisonExpr-  | SubCollectionExpr EgisonExpr- deriving (Show)- -- -- Values --@@ -167,8 +242,12 @@   | EOF  type Matcher = (Env, MatcherInfo)-type PrimitiveFunc = [WHNFData] -> EgisonM EgisonValue+type PrimitiveFunc = EgisonValue -> EgisonM EgisonValue +data EgisonHashKey =+    IntKey Integer+  | StrKey ByteString+ instance Show EgisonValue where   show (Char c) = "'" ++ [c] ++ "'"   show (Bool True) = "#t"@@ -214,6 +293,100 @@  _ == _ = False  --+-- Egison data and Haskell data+--+class Egison a where+  toEgison :: a -> EgisonValue+  fromEgison :: EgisonValue -> EgisonM a++instance Egison Char where+  toEgison c = Char c+  fromEgison = liftError . fromCharValue++instance Egison Bool where+  toEgison b = Bool b+  fromEgison = liftError . fromBoolValue++instance Egison Integer where+  toEgison i = Integer i+  fromEgison = liftError . fromIntegerValue++instance Egison Rational where+  toEgison r = Rational r+  fromEgison = liftError . fromRationalValue++instance Egison Double where+  toEgison f = Float f+  fromEgison = liftError . fromFloatValue++instance Egison Handle where+  toEgison h = Port h+  fromEgison = liftError . fromPortValue++instance (Egison a) => Egison [a] where+  toEgison xs = Collection $ Sq.fromList (map toEgison xs)+  fromEgison (Collection seq) = mapM fromEgison (toList seq)+  fromEgison val = liftError $ throwError $ TypeMismatch "collection" (Value val)++instance Egison () where+  toEgison () = Tuple []+  fromEgison (Tuple []) = return ()+  fromEgison val = liftError $ throwError $ TypeMismatch "zero element tuple" (Value val)++instance (Egison a, Egison b) => Egison (a, b) where+  toEgison (x, y) = Tuple [toEgison x, toEgison y]+  fromEgison (Tuple (x:y:[])) = (liftM2 (,)) (fromEgison x) (fromEgison y)+  fromEgison val = liftError $ throwError $ TypeMismatch "two elements tuple" (Value val)++instance (Egison a, Egison b, Egison c) => Egison (a, b, c) where+  toEgison (x, y, z) = Tuple [toEgison x, toEgison y, toEgison z]+  fromEgison (Tuple (x:y:z:[])) = do+    x' <- fromEgison x+    y' <- fromEgison y+    z' <- fromEgison z+    return (x', y', z')+  fromEgison val = liftError $ throwError $ TypeMismatch "two elements tuple" (Value val)++instance (Egison a, Egison b, Egison c, Egison d) => Egison (a, b, c, d) where+  toEgison (x, y, z, w) = Tuple [toEgison x, toEgison y, toEgison z, toEgison w]+  fromEgison (Tuple (x:y:z:w:[])) = do+    x' <- fromEgison x+    y' <- fromEgison y+    z' <- fromEgison z+    w' <- fromEgison w+    return (x', y', z', w')+  fromEgison val = liftError $ throwError $ TypeMismatch "two elements tuple" (Value val)++fromCharValue :: EgisonValue -> Either EgisonError Char+fromCharValue (Char c) = return c+fromCharValue val = throwError $ TypeMismatch "char" (Value val)++fromBoolValue :: EgisonValue -> Either EgisonError Bool+fromBoolValue (Bool b) = return b+fromBoolValue val = throwError $ TypeMismatch "bool" (Value val)++fromIntegerValue :: EgisonValue -> Either EgisonError Integer+fromIntegerValue (Integer i) = return i+fromIntegerValue val = throwError $ TypeMismatch "integer" (Value val)++fromRationalValue :: EgisonValue -> Either EgisonError Rational+fromRationalValue (Rational x) = return x+fromRationalValue val = throwError $ TypeMismatch "rational" (Value val)++fromFloatValue :: EgisonValue -> Either EgisonError Double+fromFloatValue (Float f) = return f+fromFloatValue val = throwError $ TypeMismatch "float" (Value val)++fromPortValue :: EgisonValue -> Either EgisonError Handle+fromPortValue (Port handle) = return handle+fromPortValue val = throwError $ TypeMismatch "port" (Value val)++-- TODO : write instance declaration for Matcher+fromMatcherValue :: EgisonValue -> Either EgisonError Matcher+fromMatcherValue (Matcher matcher) = return matcher+fromMatcherValue val = throwError $ TypeMismatch "matcher" (Value val)++-- -- Internal Data -- @@ -248,76 +421,77 @@   show (Intermediate (IIntHash _)) = "{|...|}"    show (Intermediate (IStrHash _)) = "{|...|}"  -data EgisonHashKey =-    IntKey Integer-  | StrKey ByteString--makeKey :: EgisonValue -> Either EgisonError EgisonHashKey-makeKey val =-  case val of-    Integer i -> return (IntKey i)-    Collection _ -> do-      str <- fromStringValue $ Value val-      return $ StrKey $ B.pack str-    _ -> throwError $ TypeMismatch "integer or string" $ Value val--fromCharValue :: WHNFData -> Either EgisonError Char-fromCharValue (Value (Char c)) = return c-fromCharValue val = throwError $ TypeMismatch "char" val--fromStringValue :: WHNFData -> Either EgisonError String-fromStringValue (Value (Collection seq)) = do-  let ls = toList seq-  mapM (\val -> case val of-                  Char c -> return c-                  _ -> throwError $ TypeMismatch "char" (Value val))-       ls-fromStringValue val = throwError $ TypeMismatch "string" val--makeStringValue :: String -> EgisonValue-makeStringValue str = Collection $ Sq.fromList $ map Char str--fromBoolValue :: WHNFData -> Either EgisonError Bool-fromBoolValue (Value (Bool b)) = return b-fromBoolValue val = throwError $ TypeMismatch "bool" val+--+-- Extract data from WHNF+--+class EgisonWHNF a where+  fromWHNF :: WHNFData -> EgisonM a+  +instance EgisonWHNF Char where+  fromWHNF = liftError . fromCharWHNF+  +instance EgisonWHNF Bool where+  fromWHNF = liftError . fromBoolWHNF+  +instance EgisonWHNF Integer where+  fromWHNF = liftError . fromIntegerWHNF+  +instance EgisonWHNF Rational where+  fromWHNF = liftError . fromRationalWHNF+  +instance EgisonWHNF Double where+  fromWHNF = liftError . fromFloatWHNF+  +instance EgisonWHNF Handle where+  fromWHNF = liftError . fromPortWHNF+  +instance EgisonWHNF Matcher where+  fromWHNF = liftError . fromMatcherWHNF+  +fromCharWHNF :: WHNFData -> Either EgisonError Char+fromCharWHNF (Value (Char c)) = return c+fromCharWHNF whnf = throwError $ TypeMismatch "char" whnf -fromRationalValue :: WHNFData -> Either EgisonError Rational-fromRationalValue (Value (Rational x)) = return x-fromRationalValue val = throwError $ TypeMismatch "rational" val+fromBoolWHNF :: WHNFData -> Either EgisonError Bool+fromBoolWHNF (Value (Bool b)) = return b+fromBoolWHNF whnf = throwError $ TypeMismatch "bool" whnf -fromIntegerValue :: WHNFData -> Either EgisonError Integer-fromIntegerValue (Value (Integer i)) = return i-fromIntegerValue val = throwError $ TypeMismatch "integer" val+fromIntegerWHNF :: WHNFData -> Either EgisonError Integer+fromIntegerWHNF (Value (Integer i)) = return i+fromIntegerWHNF whnf = throwError $ TypeMismatch "integer" whnf -fromFloatValue :: WHNFData -> Either EgisonError Double-fromFloatValue (Value (Float f)) = return f-fromFloatValue val = throwError $ TypeMismatch "float" val+fromRationalWHNF :: WHNFData -> Either EgisonError Rational+fromRationalWHNF (Value (Rational x)) = return x+fromRationalWHNF whnf = throwError $ TypeMismatch "rational" whnf -fromPortValue :: WHNFData -> Either EgisonError Handle-fromPortValue (Value (Port handle)) = return handle-fromPortValue val = throwError $ TypeMismatch "port" val+fromFloatWHNF :: WHNFData -> Either EgisonError Double+fromFloatWHNF (Value (Float f)) = return f+fromFloatWHNF whnf = throwError $ TypeMismatch "float" whnf -fromMatcherValue :: WHNFData -> Either EgisonError Matcher-fromMatcherValue (Value (Matcher matcher)) = return matcher-fromMatcherValue val = throwError $ TypeMismatch "matcher" val+fromPortWHNF :: WHNFData -> Either EgisonError Handle+fromPortWHNF (Value (Port handle)) = return handle+fromPortWHNF whnf = throwError $ TypeMismatch "port" whnf -fromPrimitiveValue :: WHNFData -> Either EgisonError EgisonValue-fromPrimitiveValue (Value val@(Char _)) = return val-fromPrimitiveValue (Value val@(Bool _)) = return val-fromPrimitiveValue (Value val@(Integer _)) = return val-fromPrimitiveValue (Value val@(Float _)) = return val-fromPrimitiveValue val = throwError $ TypeMismatch "primitive value" val +fromMatcherWHNF :: WHNFData -> Either EgisonError Matcher+fromMatcherWHNF (Value (Matcher matcher)) = return matcher+fromMatcherWHNF whnf = throwError $ TypeMismatch "matcher" whnf -extractInteger :: EgisonValue -> EgisonM Integer-extractInteger (Integer i) = return i-extractInteger val = throwError $ TypeMismatch "integer" (Value val)+--+--+--+fromBuiltinWHNF :: WHNFData -> Either EgisonError EgisonValue+fromBuiltinWHNF (Value val@(Char _)) = return val+fromBuiltinWHNF (Value val@(Bool _)) = return val+fromBuiltinWHNF (Value val@(Integer _)) = return val+fromBuiltinWHNF (Value val@(Float _)) = return val+fromBuiltinWHNF whnf = throwError $ TypeMismatch "primitive value" whnf  -- -- Environment -- -type Var = String type Env = [HashMap Var ObjectRef]+type Var = String type Binding = (Var, ObjectRef)  nullEnv :: Env@@ -391,6 +565,39 @@ -- Monads -- +newtype EgisonM a = EgisonM {+    unEgisonM :: ErrorT EgisonError (FreshT IO) a+  } deriving (Functor, Applicative, Monad, MonadIO, MonadError EgisonError, MonadFresh)++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   +  +fromEgisonM :: EgisonM a -> IO (Either EgisonError a)+fromEgisonM = modifyCounter . runEgisonM++counter :: IORef Int+counter = unsafePerformIO (newIORef 0)++readCounter :: IO Int+readCounter = readIORef counter++updateCounter :: Int -> IO ()+updateCounter = writeIORef counter++modifyCounter :: FreshT IO a -> IO a+modifyCounter m = do+  seed <- readCounter+  (result, seed) <- runFreshT seed m +  updateCounter seed+  return result  + newtype FreshT m a = FreshT { unFreshT :: StateT Int m a }   deriving (Functor, Applicative, Monad, MonadState Int, MonadTrans) @@ -432,20 +639,7 @@ runFresh :: Int -> Fresh a -> (a, Int) runFresh seed m = runIdentity $ flip runStateT seed $ unFreshT m -newtype EgisonM a = EgisonM {-    unEgisonM :: ErrorT EgisonError (FreshT IO) a-  } deriving (Functor, Applicative, Monad, MonadIO, MonadError EgisonError, MonadFresh) -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
+ hs-src/Language/Egison/Util.hs view
@@ -0,0 +1,86 @@++{- |+Module      : Language.Egison.Util+Copyright   : Satoshi Egi+Licence     : MIT++This module provides utility functions.+-}++module Language.Egison.Util (completeEgison) where++import Data.List+import System.Console.Haskeline hiding (handle, catch, throwTo)++-- |Complete Egison keywords+completeEgison :: Monad m => CompletionFunc m+completeEgison arg@((')':_), _) = completeParen arg+completeEgison arg@(('>':_), _) = completeParen arg+completeEgison arg@((']':_), _) = completeParen arg+completeEgison arg@(('}':_), _) = completeParen arg+completeEgison arg@(('(':_), _) = (completeWord Nothing " \t<>[]{}$," completeAfterOpenParen) arg+completeEgison arg@(('<':_), _) = (completeWord Nothing " \t()[]{}$," completeAfterOpenCons) arg+completeEgison arg@((' ':_), _) = (completeWord Nothing "" completeNothing) arg+completeEgison arg@(('[':_), _) = (completeWord Nothing "" completeNothing) arg+completeEgison arg@(('{':_), _) = (completeWord Nothing "" completeNothing) arg+completeEgison arg@([], _) = (completeWord Nothing "" completeNothing) arg+completeEgison arg@(_, _) = (completeWord Nothing " \t[]{}$," completeEgisonKeyword) arg++completeAfterOpenParen :: Monad m => String -> m [Completion]+completeAfterOpenParen str = return $ map (\kwd -> Completion kwd kwd False) $ filter (isPrefixOf str) egisonKeywordsAfterOpenParen++completeAfterOpenCons :: Monad m => String -> m [Completion]+completeAfterOpenCons str = return $ map (\kwd -> Completion kwd kwd False) $ filter (isPrefixOf str) egisonKeywordsAfterOpenCons++completeNothing :: Monad m => String -> m [Completion]+completeNothing _ = return []++completeEgisonKeyword :: Monad m => String -> m [Completion]+completeEgisonKeyword str = return $ map (\kwd -> Completion kwd kwd False) $ filter (isPrefixOf str) egisonKeywords++egisonKeywordsAfterOpenParen = map ((:) '(') $ ["define", "let", "letrec", "lambda", "match", "match-all", "match-lambda", "matcher", "algebraic-data-matcher", "pattern-function", "if", "loop", "io", "do"]+                            ++ ["id", "or", "and", "not", "char", "eq?/m", "compose", "compose3", "list", "map", "between", "repeat1", "repeat", "filter", "separate", "concat", "foldr", "foldl", "map2", "zip", "empty?", "member?", "member?/m", "include?", "include?/m", "any", "all", "length", "count", "count/m", "car", "cdr", "rac", "rdc", "nth", "take", "drop", "while", "reverse", "multiset", "add", "add/m", "delete-first", "delete-first/m", "delete", "delete/m", "difference", "difference/m", "union", "union/m", "intersect", "intersect/m", "set", "unique", "unique/m", "print", "print-to-port", "each", "pure-rand", "fib", "fact", "divisor?", "gcd", "primes", "find-factor", "prime-factorization", "p-f", "min", "max", "min-and-max", "power", "mod", "qsort", "intersperse", "intercalate", "split", "split/m"]+egisonKeywordsAfterOpenCons = map ((:) '<') ["nil", "cons", "join", "snoc", "nioj"]+egisonKeywordsInNeutral = ["something"]+                       ++ ["bool", "string", "integer", "nats", "primes"]+egisonKeywords = egisonKeywordsAfterOpenParen ++ egisonKeywordsAfterOpenCons ++ egisonKeywordsInNeutral++completeParen :: Monad m => CompletionFunc m+completeParen (lstr, _) = case (closeParen lstr) of+  Nothing -> return (lstr, [])+  Just paren -> return (lstr, [(Completion paren paren False)])++closeParen :: String -> Maybe String+closeParen str = closeParen' 0 $ removeCharAndStringLiteral str++removeCharAndStringLiteral :: String -> String+removeCharAndStringLiteral [] = []+removeCharAndStringLiteral ('"':'\\':str) = '"':'\\':(removeCharAndStringLiteral str)+removeCharAndStringLiteral ('"':str) = removeCharAndStringLiteral' str+removeCharAndStringLiteral ('\'':'\\':str) = '\'':'\\':(removeCharAndStringLiteral str)+removeCharAndStringLiteral ('\'':str) = removeCharAndStringLiteral' str+removeCharAndStringLiteral (c:str) = c:(removeCharAndStringLiteral str)++removeCharAndStringLiteral' :: String -> String+removeCharAndStringLiteral' [] = []+removeCharAndStringLiteral' ('"':'\\':str) = removeCharAndStringLiteral' str+removeCharAndStringLiteral' ('"':str) = removeCharAndStringLiteral str+removeCharAndStringLiteral' ('\'':'\\':str) = removeCharAndStringLiteral' str+removeCharAndStringLiteral' ('\'':str) = removeCharAndStringLiteral str+removeCharAndStringLiteral' (_:str) = removeCharAndStringLiteral' str++closeParen' :: Integer -> String -> Maybe String+closeParen' _ [] = Nothing+closeParen' 0 ('(':_) = Just ")"+closeParen' 0 ('<':_) = Just ">"+closeParen' 0 ('[':_) = Just "]"+closeParen' 0 ('{':_) = Just "}"+closeParen' n ('(':str) = closeParen' (n - 1) str+closeParen' n ('<':str) = closeParen' (n - 1) str+closeParen' n ('[':str) = closeParen' (n - 1) str+closeParen' n ('{':str) = closeParen' (n - 1) str+closeParen' n (')':str) = closeParen' (n + 1) str+closeParen' n ('>':str) = closeParen' (n + 1) str+closeParen' n (']':str) = closeParen' (n + 1) str+closeParen' n ('}':str) = closeParen' (n + 1) str+closeParen' n (_:str) = closeParen' n str
lib/core/collection.egi view
@@ -55,8 +55,8 @@  (define $between   (lambda [$s $e]-    (if (gt-i? (+ s 10) e)-      (if (gt-i? s e)+    (if (gt? (+ s 10) e)+      (if (gt? s e)         {}         {s @(between (+ s 1) e)})       {s (+ s 1) (+ s 2) (+ s 3) (+ s 4) (+ s 5) (+ s 6) (+ s 7) (+ s 8) (+ s 9) (+ s 10) @(between (+ s 11) e)})
+ sample/bipartite-graph.egi view
@@ -0,0 +1,87 @@+;;;+;;;+;;; Bipartite Graph demonstartion+;;;+;;;++;;+;; Matcher definitions+;;+(define $bipartite-graph+  (lambda [$a $b]+    (multiset (edge a b))))++(define $edge+  (lambda [$a $b]+    (algebraic-data-matcher+      {<edge a b>})))++;;+;; Demonstration code+;;+(define $bipartite-graph-data+  {<Edge 1 "a">+   <Edge 1 "a">+   <Edge 1 "a">+   <Edge 1 "a">+   <Edge 1 "b">+   <Edge 1 "c">+   <Edge 2 "a">+   <Edge 2 "a">+   <Edge 2 "a">+   <Edge 2 "a">+   <Edge 2 "a">+   <Edge 3 "c">+   <Edge 4 "a">+   <Edge 5 "a">+   <Edge 5 "b">+   <Edge 5 "c">+   <Edge 6 "c">+   <Edge 6 "c">+   <Edge 6 "c">+   })++(test (match-all bipartite-graph-data (bipartite-graph integer string)+        [<cons <edge ,1 $str> _> str]))++(test (unique/m integer+                (match-all bipartite-graph-data (bipartite-graph integer string)+                  [<cons <edge $n $str>+                         <cons <edge ,n ,str>+                               ^<cons <edge ,n ^,str> _>>>+                   n])))++(test (unique/m integer+                (match-all bipartite-graph-data (bipartite-graph integer string)+                  [<cons <edge $n $str>+                         <cons <edge ,n ,str>+                               ^<cons <edge ,n ^,str> _>>>+                   n])))++(test (unique/m integer+                (match-all bipartite-graph-data (bipartite-graph integer string)+                  [<cons <edge $n ,"a"> _>+                   n])))++(test (unique/m integer+                (match-all bipartite-graph-data (bipartite-graph integer string)+                  [<cons <edge $n ,"a">+                    <cons <edge ,n ,"c">+                     _>>+                   n])))++;; I found bug on nested not-patterns+;(test (unique/m integer+;                (match-all bipartite-graph-data (bipartite-graph integer string)+;                  [(& <cons <edge $n $str>+;                            <cons <edge ,n ,str>+;                                  <cons <edge ,n ,str> _>>>+;                      ^<cons <edge $n2 $str2>+;                             ^<cons <edge ,n2 ,str2> _>>)+;                   n])))++(test (unique/m integer+                (match-all bipartite-graph-data (bipartite-graph integer string)+                  [<cons <edge $n2 $str2>+                         ^<cons <edge ,n2 ,str2> _>>+                  n2])))
+ sample/graph.egi view
@@ -0,0 +1,86 @@+;;;+;;;+;;; Graph demonstartion+;;;+;;;++;;+;; Matcher definitions+;;+(define $graph+  (lambda [$a]+    (set (edge a))))++(define $edge+  (lambda [$a]+    (algebraic-data-matcher+      {<edge a a>})))++;;+;; Sample data+;;+(define $graph-data1+  {<Edge 1 4>+   <Edge 2 1>+   <Edge 3 1>+   <Edge 3 2>+   <Edge 4 3>+   <Edge 5 1>+   <Edge 5 4>+   })++(define $graph-data2+  {<Edge 1 4> <Edge 1 5> <Edge 1 8> <Edge 1 10>+   <Edge 2 3> <Edge 2 6> <Edge 2 12>+   <Edge 3 2> <Edge 3 7> <Edge 3 9>+   <Edge 4 1> <Edge 4 6>+   <Edge 5 1> <Edge 5 8> <Edge 5 9> <Edge 5 11>+   <Edge 6 2> <Edge 6 4> <Edge 6 10> <Edge 6 12>+   <Edge 7 3> <Edge 7 9> <Edge 7 11>+   <Edge 8 1> <Edge 8 5>+   <Edge 9 3> <Edge 9 5> <Edge 9 7>+   <Edge 10 1> <Edge 10 6> <Edge 10 12>+   <Edge 11 5> <Edge 11 7>+   <Edge 12 2> <Edge 12 6> <Edge 12 10>+   })+   +;;+;; Demonstration code+;;+;; find all nodes who have an edege from 's' but not have an edge to 's'+(test (let {[$s 1]}+        (match-all graph-data1 (graph integer)+          [<cons <edge ,s $x>+                 ^<cons <edge ,x ,x>+                        _>>+           x])))++;; find all nodes in two path from 's'+(test (let {[$s 1]}+        (match-all graph-data1 (graph integer)+          [<cons <edge (& ,s $x_1) $x_2>+                 <cons <edge ,x_2 $x_3>+                       _>>+           x])))++;; enumerate first 5 paths from 's' to 'e'+(test (take 5 (let {[$s 1] [$e 2]}+                 (match-all graph-data2 (graph integer)+                   [<cons <edge (& ,s $x_1) $x_2>+                          (loop $i [4 $n]+                            <cons <edge ,x_(- i 2) $x_(- i 1)> ...>+                            <cons <edge ,x_(- n 1) (& ,e $x_n)> _>)>+                    x]))))++;; find all cliques whose size is 'n'+(test (let {[$n 3]}+        (match-all graph-data2 (graph integer)+          [<cons <edge $x_1 $x_2>+                 (loop $i [3 ,n]+                   <cons <edge ,x_1 $x_i>+                         (loop $j [2 ,(- i 1)]+                           <cons <edge ,x_j ,x_i> ...>+                           ...)+                         _>+                   _)>+           x])))
+ sample/io/argv.egi view
@@ -0,0 +1,18 @@+(define $write-each+  (lambda [$xs]+    (match xs (list something)+      {[<nil> (do {} [])]+       [<cons $x $rs>+        (do {[(write-string x)]+             [(write-string "\n")]+             [(write-each rs)]+             }+          [])]})))++(define $main+  (lambda [$argv]+    (do {[(write-string "argv: ")]+         [(write argv)]+         [(write-string "\n")]+         [(write-each argv)]}+      [])))
+ sample/io/cat.egi view
@@ -0,0 +1,44 @@+(define $main+  (lambda [$argv]+    (match argv (list string)+      {[<nil> (letrec {[$iter+                        (do {[$eof (eof?)]+                             [(unless eof+                                (do {[$line (read-line)]+                                     [(write-string line)]+                                     [(write-char '\n')]+                                     [iter]}+                                  []))]}+                          [])]}+                iter)]+       [_ (cat-files argv)]})))++(define $cat-files+  (match-lambda (list string)+    {[<nil> nop]+     [<cons $file $files>+      (do {[$port (open-input-file file)]+           [(letrec {[$iter+                     (do {[$eof (eof-port? port)]+                          [(unless eof+                             (do {[$line (read-line-from-port port)]+                                  [(write-string line)]+                                  [(write-char '\n')]+                                  [iter]}+                               []))]}+                       [])]}+              iter)]+           [(close-input-port port)]+           [(cat-files files)]}+        [])]}))++(define $nop+  (return []))++(define $when+  (lambda [$cond $action]+    (if cond action nop)))++(define $unless+  (lambda [$cond $action]+    (when (not cond) action)))
+ sample/io/cat2.egi view
@@ -0,0 +1,5 @@+(define $main+  (lambda [$argv]+    (do {[$content (read-file (car argv))]+         [(write-string content)]}+        [])))
+ sample/io/dice.egi view
@@ -0,0 +1,6 @@+(define $main+  (lambda [$argv]+    (do {[$v (rand 1 6)]+         [(write v)]+         [(write-char '\n')]}+        [])))
+ sample/io/hello.egi view
@@ -0,0 +1,3 @@+(define $main+  (lambda [$args]+    (print "Hello, world!")))
+ sample/io/interactive.egi view
@@ -0,0 +1,17 @@+(define $repl+  (lambda []+    (do {[(write-string "input: ")]+         [(flush)]+         [$input (read)]+         [(write input)]+         [(print "")]+         [(write (take 3 input))]+         [(print "")]+         [(repl)]+         }+      [])))++(define $main+  (lambda [$argv]+    (do {[(repl)]}+      [])))
+ sample/io/print-primes.egi view
@@ -0,0 +1,4 @@+(define $main+  (lambda [$argv]+    (do {[(each print (map itos primes))]}+      [])))
+ sample/mahjong.egi view
@@ -0,0 +1,73 @@+;;;+;;;+;;; Mah-jong example+;;;+;;;++;;+;; Matcher definitions+;;+(define $suit+  (algebraic-data-matcher+    {<wan> <pin> <sou>}))++(define $honor+  (algebraic-data-matcher+    {<ton> <nan> <sha> <pe> <haku> <hatsu> <chun>}))++(define $hai+  (algebraic-data-matcher+    {<num suit integer> <ji honor>}))++;;+;; Pattern modularizations+;;+(define $twin+  (pattern-function [$pat1 $pat2]+    <cons (& $pat pat1)+     <cons ,pat+      pat2>>))++(define $shuntsu+  (pattern-function [$pat1 $pat2]+    <cons (& <num $s $n> pat1)+     <cons <num ,s ,(+ n 1)>+      <cons <num ,s ,(+ n 2)>+       pat2>>>))++(define $kohtsu+  (pattern-function [$pat1 $pat2]+    <cons (& $pat pat1)+     <cons ,pat+      <cons ,pat+       pat2>>>))++;;+;; A function that determins whether the hand is finished or not.+;;+(define $agari?+  (match-lambda (multiset hai)+    {[(twin $th_1+       (| (shuntsu $sh_1 (| (shuntsu $sh_2 (| (shuntsu $sh_3 (| (shuntsu $sh_4 <nil>)+                                                                (kohtsu $kh_1 <nil>)))+                                              (kohtsu $kh_1 (kohtsu $kh_2 <nil>))))+                            (kohtsu $kh_1 (kohtsu $kh_2 (kohtsu $kh_3 <nil>)))))+          (kohtsu $kh_1 (kohtsu $kh_2 (kohtsu $kh_3 (kohtsu $kh_4 <nil>)))))+       (twin $th_2 (twin $th_3 (twin $th_4 (twin $th_5 (twin $th_6 (twin $th_7 <nil>)))))))+      #t]+     [_ #f]}))++;;+;; Demonstration code+;;+(test (agari? {<Ji <Haku>> <Ji <Haku>>+               <Num <Wan> 3> <Num <Wan> 4> <Num <Wan> 5>+               <Num <Wan> 6> <Num <Wan> 7> <Num <Wan> 8>+               <Num <Pin> 2> <Num <Pin> 3> <Num <Pin> 4>+               <Num <Sou> 6> <Num <Sou> 6> <Num <Sou> 6>}))++(test (agari? {<Ji <Haku>> <Ji <Haku>>+               <Num <Pin> 1> <Num <Pin> 3> <Num <Pin> 4>+               <Num <Wan> 6> <Num <Wan> 7> <Num <Wan> 8>+               <Num <Wan> 3> <Num <Wan> 4> <Num <Wan> 5>+               <Num <Sou> 6> <Num <Sou> 6> <Num <Sou> 6>}))
+ sample/n-queen.egi view
@@ -0,0 +1,58 @@+(define $eight-queen+  (match-all {1 2 3 4 5 6 7 8} (multiset integer)+    [<cons $a_1+      <cons (& ^,(- a_1 1) ^,(+ a_1 1)+               $a_2)+       <cons (& ^,(- a_1 2) ^,(+ a_1 2)+                ^,(- a_2 1) ^,(+ a_2 1)+                $a_3)+        <cons (& ^,(- a_1 3) ^,(+ a_1 3)+                 ^,(- a_2 2) ^,(+ a_2 2)+                 ^,(- a_3 1) ^,(+ a_3 1)+                 $a_4)+          <cons (& ^,(- a_1 4) ^,(+ a_1 4)+                   ^,(- a_2 3) ^,(+ a_2 3)+                   ^,(- a_3 2) ^,(+ a_3 2)+                   ^,(- a_4 1) ^,(+ a_4 1)+                   $a_5)+           <cons (& ^,(- a_1 5) ^,(+ a_1 5)+                    ^,(- a_2 4) ^,(+ a_2 4)+                    ^,(- a_3 3) ^,(+ a_3 3)+                    ^,(- a_4 2) ^,(+ a_4 2)+                    ^,(- a_5 1) ^,(+ a_5 1)+                    $a_6)+            <cons (& ^,(- a_1 6) ^,(+ a_1 6)+                     ^,(- a_2 5) ^,(+ a_2 5)+                     ^,(- a_3 4) ^,(+ a_3 4)+                     ^,(- a_4 3) ^,(+ a_4 3)+                     ^,(- a_5 2) ^,(+ a_5 2)+                     ^,(- a_6 1) ^,(+ a_6 1)+                     $a_7)+             <cons (& ^,(- a_1 7) ^,(+ a_1 7)+                      ^,(- a_2 6) ^,(+ a_2 6)+                      ^,(- a_3 5) ^,(+ a_3 5)+                      ^,(- a_4 4) ^,(+ a_4 4)+                      ^,(- a_5 3) ^,(+ a_5 3)+                      ^,(- a_6 2) ^,(+ a_6 2)+                      ^,(- a_7 1) ^,(+ a_7 1)+                      $a_8)+              <nil>>>>>>>>>+     a]))++(test eight-queen)++(define $n-queen+  (lambda [$n]+    (match-all (between 1 n) (multiset integer)+      [<cons $a_1+             (loop $i [2 ,n]+                   <cons (loop $i1 [1 ,(- i 1)]+                               (& ^,(- a_i1 (- i i1))+                                  ^,(+ a_i1 (- i i1))+                                  ...)+                               $a_i)+                         ...>+                   <nil>)>+      a])))++(test (n-queen 4))
+ sample/poker-hands.egi view
@@ -0,0 +1,114 @@+;;;+;;;+;;; Poker-hands demonstration+;;;+;;;++;;+;; Matcher definitions+;;+(define $suit+  (algebraic-data-matcher+    {<spade> <heart> <club> <diamond>}))++(define $card+  (algebraic-data-matcher+    {<card suit (mod 13)>}))++;;+;; A function that determins poker-hands+;;+(define $poker-hands+  (lambda [$cs]+    (match cs (multiset card)+      {[<cons <card $s $n>+         <cons <card ,s ,(- n 1)>+          <cons <card ,s ,(- n 2)>+           <cons <card ,s ,(- n 3)>+            <cons <card ,s ,(- n 4)>+             <nil>>>>>>+        <Straight-Flush>]+       [<cons <card _ $n>+         <cons <card _ ,n>+          <cons <card _ ,n>+            <cons <card _ ,n>+              <cons _+                <nil>>>>>>+        <Four-of-Kind>]+       [<cons <card _ $m>+         <cons <card _ ,m>+          <cons <card _ ,m>+           <cons <card _ $n>+            <cons <card _ ,n>+              <nil>>>>>>+        <Full-House>]+       [<cons <card $s _>+         <cons <card ,s _>+           <cons <card ,s _>+             <cons <card ,s _>+               <cons <card ,s _>+                 <nil>>>>>>+        <Flush>]+       [<cons <card _ $n>+         <cons <card _ ,(- n 1)>+          <cons <card _ ,(- n 2)>+           <cons <card _ ,(- n 3)>+            <cons <card _ ,(- n 4)>+             <nil>>>>>>+        <Straight>]+       [<cons <card _ $n>+         <cons <card _ ,n>+          <cons <card _ ,n>+           <cons _+            <cons _+             <nil>>>>>>+        <Three-of-Kind>]+       [<cons <card _ $m>+         <cons <card _ ,m>+          <cons <card _ $n>+            <cons <card _ ,n>+             <cons _+               <nil>>>>>>+        <Two-Pair>]+       [<cons <card _ $n>+         <cons <card _ ,n>+          <cons _+           <cons _+            <cons _+             <nil>>>>>>+        <One-Pair>]+       [<cons _+         <cons _+          <cons _+           <cons _+            <cons _+             <nil>>>>>>+        <Nothing>]})))++;;+;; Demonstration code+;;+(test (poker-hands {<Card <Club> 12>+                    <Card <Club> 10>+                    <Card <Club> 13>+                    <Card <Club> 1>+                    <Card <Club> 11>}))++(test (poker-hands {<Card <Diamond> 1>+                    <Card <Club> 2>+                    <Card <Club> 1>+                    <Card <Heart> 1>+                    <Card <Diamond> 2>}))++(test (poker-hands {<Card <Diamond> 4>+                    <Card <Club> 2>+                    <Card <Club> 5>+                    <Card <Heart> 1>+                    <Card <Diamond> 3>}))++(test (poker-hands {<Card <Diamond> 4>+                    <Card <Club> 10>+                    <Card <Club> 5>+                    <Card <Heart> 1>+                    <Card <Diamond> 3>}))+
+ sample/sequence.egi view
@@ -0,0 +1,32 @@+;;;+;;;+;;; Pattern-matching against sequence of natural numbers+;;;+;;;++; first 100 natural numbers+(test (take 100 nats))++; inifinite list of two-combinations of numbers+(define $pairs (match-all nats (list integer)+                 [<join _ (& <cons $m _> <join _ <cons $n _>>)>+                  [m n]]))++; test 'pairs'+(test (take 100 pairs))++; infinite list of pythagoras numbers+(define $pyths (map (lambda [$m $n] (+ (power m 2) (power n 2))) pairs))++; test 'pyths'+(test (take 100 pyths))++; function that enumerates all common elements between two lists+(define $commons+  (lambda [$xs $ys]+    (match-all [xs ys] [(multiset integer) (multiset integer)]+      [[<cons $c _> <cons ,c _>]+       c])))++; test 'commons'+(test (commons (take 100 primes) (take 300 pyths)))
+ sample/social-graph.egi view
@@ -0,0 +1,81 @@+;;;+;;;+;;; Social-graph Demonstration+;;;+;;;++;;+;; Matcher definition+;;+(define $user+  (matcher+    {[,$u []+      {[$tgt (match [u tgt] [user user]+               {[[<id $id> <id ,id>] {[]}]+                [_ {}]})]}]+     [<id $> [integer]+      {[<User $id _ _> {id}]}]+     [<name $> [string]+      {[<User _ $name _> {name}]}]+     [<description $> [string]+      {[<User _ _ $txt> {txt}]}]+     [$ [something]+      {[$tgt {tgt}]}]+     }))++(define $user-table (multiset user))++(define $follow+  (matcher+    {[,$f []+      {[$tgt (match [f tgt] [follow follow]+               {[[(& <from-id $fid> <to-id $tid>) (& <from-id ,fid> <to-id ,tid>)] {[]}]+                [_ {}]})]}]+     [<from-id $> [integer]+      {[<Follow $fid _> {fid}]}]+     [<to-id $> [integer]+      {[<Follow _ $tid> {tid}]}]+     [$ [something]+      {[$tgt {tgt}]}]+     }))++(define $follow-table (multiset follow))++;;+;; Demonstration code+;;+(define $user-data+  {<User 1 "Egison_Lang" "The Programming Language Egison.\nThe pattern-matching-oriented pure functional programming language.">+   <User 2 "RakutenRIT" "Rakuten Institute of Technology">+   <User 3 "Haskeller" "I love Haskell programming.">+   })++(define $follow-data+  {<Follow 1 2>+   <Follow 2 3>+   })++; Users whom "Egison_Lang" follows+(test (match-all [user-data follow-data user-data] [user-table follow-table user-table]+        [[<cons (& <name ,"Egison_Lang"> <id $uid>) _>+          <cons (& <from-id ,uid> <to-id $fid>) _>+          <cons (& <id ,fid> <name $name> <description $txt>) _>]+         <User fid name txt>]))++; Users who don't follow back "Egison_Lang"+(test (match-all [user-data follow-data user-data] [user-table follow-table user-table]+        [[<cons (& <name ,"Egison_Lang"> <id $uid>) _>+          <cons (& <from-id ,uid> <to-id $fid>)+           ^<cons (& <from-id ,fid> <to-id ,uid>)+             _>>+          <cons (& <id ,fid> <name $name> <description $txt>) _>]+         <User fid name txt>]))++; Users who have interested in "Haskell" in the followers of followers of "Egison_Lang"+(test (match-all [user-data follow-data user-data] [user-table follow-table user-table]+        [[<cons (& <name ,"Egison_Lang"> <id $uid>) _>+          <cons (& <from-id ,uid> <to-id $fid>)+           <cons (& <from-id ,fid> <to-id $ffid>)+            _>>+          <cons (& <id ,ffid> <description (& <join _ <join ,"Haskell" _>> $txt)> <name $name>) _>]+         <User ffid name txt>]))
+ sample/tree.egi view
@@ -0,0 +1,89 @@+;;;+;;;+;;; Tree demonstration+;;;+;;;++;;+;; Matcher definition+;;+(define $tree+  (lambda [$a $b]+    (matcher+      {[,$val []+        {[$tgt (match [val tgt] [(tree a b) (tree a b)]+                 {[[<lnode $x $ts> <lnode ,x ,ts>] {[]}]+                  [[_ _] {}]})]}]+       [<leaf $> b+        {[<Leaf $x> {x}]+         [_ {}]}]+       [<lnode $ $> [a (list (tree a b))] ; Node whose children are seen as a list.+        {[<Node $x $ts> {[x ts]}]+         [_ {}]}]+       [<mnode $ $> [a (multiset (tree a b))] ; Node whose children are seen as a multiset.+        {[<Node $x $ts> {[x ts]}]+         [_ {}]}]+       [<descendant $> [(tree a b)]+        {[$t (match-all t (tree a b)+               [(loop $i [1 _] <mnode _ <cons ... _>> $x) x])]}]+       [$ [something]+        {[$tgt {tgt}]}]+       })))++;;+;; Demonstration code+;;+(define $tree-data+  <Node "Programming language"+    {<Node "Pattern-matching oriented"+       {<Leaf "Egison">}>+     <Node "Functional language"+       {<Node "Strictly typed"+          {<Leaf "OCaml">+           <Leaf "Haskell">+           <Leaf "Curry">+           <Leaf "Coq">+           }>+        <Node "Dynamically typed"+          {<Leaf "Egison">+           <Leaf "Lisp">+           <Leaf "Scheme">+           <Leaf "Clojure">+           }>+        }>+     <Node "Logic programming"+       {<Leaf "Prolog">+        <Leaf "LiLFeS">+        <Leaf "Curry">+        }>+     <Node "Object oriented"+       {<Leaf "C++">+        <Leaf "Java">+        <Leaf "Ruby">+        <Leaf "Python">+        <Leaf "OCaml">+        }>+     }>)+++; All langauges+(test (unique/m string (match-all tree-data (tree string string)+                         [<descendant <leaf $x>> x])))+        +; All langauges that belongs to Functional language+(test (unique/m string (match-all tree-data (tree string string)+                         [<descendant <mnode ,"Functional language" <cons <descendant <leaf $x>> _>>> x])))+        +; All langauges that belongs more than two categories+(test (unique/m string (match-all tree-data (tree string string)+                         [<mnode _ <cons <descendant <leaf $x>>+                                         <cons <descendant <leaf ,x>>+                                               _>>>+                          x])))++; All categories that Egison belongs+(test (match-all tree-data (tree string string)+        [(loop $i [1 $n]+               <mnode $c_i <cons ... _>>+               <leaf ,"Egison">)+         c]))
+ sample/xml-test.egi view
@@ -0,0 +1,49 @@+(load "lib/tree/xml.egi")++(define $xml1+  <Node "top"+        {<Node "middle1" {<Leaf "bottom1" "text1">+                          <Leaf "bottom1" "text2">+                          <Leaf "bottom1" "text3">+                          <Node "bottom1" {<Leaf "bottom2" "text21">+                                           <Leaf "bottom2" "text100">+                                           <Leaf "bottom2" "text22">}>+                          }>+         <Node "middle2" {<Leaf "bottom3" "text31">+                          <Leaf "bottom3" "text32">+                          <Leaf "bottom3" "text33">+                          <Leaf "bottom3" "text31">+                          <Leaf "bottom3" "text35">+                          }>++         <Node "middle3" {<Leaf "bottom4" "text41">+                          <Leaf "bottom4"  "text42">+                          <Node "bottom4" {<Leaf "bottom2" "text51">+                                           <Leaf "bottom2" "text100">+                                           <Leaf "bottom2" "text53">}>+                          <Leaf "bottom4"  "text44">+                          <Leaf "bottom4"  "text53">+                          }>+         }>)+++;; List up all tags.+(test (match-all xml1 xml+        [<descendant <mnode $tag _>  _> [tag]]))+; {top middle1 middle2 middle3 bottom1 bottom4}++;; List up all nodes which has more than two same child nodes.+(test (match-all xml1 xml+        [<descendant <mnode $tag <cons $x <cons ,x _>>>>+         [tag x]]))+; {[middle2 <Leaf bottom3 text31>] [middle2 <Leaf bottom3 text31>]}++;; List up all nodes which has more than two same descendant nodes.+(test (match-all xml1 xml+        [<descendant+          <mnode $tag+           <cons <descendant $x>+            <cons <descendant ,x>+             _>>>>+         [tag x]]))+; {[middle2 <Leaf bottom3 text31>] [middle2 <Leaf bottom3 text31>] [top <Leaf bottom2 text100>] [top <Leaf bottom2 text100>]}
test/UnitTest.hs view
@@ -20,12 +20,12 @@  runTestCase :: FilePath -> Test runTestCase file = TestLabel file . TestCase $ do-  env <- primitiveEnv >>= loadLibraries+  env <- primitiveEnv >>= loadCoreLibraries   assertEgisonM $ do     exprs <- loadFile file     let (bindings, tests) = foldr collectDefsAndTests ([], []) exprs     env' <- recursiveBind env bindings-    forM_ tests $ evalExpr' env'+    forM_ tests $ evalExprDeep env'       where         assertEgisonM :: EgisonM a -> Assertion         assertEgisonM m = fromEgisonM m >>= assertString . either show (const "")